diff --git a/CHANGELOG.md b/CHANGELOG.md index f2d40e0efc8..ab94e3cbc55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,271 @@ +## [v23.12.00]( https://github.com/sofa-framework/sofa/tree/v23.12.00 ) + +[Full log](https://github.com/sofa-framework/sofa/compare/v23.06..v23.12) + +### Highlighted contributions +- [Mass] Remove DiagonalMass and replace with MeshMatrixMass (with lumping) [#3001](https://github.com/sofa-framework/sofa/pull/3001) +- [LinearAlgebra] Pull Insimo's CompressedRowSparseMatrix into the main branch [#3515](https://github.com/sofa-framework/sofa/pull/3515) +- [plugins] Add fetchable SoftRobots [#3882](https://github.com/sofa-framework/sofa/pull/3882) +- [Sofa.Simulation] First steps to remove the singleton Simulation [#3889](https://github.com/sofa-framework/sofa/pull/3889) +- [plugins] ADD external collisions plugins [#3890](https://github.com/sofa-framework/sofa/pull/3890) +- [LinearAlgebra] Implement CompressedRowSparseMatrixConstraint [#3894](https://github.com/sofa-framework/sofa/pull/3894) +- [Simulation.Core] Refactor DefaultAnimationLoop + multithreading [#3959](https://github.com/sofa-framework/sofa/pull/3959) +- [LinearSolver.Direct] Parallelization of H A^-1 H^T in SparseLDLSolver [#3986](https://github.com/sofa-framework/sofa/pull/3986) +- [LinearSystem] Optim: Only account for affected DoFs [#4001](https://github.com/sofa-framework/sofa/pull/4001) +- [GitHub] Action to check labels [#4079](https://github.com/sofa-framework/sofa/pull/4079) +- [MultiThreading] Introduce parallel CG [#4138](https://github.com/sofa-framework/sofa/pull/4138) +- [LinearSystem] Introduce constant sparsity matrix assembly [#4158](https://github.com/sofa-framework/sofa/pull/4158) +- [LinearSolver] Implement parallel inverse product for all linear solvers [#4255](https://github.com/sofa-framework/sofa/pull/4255) + + +### Breaking +- [Constraint.Lagrangian] Activate the export of lambda forces by default [#3857](https://github.com/sofa-framework/sofa/pull/3857) +- [all] Change variable name supportOnlySymmetricMatrix in MParams [#3861](https://github.com/sofa-framework/sofa/pull/3861) +- [all] Unify how Animation/Visual loops are handling their "targetNode" [#3945](https://github.com/sofa-framework/sofa/pull/3945) +- [MechanicalLoad] Implement buildStiffnessMatrix for PlaneForceField [#3972](https://github.com/sofa-framework/sofa/pull/3972) +- [AnimationLoop] Change the default constraint solver in FreeMotionAnimationLoop [#3994](https://github.com/sofa-framework/sofa/pull/3994) +- [Spring] Implement buildStiffnessMatrix in PolynomialRestShapeSpringsForceField [#4009](https://github.com/sofa-framework/sofa/pull/4009) +- [MechanicalLoad] Remove the data force in ConstantFF and solves circular dependency [#4019](https://github.com/sofa-framework/sofa/pull/4019) +- [all] Lifecycle v23.12 1/n [#4034](https://github.com/sofa-framework/sofa/pull/4034) +- [Core] Make doDrawVisual final [#4045](https://github.com/sofa-framework/sofa/pull/4045) +- [Visual] ADD a visualization flag and draw method for NarrowPhaseDetection [#4048](https://github.com/sofa-framework/sofa/pull/4048) +- [SolidMechanics.TensorMass] Implement buildStiffnessMatrix for TetrahedralTensorMassForceField [#4127](https://github.com/sofa-framework/sofa/pull/4127) +- [BatchGUI] Show progress bar [#4168](https://github.com/sofa-framework/sofa/pull/4168) +- [Constraint.Lagrangian.Solver] Another step to factorize both constraint solvers [#4213](https://github.com/sofa-framework/sofa/pull/4213) +- [all] Replace tinyxml by external tinyxml2 [#4240](https://github.com/sofa-framework/sofa/pull/4240) + + +### Improvements +- [all] Add namespaces in the factory and a python-like import mechanism [#2512](https://github.com/sofa-framework/sofa/pull/2512) +- [IO][Tests] Add basic test for the MeshSTLLoader [#2999](https://github.com/sofa-framework/sofa/pull/2999) +- [SofaCarving] Add an example written in python [#3457](https://github.com/sofa-framework/sofa/pull/3457) +- [MultiThreading] Implement domain decomposition for a lock-free parallelism [#3566](https://github.com/sofa-framework/sofa/pull/3566) +- [Components] Add functions to visualization of TetrahedronFemForceField [#3821](https://github.com/sofa-framework/sofa/pull/3821) +- [LinearAlgebra] Change access specifier for the method set [#3834](https://github.com/sofa-framework/sofa/pull/3834) +- [Mapping.NonLinear] Warns when non-symmetric matrix is produced [#3838](https://github.com/sofa-framework/sofa/pull/3838) +- [Spring] Limit spring force to some axis [#3849](https://github.com/sofa-framework/sofa/pull/3849) +- [Spring] Limit spring force to some axis [#3850](https://github.com/sofa-framework/sofa/pull/3850) +- [Constraint] Add tag to classify constraints [#3888](https://github.com/sofa-framework/sofa/pull/3888) +- [Spring] Rename RestShapeSpringsForceField to a more user-oriented name [#3903](https://github.com/sofa-framework/sofa/pull/3903) +- [Mapping.NonLinear] Implement buildGeometricStiffnessMatrix for DistanceFromTargetMapping + example [#3921](https://github.com/sofa-framework/sofa/pull/3921) +- [Config] Allow fast math mode for gcc/clang [#3922](https://github.com/sofa-framework/sofa/pull/3922) +- [all] Use NVI design pattern for drawVisual [#3931](https://github.com/sofa-framework/sofa/pull/3931) +- [all] Add DeprecatedData and RemovedData [#3934](https://github.com/sofa-framework/sofa/pull/3934) +- [Helper] add the experimental filesystem library for gcc-8 compilation [#3944](https://github.com/sofa-framework/sofa/pull/3944) +- [FEM.Elastic] Implement buildStiffnessMatrix in HexahedralFEMForceField [#3969](https://github.com/sofa-framework/sofa/pull/3969) +- [Spring] Implement buildStiffnessMatrix for SpringForceField [#3970](https://github.com/sofa-framework/sofa/pull/3970) +- [MechanicalLoad] Implement buildStiffnessMatrix for LinearForceField [#3973](https://github.com/sofa-framework/sofa/pull/3973) +- [Collision.Response.Contact] Implement buildStiffnessMatrix in PenalityContactForceField [#3974](https://github.com/sofa-framework/sofa/pull/3974) +- [FEM.Elastic] Implement buildStiffnessMatrix for TetrahedralCorotationalFEMForceField [#3981](https://github.com/sofa-framework/sofa/pull/3981) +- [LinearSystem.Direct] More details in the error message [#3985](https://github.com/sofa-framework/sofa/pull/3985) +- [FEM.Linear] Implement buildStiffnessMatrix and addKToMatrix for TriangularFEMForceField [#3991](https://github.com/sofa-framework/sofa/pull/3991) +- [Spring] Implement buildStiffnessMatrix for AngularSpringForceField [#3993](https://github.com/sofa-framework/sofa/pull/3993) +- [MechanicalLoad] Implement buildStiffnessMatrix for ConicalForceField [#3997](https://github.com/sofa-framework/sofa/pull/3997) +- [MechanicalLoad] Restore computation of derivatives in DiagonalVelocityDampingForceField [#3999](https://github.com/sofa-framework/sofa/pull/3999) +- [SofaCUDA] Implement buildStiffnessMatrix and buildDampingMatrix in TLED [#4000](https://github.com/sofa-framework/sofa/pull/4000) +- [MechanicalLoad] Implement buildStiffnessMatrix in EdgePressureForceField [#4004](https://github.com/sofa-framework/sofa/pull/4004) +- [MechanicalLoad] Implement buildStiffnessMatrix in EllipsoidForceField [#4005](https://github.com/sofa-framework/sofa/pull/4005) +- [Spring] Implement buildStiffnessMatrix in FastTriangularBendingSprings [#4006](https://github.com/sofa-framework/sofa/pull/4006) +- [MechanicalLoad] Implement buildStiffnessMatrix for OscillatingTorsionPressureForceField [#4007](https://github.com/sofa-framework/sofa/pull/4007) +- [SolidMechanics] Implement buildStiffnessMatrix for QuadBendingFEMForceField [#4015](https://github.com/sofa-framework/sofa/pull/4015) +- [MechanicalLoad] Implement buildStiffnessMatrix for QuadPressureForceField [#4018](https://github.com/sofa-framework/sofa/pull/4018) +- [FEM.Elastic] Add option to compute principal stress direction in TriangularFEMForceFieldOptim [#4027](https://github.com/sofa-framework/sofa/pull/4027) +- [Geometry] Add method isPointOnEdge in Edge structure [#4028](https://github.com/sofa-framework/sofa/pull/4028) +- [Geometry] Add method intersectionWithEdge in Edge structure [#4029](https://github.com/sofa-framework/sofa/pull/4029) +- [Geometry] Add methods getBarycentricCoordinates and isPointInTriangle in Triangle class [#4053](https://github.com/sofa-framework/sofa/pull/4053) +- [examples] Introduce falling beam example [#4055](https://github.com/sofa-framework/sofa/pull/4055) +- [all] Add dates for user deprecation classes RemovedData and DeprecatedData [#4059](https://github.com/sofa-framework/sofa/pull/4059) +- [LinearSolver.Direct] More details in error message [#4060](https://github.com/sofa-framework/sofa/pull/4060) +- [GitHub] Action to check PR titles [#4081](https://github.com/sofa-framework/sofa/pull/4081) +- [MechanicalLoad] Implement buildStiffnessMatrix in SurfacePressureForceField [#4097](https://github.com/sofa-framework/sofa/pull/4097) +- [MechanicalLoad] Implement buildStiffnessMatrix for SphereForceField [#4099](https://github.com/sofa-framework/sofa/pull/4099) +- [FEM.Elastic] Implement buildStiffnessMatrix for TriangularFEMForceFieldOptim [#4105](https://github.com/sofa-framework/sofa/pull/4105) +- [plugins] Add fetchable ShapeMatchingPlugin [#4106](https://github.com/sofa-framework/sofa/pull/4106) +- [Constraint.Lagrangian.Correction] Decrease the severity of not finding a file in PrecomputedConstraintCorrection [#4108](https://github.com/sofa-framework/sofa/pull/4108) +- [FEM.HyperElastic] Implement buildStiffnessMatrix for StandardTetrahedralFEMForceField [#4110](https://github.com/sofa-framework/sofa/pull/4110) +- [MechanicalLoad] Implement buildStiffnessMatrix for TorsionForceField [#4115](https://github.com/sofa-framework/sofa/pull/4115) +- [Mass] Add a callback on the lumping data in MMMass [#4128](https://github.com/sofa-framework/sofa/pull/4128) +- [Constraint.Lagrangian.Solver] GenericConstraintSolver: use given re-ordered list for unbuilt GS [#4132](https://github.com/sofa-framework/sofa/pull/4132) +- [Core] Store default value in a Data [#4133](https://github.com/sofa-framework/sofa/pull/4133) +- [all] Use SimulationInitDoneEvent instead of AnimateBeginEvent [#4160](https://github.com/sofa-framework/sofa/pull/4160) +- [GitHub] filter action if not on sofa-framework repository [#4171](https://github.com/sofa-framework/sofa/pull/4171) +- [LinearSystem] Assemble non-mapped and mapped matrices in parallel [#4172](https://github.com/sofa-framework/sofa/pull/4172) +- [Config] Integrate Tracy profiler [#4182](https://github.com/sofa-framework/sofa/pull/4182) +- [Config] CMake: Dont check for IPO at every configure step [#4191](https://github.com/sofa-framework/sofa/pull/4191) +- [Constraint.Lagrangian.Solver] GenericConstraintSolver: avoid repeated allocation in loops [#4195](https://github.com/sofa-framework/sofa/pull/4195) +- [LinearSolver.Direct] Better distribution of tasks among threads [#4220](https://github.com/sofa-framework/sofa/pull/4220) +- [all] Add the folder sofa-launcher to the resources component [#4245](https://github.com/sofa-framework/sofa/pull/4245) +- [MatrixAccumulator] adds 6x6 matrix handling [#4247](https://github.com/sofa-framework/sofa/pull/4247) +- [LinearAlgebra] Speedup accumulation on BTDMatrix [#4248](https://github.com/sofa-framework/sofa/pull/4248) +- [LinearAlgebra] Support 6x6 matrices accumulation in BaseMatrix [#4253](https://github.com/sofa-framework/sofa/pull/4253) +- [example] Speedup TorusFall with parallel inverse product [#4256](https://github.com/sofa-framework/sofa/pull/4256) +- [Helper] ADD option to cmake for advanced timer [#4259](https://github.com/sofa-framework/sofa/pull/4259) +- [LinearSystem] Speedup computation of Jacobian matrices [#4317](https://github.com/sofa-framework/sofa/pull/4317) +- [FEM.Elastic] Reference instead of a copy in TriangularFEMForceField [#4332](https://github.com/sofa-framework/sofa/pull/4332) +- [All] Add GIT_REF option for external plugins [#4448](https://github.com/sofa-framework/sofa/pull/4448) +- [Testing] Externalize (find_package() or fetch) googletest/gtest [#4471](https://github.com/sofa-framework/sofa/pull/4471) + + +### Bug Fixes +- [test] Fix unit test on RestShapeSpringsForceField [#3864](https://github.com/sofa-framework/sofa/pull/3864) +- [test] Fix failing unit test [#3876](https://github.com/sofa-framework/sofa/pull/3876) +- [Constraint.Lagrangian.Solver] LCPConstraintSolver: Fix when mu=0 (no friction) [#3905](https://github.com/sofa-framework/sofa/pull/3905) +- [applications] remove unused variable [#3920](https://github.com/sofa-framework/sofa/pull/3920) +- [Projective] Fix and test FixedPlaneConstraint [#3925](https://github.com/sofa-framework/sofa/pull/3925) +- [MechanicalLoad] Restore addKToMatrix and test SurfacePressureForceField [#3935](https://github.com/sofa-framework/sofa/pull/3935) +- [Core.Topology] Restore invalid ids in invalid containers [#3962](https://github.com/sofa-framework/sofa/pull/3962) +- [Sofa.Component] FIX default color for TetrahedronFEMForceField [#3971](https://github.com/sofa-framework/sofa/pull/3971) +- [image] Fix crash in case no parameters provided to TransferFunction [#3976](https://github.com/sofa-framework/sofa/pull/3976) +- [Mapping.NonLinear] Fix assert in RigidMapping [#3978](https://github.com/sofa-framework/sofa/pull/3978) +- [Diffusion] Fix buildStiffnessMatrix in TetrahedronDiffusionFEMForceField [#4012](https://github.com/sofa-framework/sofa/pull/4012) +- [Core] Fix drawing of Objects when hiding Visual Models [#4044](https://github.com/sofa-framework/sofa/pull/4044) +- [FEM.Elastic] Compute BBox in triangle FEM [#4061](https://github.com/sofa-framework/sofa/pull/4061) +- [FEM.Elastic] Fix typo in error message [#4062](https://github.com/sofa-framework/sofa/pull/4062) +- [LinearAlgebra] Fix matrix sizes when filtering [#4063](https://github.com/sofa-framework/sofa/pull/4063) +- [MechanicalLoad] Fix compilation further to new RemovedData constructor [#4094](https://github.com/sofa-framework/sofa/pull/4094) +- [MechanicalLoad] Fix plane force field buildStiffnessMatrix [#4098](https://github.com/sofa-framework/sofa/pull/4098) +- [GUI.Qt] Fix crash if filename is null [#4102](https://github.com/sofa-framework/sofa/pull/4102) +- [Tutorials] Update and fix oneTetrahedron tutorial [#4103](https://github.com/sofa-framework/sofa/pull/4103) +- [Helper] Fix wrong function called when writing jpg file [#4111](https://github.com/sofa-framework/sofa/pull/4111) +- [test] Make quaternion test deterministic and portable [#4126](https://github.com/sofa-framework/sofa/pull/4126) +- [Constraint.Lagrangian.Solver] Fix default value for computeConstraintForces Data [#4129](https://github.com/sofa-framework/sofa/pull/4129) +- [Sofa.GL] Fix doDrawVisual for OglLabel [#4142](https://github.com/sofa-framework/sofa/pull/4142) +- [SofaSphFluid] Fix: scenes warnings and failing examples [#4149](https://github.com/sofa-framework/sofa/pull/4149) +- [SofaSphFluid] Fix: internal draw method not restoring default parameters [#4150](https://github.com/sofa-framework/sofa/pull/4150) +- [Mass] Fix UniformMass vertexMass value should not be set to 0 if nbr of points reach 0 [#4151](https://github.com/sofa-framework/sofa/pull/4151) +- [Topology.Grid] Fix SparseGridTopology and SparseGridRamificationTopology crash at init if mesh file is not found [#4164](https://github.com/sofa-framework/sofa/pull/4164) +- [Topology] Rename Edge::pointBaryCoefs into Edge::getBarycentricCoordinates [#4165](https://github.com/sofa-framework/sofa/pull/4165) +- [LinearSolver.Direct] SparseLDL: Fix crash in addJMInvJtLocal [#4180](https://github.com/sofa-framework/sofa/pull/4180) +- [Helper] Fix warning in MeshTopologyLoader.cpp [#4181](https://github.com/sofa-framework/sofa/pull/4181) +- [examples] Fix warning of UncoupledCC in caduceus [#4187](https://github.com/sofa-framework/sofa/pull/4187) +- [LinearSystem] MatrixLinearSystem: add registration in the factory for BTDMatrix6 [#4189](https://github.com/sofa-framework/sofa/pull/4189) +- [SofaCarving] Fix warnings in SofaCarving_test due to use of deprecated methods [#4193](https://github.com/sofa-framework/sofa/pull/4193) +- [GUI.Qt] Fix libQGLViewer cmake install [#4198](https://github.com/sofa-framework/sofa/pull/4198) +- [Helper] Update ComponentChange for MechanicalMatrixMapper [#4235](https://github.com/sofa-framework/sofa/pull/4235) +- [LinearAlgebra] Robustify accesses to empty matrices [#4236](https://github.com/sofa-framework/sofa/pull/4236) +- [Topology] Check indices out-of-bound in TriangleSetTopologyContainer [#4242](https://github.com/sofa-framework/sofa/pull/4242) +- [github] Fix name of PR author in GitHub workflows [#4267](https://github.com/sofa-framework/sofa/pull/4267) +- [SofaCUDA] Dont use both version of cublas (legacy or v2) [#4274](https://github.com/sofa-framework/sofa/pull/4274) +- [Sofa.GUI.Qt] Add cmake module for QGLViewer [#4290](https://github.com/sofa-framework/sofa/pull/4290) +- [all] Fix warnings [#4291](https://github.com/sofa-framework/sofa/pull/4291) +- [LinearAlgera, Core] Fix linking with LTO on MacOS/Clang [#4293](https://github.com/sofa-framework/sofa/pull/4293) +- [MultiThreading] Avoid Static Initialization Order Fiasco [#4307](https://github.com/sofa-framework/sofa/pull/4307) +- [SofaCUDA] FIX compilation SofaCUDA along with SparseGrid with Cuda12 [#4319](https://github.com/sofa-framework/sofa/pull/4319) +- [SofaAssimp] Fix the FindAssimp.cmake [#4326](https://github.com/sofa-framework/sofa/pull/4326) +- [image] image_gui to compile with Qt6 [#4330](https://github.com/sofa-framework/sofa/pull/4330) +- [Haption] Partially fix the plugin [#4338](https://github.com/sofa-framework/sofa/pull/4338) +- [github] quick fix for GHD script [#4347](https://github.com/sofa-framework/sofa/pull/4347) +- [github] fix stale action [#4348](https://github.com/sofa-framework/sofa/pull/4348) +- [GUI] Fix compilation using QDocBrowser [#4354](https://github.com/sofa-framework/sofa/pull/4354) +- [VolumetricRendering] Fix the compilation [#4398](https://github.com/sofa-framework/sofa/pull/4398) +- [VolumetricRendering] Fix crashes in batch mode [#4436](https://github.com/sofa-framework/sofa/pull/4436) +- [LinearSolver.Direct] Fix metis dependency [#4450](https://github.com/sofa-framework/sofa/pull/4450) +- [Simulation.Common] Fix tinyXML2 install for windows [#4525](https://github.com/sofa-framework/sofa/pull/4525) +- [all] Install FindTinyXML2 [#4545](https://github.com/sofa-framework/sofa/pull/4545) +- [cmake] Remove error in Findcxxopt [#4554](https://github.com/sofa-framework/sofa/pull/4554) +- [GUI.qt] Set link to tinyxml2 to PRIVATE and fix config file [#4558](https://github.com/sofa-framework/sofa/pull/4558) +- [Config] Fix findcxxopt when version is not specified [#4564](https://github.com/sofa-framework/sofa/pull/4564) +- [Config] Fix Findmetis module when using config mode [#4570](https://github.com/sofa-framework/sofa/pull/4570) +- [all] Fix tinyxml2 dependency [#4574](https://github.com/sofa-framework/sofa/pull/4574) + + +### Cleaning +- [plugins] Remove fetching of SofaPython [#3855](https://github.com/sofa-framework/sofa/pull/3855) +- [Constraint.Lagrangian] Add messages when no compliance is given [#3858](https://github.com/sofa-framework/sofa/pull/3858) +- [all] include base class inl file [#3865](https://github.com/sofa-framework/sofa/pull/3865) +- [SofaCUDA] No longer use deprecated texture references in HexaTLED [#3868](https://github.com/sofa-framework/sofa/pull/3868) +- [SofaCUDA] Deprecated CudaTexture.h [#3869](https://github.com/sofa-framework/sofa/pull/3869) +- [Config] Fix cross-compilation for embedded external libs [#3870](https://github.com/sofa-framework/sofa/pull/3870) +- [all] Deprecate unused verbose data [#3871](https://github.com/sofa-framework/sofa/pull/3871) +- [contact] Add missing call to super init [#3884](https://github.com/sofa-framework/sofa/pull/3884) +- [examples] Fix unstable scene constantMomentum.scn [#3886](https://github.com/sofa-framework/sofa/pull/3886) +- [SolidMechanics] Use accessors & make geometrical data required in BFF [#3887](https://github.com/sofa-framework/sofa/pull/3887) +- [SofaCUDA] Replace deprecated vector types [#3902](https://github.com/sofa-framework/sofa/pull/3902) +- [Helper] Improve text message for users in ComponentChange [#3913](https://github.com/sofa-framework/sofa/pull/3913) +- [all] Minor clean of types [#3915](https://github.com/sofa-framework/sofa/pull/3915) +- [examples] Remove example for MechanicalMatrixMapper [#3919](https://github.com/sofa-framework/sofa/pull/3919) +- [MechanicalLoad] Replace doUpdateInternal by callback: ConstantFF [#3924](https://github.com/sofa-framework/sofa/pull/3924) +- [FEM.Elastic] Implement buildStiffnessMatrix for FastTetrahedralCorotationalForceField [#3929](https://github.com/sofa-framework/sofa/pull/3929) +- [all] Cosmetic: apply nested namespaces style [#3932](https://github.com/sofa-framework/sofa/pull/3932) +- [Helper] Properly deprecate an already deprecated function [#3933](https://github.com/sofa-framework/sofa/pull/3933) +- [all] Make local variables const [#3937](https://github.com/sofa-framework/sofa/pull/3937) +- [Tests] Properly remove exported files [#3942](https://github.com/sofa-framework/sofa/pull/3942) +- [all] Remove few lines of code that do nothing [#3946](https://github.com/sofa-framework/sofa/pull/3946) +- [all] Implement empty buildDampingMatrix [#3948](https://github.com/sofa-framework/sofa/pull/3948) +- [IO.Mesh] More debug info in the error message in MeshSTLLoader [#3949](https://github.com/sofa-framework/sofa/pull/3949) +- [Sofa.Simulation] Remove Node::bwdInit [#3954](https://github.com/sofa-framework/sofa/pull/3954) +- [Mapping/tests] Remove dependency on SceneCreator [#3955](https://github.com/sofa-framework/sofa/pull/3955) +- [Simulation.Core] Deprecate unused classes *VisitorScheduler [#3957](https://github.com/sofa-framework/sofa/pull/3957) +- [Helper.System] Introduce function append for paths [#3961](https://github.com/sofa-framework/sofa/pull/3961) +- [Project] Start dev phase v23.12 [#3963](https://github.com/sofa-framework/sofa/pull/3963) +- [all] Minor clean on indentation and warning [#3975](https://github.com/sofa-framework/sofa/pull/3975) +- [MechanicalLoad] Remove empty draw function in LinearForceField [#3979](https://github.com/sofa-framework/sofa/pull/3979) +- [tests] Restore commented unit tests [#3982](https://github.com/sofa-framework/sofa/pull/3982) +- [CHANGELOG] Update further to latest changes in v23.06 [#3998](https://github.com/sofa-framework/sofa/pull/3998) +- [Component] Follow changes from SOFA #3889 [#4013](https://github.com/sofa-framework/sofa/pull/4013) +- [LinearAlgebra] CompressedRowSparseMatrix: add virtual destructor [#4020](https://github.com/sofa-framework/sofa/pull/4020) +- [GuiQt] Remove some unactivated code [#4025](https://github.com/sofa-framework/sofa/pull/4025) +- [constraint] Update PrecomputedConstraintCorrection logs when loading compliance file [#4026](https://github.com/sofa-framework/sofa/pull/4026) +- [all] Lifecycle v23.12 2/n [#4040](https://github.com/sofa-framework/sofa/pull/4040) +- [GUI.Qt] Remove unused recorder feature [#4041](https://github.com/sofa-framework/sofa/pull/4041) +- [MechanicalLoad] Use prefix d_ in DiagonalVelocityDampingForceField [#4046](https://github.com/sofa-framework/sofa/pull/4046) +- [all] Lifecycle v23.12 3/n [#4056](https://github.com/sofa-framework/sofa/pull/4056) +- [all] Clean unused warnings in SOFA [#4057](https://github.com/sofa-framework/sofa/pull/4057) +- [all] Lifecycle v23.12 4/n [#4058](https://github.com/sofa-framework/sofa/pull/4058) +- [plugins] Fix OptionGroup deprecated constructor in image and SofaCUDA plugin [#4064](https://github.com/sofa-framework/sofa/pull/4064) +- [all] Update code regarding lifecycle in Topology.h [#4065](https://github.com/sofa-framework/sofa/pull/4065) +- [all] Fix warnings related to Vec and unused var [#4067](https://github.com/sofa-framework/sofa/pull/4067) +- [all] Remove some simple uses of bwdInit() [#4075](https://github.com/sofa-framework/sofa/pull/4075) +- [SofaMatrix] Remove CImgPlugin dependency [#4112](https://github.com/sofa-framework/sofa/pull/4112) +- [all] Replace deprecated wbloc function by its new function name [#4118](https://github.com/sofa-framework/sofa/pull/4118) +- [Core] VecId: set correct message for the deleted function holonomicC [#4120](https://github.com/sofa-framework/sofa/pull/4120) +- [IO.Mesh.Tests] Reduce number of logs by unactivating printlog [#4148](https://github.com/sofa-framework/sofa/pull/4148) +- [Constraint.Lagrangian.Solver] LCPConstraintSolver: remove useless computation if printLog is enabled [#4170](https://github.com/sofa-framework/sofa/pull/4170) +- [Scene] Eigen3-SVD.scn: disable printLog [#4184](https://github.com/sofa-framework/sofa/pull/4184) +- [Constraint.Lagrangian.Solver] Clean both constraint solvers [#4185](https://github.com/sofa-framework/sofa/pull/4185) +- [Topology.Container] Update and rename methods in EdgeSetGeometryAlgorithms to compute barycentric coordinates [#4190](https://github.com/sofa-framework/sofa/pull/4190) +- [Topology.Container] Remove method writeMSHfile in GeometryAlgorithms components [#4192](https://github.com/sofa-framework/sofa/pull/4192) +- [all] Fix mismatch on explicit template instantiations [#4210](https://github.com/sofa-framework/sofa/pull/4210) +- [SofaCUDA] Move cuda GUI dependent code [#4227](https://github.com/sofa-framework/sofa/pull/4227) +- [all] Forgotten scoped timers [#4237](https://github.com/sofa-framework/sofa/pull/4237) +- [all] Fix warnings [#4238](https://github.com/sofa-framework/sofa/pull/4238) +- [all] Remove TODO.md [#4244](https://github.com/sofa-framework/sofa/pull/4244) +- [Type, Helper] Remove unused __STL_MEMBER_TEMPLATES parts [#4251](https://github.com/sofa-framework/sofa/pull/4251) +- [GL] Remove deprecated (and incomplete) Color class [#4264](https://github.com/sofa-framework/sofa/pull/4264) +- [FEM, Mapping] dont mix type::fixed_array and type::Vec [#4269](https://github.com/sofa-framework/sofa/pull/4269) +- [all] Fix headeronly extlibs licenses [#4272](https://github.com/sofa-framework/sofa/pull/4272) +- [all] Externalize cxxopts [#4273](https://github.com/sofa-framework/sofa/pull/4273) +- [Topology.Mapping] SimpleTesselatedHexaTopologicalMapping: use correct type for Index [#4279](https://github.com/sofa-framework/sofa/pull/4279) +- [GUI.Qt] Minor single-line cleaning [#4308](https://github.com/sofa-framework/sofa/pull/4308) +- [Core] Minor clean of DefaultAnimationLoop [#4314](https://github.com/sofa-framework/sofa/pull/4314) +- [Collections] Remove reference to non-existing SofaSimulation [#4320](https://github.com/sofa-framework/sofa/pull/4320) +- [All] Changed default plugins [#4322](https://github.com/sofa-framework/sofa/pull/4322) +- [ODESolver.Backward] Convert double to SReal in NewmarkImplicitSolver [#4341](https://github.com/sofa-framework/sofa/pull/4341) +- [Sofa.Testing] Do not build Sofa.Testing if SOFA_BUILD_TESTS is OFF [#4459](https://github.com/sofa-framework/sofa/pull/4459) +- [Simulation.Common] Fix downstream project compilation with tinyXML2 [#4506](https://github.com/sofa-framework/sofa/pull/4506) + + +### Refactoring +- [Sofa.Core] minor refactoring for Data::read() to move into BaseData the reading code [#3278](https://github.com/sofa-framework/sofa/pull/3278) +- [all] Rename DefaultContactManager into CollisionResponse [#3891](https://github.com/sofa-framework/sofa/pull/3891) +- [FEM.Elastic] Minor refactor of buildStiffnessMatrix in TetrahedronFEMForceField [#3983](https://github.com/sofa-framework/sofa/pull/3983) +- [plugins] Remove PSL files, add ExternalProjectConfig and update CMakeLists [#4047](https://github.com/sofa-framework/sofa/pull/4047) +- Revert "[Sofa.Core] minor refactoring for Data::read() to move into BaseData the reading code" [#4068](https://github.com/sofa-framework/sofa/pull/4068) +- [MechanicalLoad] Implement buildStiffnessMatrix for TaitSurfacePressureForceField [#4116](https://github.com/sofa-framework/sofa/pull/4116) +- [Constraint.Lagrangian.Solver] Unify lists of constraint corrections into a MultiLink [#4117](https://github.com/sofa-framework/sofa/pull/4117) +- [Constraint.Projective] Implement applyConstraint in LinearMovementConstraint [#4144](https://github.com/sofa-framework/sofa/pull/4144) +- [all] Generalize the usage of ScopedAdvancedTimer [#4177](https://github.com/sofa-framework/sofa/pull/4177) +- [all] Replace ScopedAdvancedTimers by macros [#4203](https://github.com/sofa-framework/sofa/pull/4203) +- [LinearSolver] Remove CSparse-based linear solvers [#4258](https://github.com/sofa-framework/sofa/pull/4258) +- [Common] Add message to make the fetch mechanism less hidden [#4310](https://github.com/sofa-framework/sofa/pull/4310) +- [Simulation.Core] Deprecate LocalStorage feature [#4327](https://github.com/sofa-framework/sofa/pull/4327) + + + + ## [v23.06.00]( https://github.com/sofa-framework/sofa/tree/v23.06.00 ) [Full log]( https://github.com/sofa-framework/sofa/compare/v22.12..v23.06 ) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad2fea6d3d7..2940cb95fa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ include(CMakeDependentOption) # Manually define VERSION set(Sofa_VERSION_MAJOR 23) set(Sofa_VERSION_MINOR 12) -set(Sofa_VERSION_PATCH 99) +set(Sofa_VERSION_PATCH 00) set(Sofa_VERSION ${Sofa_VERSION_MAJOR}.${Sofa_VERSION_MINOR}.${Sofa_VERSION_PATCH}) set(SOFA_VERSION_STR "\"${Sofa_VERSION}\"") @@ -37,7 +37,7 @@ option(SOFA_BUILD_RELEASE_PACKAGE "Run package specific configure" OFF) # Option to allow some dependencies such as cxxopts to be fetched by cmake if # the package is not found option(SOFA_ALLOW_FETCH_DEPENDENCIES "Allow compatible dependencies to be fetched if the package is not found by cmake. - List of dependencies that can be fetched: cxxopts" ON) + List of dependencies that can be fetched: cxxopts, gtest, metis, CImg" ON) # Option to accelerate the compilation # see https://cmake.org/cmake/help/v3.16/command/target_precompile_headers.html @@ -91,6 +91,7 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/FindEigen3.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/macdeployqt.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/windeployqt.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/FindTinyXML2.cmake" DESTINATION lib/cmake/Modules COMPONENT headers ) diff --git a/Sofa/Component/Constraint/Projective/tests/FixedPlaneConstraint_test.cpp b/Sofa/Component/Constraint/Projective/tests/FixedPlaneConstraint_test.cpp index 5ed1c9ca855..b040bfced84 100644 --- a/Sofa/Component/Constraint/Projective/tests/FixedPlaneConstraint_test.cpp +++ b/Sofa/Component/Constraint/Projective/tests/FixedPlaneConstraint_test.cpp @@ -67,7 +67,7 @@ struct FixedPlaneConstraint_test : public BaseSimulationTest /// Scene initialization sofa::simulation::Simulation* simulation; - sofa::simulation::setSimulation(simulation = new sofa::simulation::graph::DAGSimulation()); + simulation = sofa::simulation::getSimulation(); simulation::Node::SPtr root = simulation->createNewGraph("root"); root->setGravity( type::Vec3(0,0,0) ); diff --git a/Sofa/Component/IO/Mesh/CMakeLists.txt b/Sofa/Component/IO/Mesh/CMakeLists.txt index 0f48feedef6..89d8e732bcf 100644 --- a/Sofa/Component/IO/Mesh/CMakeLists.txt +++ b/Sofa/Component/IO/Mesh/CMakeLists.txt @@ -52,13 +52,13 @@ set(SOURCE_FILES ${SOFACOMPONENTIOMESH_SOURCE_DIR}/STLExporter.cpp ) -sofa_find_package(TinyXML REQUIRED) # BaseVTKReader +sofa_find_package(TinyXML2 REQUIRED) # BaseVTKReader sofa_find_package(ZLIB REQUIRED) # BlenderExporter sofa_find_package(Sofa.Simulation.Core REQUIRED) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${WRAPPER_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Simulation.Core) -target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml) +target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml2::tinyxml2) target_link_libraries(${PROJECT_NAME} PUBLIC ZLIB::ZLIB) if(CMAKE_SYSTEM_NAME STREQUAL Windows) sofa_install_libraries(TARGETS ZLIB::ZLIB) diff --git a/Sofa/Component/IO/Mesh/src/sofa/component/io/mesh/MeshVTKLoader.cpp b/Sofa/Component/IO/Mesh/src/sofa/component/io/mesh/MeshVTKLoader.cpp index 326c589f726..7a79d41ed96 100644 --- a/Sofa/Component/IO/Mesh/src/sofa/component/io/mesh/MeshVTKLoader.cpp +++ b/Sofa/Component/IO/Mesh/src/sofa/component/io/mesh/MeshVTKLoader.cpp @@ -34,12 +34,13 @@ using sofa::component::io::mesh::BaseVTKReader ; /// This is needed for template specialization. #include -#include +#include //XML VTK Loader #define checkError(A) if (!A) { return false; } #define checkErrorPtr(A) if (!A) { return nullptr; } #define checkErrorMsg(A, B) if (!A) { msg_error() << B << "\n" ; return false; } +#define checkErrorMsgAuto(A) if(A != tinyxml2::XML_SUCCESS) { msg_error() << "TinyXML error message : " << tinyxml2::XMLDocument::ErrorIDToName(A) << "\n" ; return false; } namespace sofa::component::io::mesh { @@ -69,15 +70,15 @@ class XMLVTKReader : public BaseVTKReader public: bool readFile(const char* filename) override; protected: - bool loadUnstructuredGrid(TiXmlHandle datasetFormatHandle); - bool loadPolydata(TiXmlHandle datasetFormatHandle); - bool loadRectilinearGrid(TiXmlHandle datasetFormatHandle); - bool loadStructuredGrid(TiXmlHandle datasetFormatHandle); - bool loadStructuredPoints(TiXmlHandle datasetFormatHandle); - bool loadImageData(TiXmlHandle datasetFormatHandle); - BaseVTKDataIO* loadDataArray(TiXmlElement* dataArrayElement, int size, string type); - BaseVTKDataIO* loadDataArray(TiXmlElement* dataArrayElement, int size); - BaseVTKDataIO* loadDataArray(TiXmlElement* dataArrayElement); + bool loadUnstructuredGrid(tinyxml2::XMLHandle datasetFormatHandle); + bool loadPolydata(tinyxml2::XMLHandle datasetFormatHandle); + bool loadRectilinearGrid(tinyxml2::XMLHandle datasetFormatHandle); + bool loadStructuredGrid(tinyxml2::XMLHandle datasetFormatHandle); + bool loadStructuredPoints(tinyxml2::XMLHandle datasetFormatHandle); + bool loadImageData(tinyxml2::XMLHandle datasetFormatHandle); + BaseVTKDataIO* loadDataArray(tinyxml2::XMLElement* dataArrayElement, int size, string type); + BaseVTKDataIO* loadDataArray(tinyxml2::XMLElement* dataArrayElement, int size); + BaseVTKDataIO* loadDataArray(tinyxml2::XMLElement* dataArrayElement); }; //////////////////////////////////////////////////////////////////////////////////////////// @@ -950,19 +951,19 @@ bool LegacyVTKReader::readFile(const char* filename) bool XMLVTKReader::readFile(const char* filename) { - TiXmlDocument vtkDoc(filename); + tinyxml2::XMLDocument vtkDoc(true,tinyxml2::COLLAPSE_WHITESPACE); //quick check - checkErrorMsg(vtkDoc.LoadFile(), "Unknown error while loading VTK Xml doc"); + checkErrorMsgAuto(vtkDoc.LoadFile(filename)) - const TiXmlHandle hVTKDoc(&vtkDoc); - TiXmlElement* pElem; - TiXmlHandle hVTKDocRoot(nullptr); + tinyxml2::XMLHandle hVTKDoc(&vtkDoc); + tinyxml2::XMLElement* pElem; + tinyxml2::XMLHandle hVTKDocRoot(nullptr); //block VTKFile pElem = hVTKDoc.FirstChildElement().ToElement(); checkErrorMsg(pElem, "VTKFile Node not found"); - hVTKDocRoot = TiXmlHandle(pElem); + hVTKDocRoot = tinyxml2::XMLHandle(pElem); //Endianness const char* endiannessStrTemp = pElem->Attribute("byte_order"); @@ -1003,7 +1004,7 @@ bool XMLVTKReader::readFile(const char* filename) checkErrorMsg(false, "Dataset format " << datasetFormatStr << " not recognized"); } - const TiXmlHandle datasetFormatHandle = TiXmlHandle(hVTKDocRoot.FirstChild( datasetFormatStr.c_str() ).ToElement()); + const tinyxml2::XMLHandle datasetFormatHandle = tinyxml2::XMLHandle(hVTKDocRoot.FirstChildElement( datasetFormatStr.c_str() )); bool stateLoading = false; switch (datasetFormat) @@ -1035,17 +1036,17 @@ bool XMLVTKReader::readFile(const char* filename) return true; } -BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(TiXmlElement* dataArrayElement) +BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(tinyxml2::XMLElement* dataArrayElement) { return loadDataArray(dataArrayElement, 0); } -BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(TiXmlElement* dataArrayElement, int size) +BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(tinyxml2::XMLElement* dataArrayElement, int size) { return loadDataArray(dataArrayElement, size, ""); } -BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(TiXmlElement* dataArrayElement, int size, string type) +BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(tinyxml2::XMLElement* dataArrayElement, int size, string type) { //Type const char* typeStrTemp; @@ -1085,7 +1086,7 @@ BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(TiXmlElement* dataArra //NumberOfComponents int numberOfComponents; - if (dataArrayElement->QueryIntAttribute("NumberOfComponents", &numberOfComponents) != TIXML_SUCCESS) + if (dataArrayElement->QueryIntAttribute("NumberOfComponents", &numberOfComponents) != tinyxml2::XML_SUCCESS) { numberOfComponents = 1; } @@ -1124,9 +1125,9 @@ BaseVTKReader::BaseVTKDataIO* XMLVTKReader::loadDataArray(TiXmlElement* dataArra return d; } -bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) +bool XMLVTKReader::loadUnstructuredGrid(tinyxml2::XMLHandle datasetFormatHandle) { - TiXmlElement* pieceElem = datasetFormatHandle.FirstChild( "Piece" ).ToElement(); + tinyxml2::XMLElement* pieceElem = datasetFormatHandle.FirstChildElement( "Piece" ).ToElement(); checkError(pieceElem); for( ; pieceElem; pieceElem = pieceElem->NextSiblingElement()) @@ -1134,9 +1135,9 @@ bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) pieceElem->QueryIntAttribute("NumberOfPoints", &numberOfPoints); pieceElem->QueryIntAttribute("NumberOfCells", &numberOfCells); - TiXmlNode* dataArrayNode; - TiXmlElement* dataArrayElement; - TiXmlNode* node = pieceElem->FirstChild(); + tinyxml2::XMLNode* dataArrayNode; + tinyxml2::XMLElement* dataArrayElement; + tinyxml2::XMLNode* node = pieceElem->FirstChild(); for ( ; node ; node = node->NextSibling()) { @@ -1145,7 +1146,7 @@ bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) if (currentNodeName.compare("Points") == 0) { /* Points */ - dataArrayNode = node->FirstChild("DataArray"); + dataArrayNode = node->FirstChildElement("DataArray"); checkError(dataArrayNode); dataArrayElement = dataArrayNode->ToElement(); checkError(dataArrayElement); @@ -1157,8 +1158,8 @@ bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) if (currentNodeName.compare("Cells") == 0) { /* Cells */ - dataArrayNode = node->FirstChild("DataArray"); - for ( ; dataArrayNode; dataArrayNode = dataArrayNode->NextSibling( "DataArray")) + dataArrayNode = node->FirstChildElement("DataArray"); + for ( ; dataArrayNode; dataArrayNode = dataArrayNode->NextSiblingElement( "DataArray")) { dataArrayElement = dataArrayNode->ToElement(); checkError(dataArrayElement); @@ -1187,8 +1188,8 @@ bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) if (currentNodeName.compare("PointData") == 0) { - dataArrayNode = node->FirstChild("DataArray"); - for ( ; dataArrayNode; dataArrayNode = dataArrayNode->NextSibling( "DataArray")) + dataArrayNode = node->FirstChildElement("DataArray"); + for ( ; dataArrayNode; dataArrayNode = dataArrayNode->NextSiblingElement( "DataArray")) { dataArrayElement = dataArrayNode->ToElement(); checkError(dataArrayElement); @@ -1203,8 +1204,8 @@ bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) } if (currentNodeName.compare("CellData") == 0) { - dataArrayNode = node->FirstChild("DataArray"); - for ( ; dataArrayNode; dataArrayNode = dataArrayNode->NextSibling( "DataArray")) + dataArrayNode = node->FirstChildElement("DataArray"); + for ( ; dataArrayNode; dataArrayNode = dataArrayNode->NextSiblingElement( "DataArray")) { dataArrayElement = dataArrayNode->ToElement(); checkError(dataArrayElement); @@ -1221,35 +1222,35 @@ bool XMLVTKReader::loadUnstructuredGrid(TiXmlHandle datasetFormatHandle) return true; } -bool XMLVTKReader::loadPolydata(TiXmlHandle datasetFormatHandle) +bool XMLVTKReader::loadPolydata(tinyxml2::XMLHandle datasetFormatHandle) { SOFA_UNUSED(datasetFormatHandle); msg_error() << "Polydata dataset not implemented yet" ; return false; } -bool XMLVTKReader::loadRectilinearGrid(TiXmlHandle datasetFormatHandle) +bool XMLVTKReader::loadRectilinearGrid(tinyxml2::XMLHandle datasetFormatHandle) { SOFA_UNUSED(datasetFormatHandle); msg_error() << "RectilinearGrid dataset not implemented yet" ; return false; } -bool XMLVTKReader::loadStructuredGrid(TiXmlHandle datasetFormatHandle) +bool XMLVTKReader::loadStructuredGrid(tinyxml2::XMLHandle datasetFormatHandle) { SOFA_UNUSED(datasetFormatHandle); msg_error() << "StructuredGrid dataset not implemented yet" ; return false; } -bool XMLVTKReader::loadStructuredPoints(TiXmlHandle datasetFormatHandle) +bool XMLVTKReader::loadStructuredPoints(tinyxml2::XMLHandle datasetFormatHandle) { SOFA_UNUSED(datasetFormatHandle); msg_error() << "StructuredPoints dataset not implemented yet" ; return false; } -bool XMLVTKReader::loadImageData(TiXmlHandle datasetFormatHandle) +bool XMLVTKReader::loadImageData(tinyxml2::XMLHandle datasetFormatHandle) { SOFA_UNUSED(datasetFormatHandle); msg_error() << "ImageData dataset not implemented yet" ; diff --git a/Sofa/Component/LinearSolver/Direct/CMakeLists.txt b/Sofa/Component/LinearSolver/Direct/CMakeLists.txt index 51fa093de06..9f09a537c30 100644 --- a/Sofa/Component/LinearSolver/Direct/CMakeLists.txt +++ b/Sofa/Component/LinearSolver/Direct/CMakeLists.txt @@ -55,12 +55,19 @@ set(SOURCE_FILES ${SOFACOMPONENTLINEARSOLVERDIRECT_SOURCE_DIR}/TypedMatrixLinearSystem[BTDMatrix].cpp ) -sofa_find_package(metis QUIET) # Unix users can have an installed version of metis -if(NOT metis_FOUND) - message(STATUS "${PROJECT_NAME}: using built-in metis library") - option(METIS-GKLIB_GKRAND "enable GKRAND support" ON) #GKRAND support allows the portability of random number generation across different architectures - add_subdirectory(extlibs/metis-5.1.0) +find_package(metis 5.1.0 EXACT QUIET) +if(NOT metis_FOUND AND SOFA_ALLOW_FETCH_DEPENDENCIES) + message("Sofa.Component.LinearSolver.Direct: DEPENDENCY metis NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is ON, fetching metis...") + include(FetchContent) + FetchContent_Declare(metis + GIT_REPOSITORY https://github.com/sofa-framework/METIS + GIT_TAG v5.1.0-ModernInstall + ) + FetchContent_MakeAvailable(metis) +elseif (NOT metis_FOUND) + message(FATAL_ERROR "Sofa.Component.LinearSolver.Direct: DEPENDENCY metis NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is OFF and thus cannot be fetched. Install metis (version=5.1.0), or enable SOFA_ALLOW_FETCH_DEPENDENCIES to fix this issue.") endif() + sofa_set_01(SOFA_COMPONENT_LINEARSOLVER_DIRECT_HAVE_METIS VALUE TRUE) # make sure you have threads for AsyncSparseLDLSolver @@ -70,8 +77,9 @@ sofa_find_package(Sofa.Simulation.Core REQUIRED) sofa_find_package(Sofa.Component.LinearSolver.Iterative REQUIRED) # Only for MatrixLinearSolver which will move to core add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${WRAPPER_FILES}) + target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Simulation.Core Sofa.Component.LinearSolver.Iterative) -target_link_libraries(${PROJECT_NAME} PUBLIC metis) +target_link_libraries(${PROJECT_NAME} PRIVATE metis) target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads) sofa_create_package_with_targets( diff --git a/Sofa/Component/LinearSolver/Direct/Sofa.Component.LinearSolver.DirectConfig.cmake.in b/Sofa/Component/LinearSolver/Direct/Sofa.Component.LinearSolver.DirectConfig.cmake.in index 4025df0d43e..ba84a7fb0fb 100644 --- a/Sofa/Component/LinearSolver/Direct/Sofa.Component.LinearSolver.DirectConfig.cmake.in +++ b/Sofa/Component/LinearSolver/Direct/Sofa.Component.LinearSolver.DirectConfig.cmake.in @@ -9,10 +9,6 @@ find_package(Threads QUIET REQUIRED) set(SOFA_COMPONENT_LINEARSOLVER_DIRECT_HAVE_METIS @SOFA_COMPONENT_LINEARSOLVER_DIRECT_HAVE_METIS@) -if(SOFA_COMPONENT_LINEARSOLVER_DIRECT_HAVE_METIS) - find_package(Metis QUIET REQUIRED HINTS "${CMAKE_CURRENT_LIST_DIR}/..") -endif() - if(NOT TARGET @PROJECT_NAME@) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") endif() diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/CMakeLists.txt b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/CMakeLists.txt deleted file mode 100644 index 0b3bf6e9b9e..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -cmake_minimum_required(VERSION 3.12) -project(metis) - -unset(GKLIB_PATH CACHE) -get_filename_component(GKLIB_PATH "GKlib" ABSOLUTE) -include(GKlib/GKlibSystem.cmake) - -file(GLOB metis_sources libmetis/*.c libmetis/*.h include/*.h) - -# The code must be relocatable if we want to link a shared library against it. -if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xGNU" OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang") - add_compile_options(-fPIC) -endif() - -add_library(${PROJECT_NAME} STATIC ${metis_sources} ${GKlib_sources}) -target_include_directories(${PROJECT_NAME} PUBLIC "$") -target_include_directories(${PROJECT_NAME} PUBLIC "$") - -# Disable warnings coming from the metis library -target_compile_options(${PROJECT_NAME} PRIVATE - $<$,$,$>: - -w> - $<$: - /w>) - -if(UNIX) - target_link_libraries(${PROJECT_NAME} m) -endif() - -if(WIN32) - # remove warnings about deprecation (CRT,etc) - target_compile_options(${PROJECT_NAME} PRIVATE "/wd4996") -endif() - -sofa_create_package_with_targets( - PACKAGE_NAME Metis - PACKAGE_VERSION 5.1.0 - TARGETS metis AUTO_SET_TARGET_PROPERTIES - INCLUDE_SOURCE_DIR "include" - INCLUDE_INSTALL_DIR "extlibs/Metis" - ) diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/GKlib.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/GKlib.h deleted file mode 100644 index 492c90f2e84..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/GKlib.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * GKlib.h - * - * George's library of most frequently used routines - * - * $Id: GKlib.h 13005 2012-10-23 22:34:36Z karypis $ - * - */ - -#ifndef _GKLIB_H_ -#define _GKLIB_H_ 1 - -#define GKMSPACE - -#if defined(_MSC_VER) -#define __MSC__ -#endif -#if defined(__ICC) -#define __ICC__ -#endif - - -#include "gk_arch.h" /*!< This should be here, prior to the includes */ - - -/************************************************************************* -* Header file inclusion section -**************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__WITHPCRE__) - #include -#else - #if defined(USE_GKREGEX) - #include "gkregex.h" - #else - #include - #endif /* defined(USE_GKREGEX) */ -#endif /* defined(__WITHPCRE__) */ - - - -#if defined(__OPENMP__) -#include -#endif - - - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - - -#endif /* GKlib.h */ - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/GKlibSystem.cmake b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/GKlibSystem.cmake deleted file mode 100644 index 4835cd50e58..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/GKlibSystem.cmake +++ /dev/null @@ -1,138 +0,0 @@ -# Helper modules. -include(CheckFunctionExists) -include(CheckIncludeFile) - -# Setup options. -option(METIS-GKLIB_GDB "enable use of GDB" OFF) -mark_as_advanced(METIS-GKLIB_GDB) -option(METIS-GKLIB_ASSERT "turn asserts on" OFF) -mark_as_advanced(METIS-GKLIB_ASSERT) -option(METIS-GKLIB_ASSERT2 "additional assertions" OFF) -mark_as_advanced(METIS-GKLIB_ASSERT2) -option(METIS-GKLIB_DEBUG "add debugging support" OFF) -mark_as_advanced(METIS-GKLIB_DEBUG) -option(METIS-GKLIB_GPROF "add gprof support" OFF) -mark_as_advanced(METIS-GKLIB_GPROF) -option(METIS-GKLIB_OPENMP "enable OpenMP support" OFF) -mark_as_advanced(METIS-GKLIB_OPENMP) -option(METIS-GKLIB_PCRE "enable PCRE support" OFF) -mark_as_advanced(METIS-GKLIB_PCRE) -option(METIS-GKLIB_GKREGEX "enable GKREGEX support" OFF) -mark_as_advanced(METIS-GKLIB_GKREGEX) -option(METIS-GKLIB_GKRAND "enable GKRAND support. GKRAND support allows the portability of random number generation accross different architectures" ON) -mark_as_advanced(METIS-GKLIB_GKRAND) - -# Add compiler flags. -if(MSVC) - set(GKlib_COPTS "/Ox") - set(GKlib_COPTIONS "-DWIN32 -DMSC -D_CRT_SECURE_NO_DEPRECATE -DUSE_GKREGEX") -elseif(MINGW) - set(GKlib_COPTS "-DUSE_GKREGEX") -else() - set(GKlib_COPTS "-O3") - set(GKlib_COPTIONS "-DLINUX -D_FILE_OFFSET_BITS=64") -endif(MSVC) -if(CYGWIN) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DCYGWIN") -endif(CYGWIN) -if(CMAKE_COMPILER_IS_GNUCC) -# GCC opts. - set(GKlib_COPTIONS "${GKlib_COPTIONS} -std=c99 -fno-strict-aliasing") - if(NOT MINGW) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -fPIC") - endif(NOT MINGW) -# GCC warnings. - set(GKlib_COPTIONS "${GKlib_COPTIONS} -Wall -pedantic -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unknown-pragmas") -elseif(${CMAKE_C_COMPILER_ID} MATCHES "Sun") -# Sun insists on -xc99. - set(GKlib_COPTIONS "${GKlib_COPTIONS} -xc99") -endif(CMAKE_COMPILER_IS_GNUCC) - -# Find OpenMP if it is requested. -if(METIS-GKLIB_OPENMP) - include(FindOpenMP) - if(OPENMP_FOUND) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__OPENMP__ ${OpenMP_C_FLAGS}") - else() - message(WARNING "OpenMP was requested but support was not found") - endif(OPENMP_FOUND) -endif(METIS-GKLIB_OPENMP) - - -# Add various definitions. -if(METIS-GKLIB_GDB) - set(GKlib_COPTS "${GKlib_COPTS} -g") - set(GKlib_COPTIONS "${GKlib_COPTIONS} -Werror") -endif(METIS-GKLIB_GDB) - - -if(METIS-GKLIB_DEBUG) - set(GKlib_COPTS "-g") - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DDEBUG") -endif(METIS-GKLIB_DEBUG) - -if(METIS-GKLIB_GPROF) - set(GKlib_COPTS "-pg") -endif(METIS-GKLIB_GPROF) - -if(NOT METIS-GKLIB_ASSERT) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DNDEBUG") -endif(NOT METIS-GKLIB_ASSERT) - -if(NOT METIS-GKLIB_ASSERT2) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DNDEBUG2") -endif(NOT METIS-GKLIB_ASSERT2) - - -# Add various options -if(METIS-GKLIB_PCRE) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__WITHPCRE__") -endif(METIS-GKLIB_PCRE) - -if(METIS-GKLIB_GKREGEX) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DUSE_GKREGEX") -endif(METIS-GKLIB_GKREGEX) - -if(METIS-GKLIB_GKRAND) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DUSE_GKRAND") -endif(METIS-GKLIB_GKRAND) - - -# Check for features. -check_include_file(execinfo.h HAVE_EXECINFO_H) -if(HAVE_EXECINFO_H) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DHAVE_EXECINFO_H") -endif(HAVE_EXECINFO_H) - -check_function_exists(getline HAVE_GETLINE) -if(HAVE_GETLINE) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -DHAVE_GETLINE") -endif(HAVE_GETLINE) - - -# Custom check for TLS. -if(MSVC) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__thread=__declspec(thread)") -else() - # This if checks if that value is cached or not. - if("${HAVE_THREADLOCALSTORAGE}" MATCHES "^${HAVE_THREADLOCALSTORAGE}$") - try_compile(HAVE_THREADLOCALSTORAGE - ${CMAKE_BINARY_DIR} - ${GKLIB_PATH}/conf/check_thread_storage.c) - # if(HAVE_THREADLOCALSTORAGE) - # message(STATUS "checking for thread-local storage - found") - # else() - # message(STATUS "checking for thread-local storage - not found") - # endif() - endif() - if(NOT HAVE_THREADLOCALSTORAGE) - set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__thread=") - endif() -endif() - -# Finally set the official C flags. -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GKlib_COPTIONS} ${GKlib_COPTS}") - -# Find GKlib sources. -file(GLOB GKlib_sources ${GKLIB_PATH}/*.c) -file(GLOB GKlib_includes ${GKLIB_PATH}/*.h) diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/b64.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/b64.c deleted file mode 100644 index afacd68a1e1..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/b64.c +++ /dev/null @@ -1,95 +0,0 @@ -/*! -\file b64.c -\brief This file contains some simple 8bit-to-6bit encoding/deconding routines - -Most of these routines are outdated and should be converted using glibc's equivalent -routines. - -\date Started 2/22/05 -\author George -\version\verbatim $Id: b64.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim - -\verbatim -$Copyright$ -$License$ -\endverbatim - -*/ - - -#include "GKlib.h" - -#define B64OFFSET 48 /* This is the '0' number */ - - -/****************************************************************************** -* Encode 3 '8-bit' binary bytes as 4 '6-bit' characters -*******************************************************************************/ -void encodeblock(unsigned char *in, unsigned char *out) -{ - out[0] = (in[0] >> 2); - out[1] = (((in[0] & 0x03) << 4) | (in[1] >> 4)); - out[2] = (((in[1] & 0x0f) << 2) | (in[2] >> 6)); - out[3] = (in[2] & 0x3f); - - out[0] += B64OFFSET; - out[1] += B64OFFSET; - out[2] += B64OFFSET; - out[3] += B64OFFSET; - -// printf("%c %c %c %c %2x %2x %2x %2x %2x %2x %2x\n", out[0], out[1], out[2], out[3], out[0], out[1], out[2], out[3], in[0], in[1], in[2]); -} - -/****************************************************************************** -* Decode 4 '6-bit' characters into 3 '8-bit' binary bytes -*******************************************************************************/ -void decodeblock(unsigned char *in, unsigned char *out) -{ - in[0] -= B64OFFSET; - in[1] -= B64OFFSET; - in[2] -= B64OFFSET; - in[3] -= B64OFFSET; - - out[0] = (in[0] << 2 | in[1] >> 4); - out[1] = (in[1] << 4 | in[2] >> 2); - out[2] = (in[2] << 6 | in[3]); -} - - -/****************************************************************************** -* This function encodes an input array of bytes into a base64 encoding. Memory -* for the output array is assumed to have been allocated by the calling program -* and be sufficiently large. The output string is NULL terminated. -*******************************************************************************/ -void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer) -{ - int i, j; - - if (nbytes%3 != 0) - gk_errexit(SIGERR, "GKEncodeBase64: Input buffer size should be a multiple of 3! (%d)\n", nbytes); - - for (j=0, i=0; i - - - -/*************************************************************************/ -/*! Use the templates to generate BLAS routines for the scalar data types */ -/*************************************************************************/ -GK_MKBLAS(gk_c, char, int) -GK_MKBLAS(gk_i, int, int) -GK_MKBLAS(gk_i32, int32_t, int32_t) -GK_MKBLAS(gk_i64, int64_t, int64_t) -GK_MKBLAS(gk_z, ssize_t, ssize_t) -GK_MKBLAS(gk_f, float, float) -GK_MKBLAS(gk_d, double, double) -GK_MKBLAS(gk_idx, gk_idx_t, gk_idx_t) - - - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/conf/check_thread_storage.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/conf/check_thread_storage.c deleted file mode 100644 index e6e1e980e2b..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/conf/check_thread_storage.c +++ /dev/null @@ -1,5 +0,0 @@ -extern __thread int x; - -int main(int argc, char **argv) { - return 0; -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/csr.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/csr.c deleted file mode 100644 index a19d793bdce..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/csr.c +++ /dev/null @@ -1,2010 +0,0 @@ -/*! - * \file - * - * \brief Various routines with dealing with CSR matrices - * - * \author George Karypis - * \version\verbatim $Id: csr.c 13437 2013-01-11 21:54:10Z karypis $ \endverbatim - */ - -#include - -#define OMPMINOPS 50000 - -/*************************************************************************/ -/*! Allocate memory for a CSR matrix and initializes it - \returns the allocated matrix. The various fields are set to NULL. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_Create() -{ - gk_csr_t *mat; - - mat = (gk_csr_t *)gk_malloc(sizeof(gk_csr_t), "gk_csr_Create: mat"); - - gk_csr_Init(mat); - - return mat; -} - - -/*************************************************************************/ -/*! Initializes the matrix - \param mat is the matrix to be initialized. -*/ -/*************************************************************************/ -void gk_csr_Init(gk_csr_t *mat) -{ - memset(mat, 0, sizeof(gk_csr_t)); - mat->nrows = mat->ncols = -1; -} - - -/*************************************************************************/ -/*! Frees all the memory allocated for matrix. - \param mat is the matrix to be freed. -*/ -/*************************************************************************/ -void gk_csr_Free(gk_csr_t **mat) -{ - if (*mat == NULL) - return; - gk_csr_FreeContents(*mat); - gk_free((void **)mat, LTERM); -} - - -/*************************************************************************/ -/*! Frees only the memory allocated for the matrix's different fields and - sets them to NULL. - \param mat is the matrix whose contents will be freed. -*/ -/*************************************************************************/ -void gk_csr_FreeContents(gk_csr_t *mat) -{ - gk_free((void *)&mat->rowptr, &mat->rowind, &mat->rowval, &mat->rowids, - &mat->colptr, &mat->colind, &mat->colval, &mat->colids, - &mat->rnorms, &mat->cnorms, &mat->rsums, &mat->csums, - &mat->rsizes, &mat->csizes, &mat->rvols, &mat->cvols, - &mat->rwgts, &mat->cwgts, - LTERM); -} - - -/*************************************************************************/ -/*! Returns a copy of a matrix. - \param mat is the matrix to be duplicated. - \returns the newly created copy of the matrix. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_Dup(gk_csr_t *mat) -{ - gk_csr_t *nmat; - - nmat = gk_csr_Create(); - - nmat->nrows = mat->nrows; - nmat->ncols = mat->ncols; - - /* copy the row structure */ - if (mat->rowptr) - nmat->rowptr = gk_zcopy(mat->nrows+1, mat->rowptr, - gk_zmalloc(mat->nrows+1, "gk_csr_Dup: rowptr")); - if (mat->rowids) - nmat->rowids = gk_icopy(mat->nrows, mat->rowids, - gk_imalloc(mat->nrows, "gk_csr_Dup: rowids")); - if (mat->rnorms) - nmat->rnorms = gk_fcopy(mat->nrows, mat->rnorms, - gk_fmalloc(mat->nrows, "gk_csr_Dup: rnorms")); - if (mat->rowind) - nmat->rowind = gk_icopy(mat->rowptr[mat->nrows], mat->rowind, - gk_imalloc(mat->rowptr[mat->nrows], "gk_csr_Dup: rowind")); - if (mat->rowval) - nmat->rowval = gk_fcopy(mat->rowptr[mat->nrows], mat->rowval, - gk_fmalloc(mat->rowptr[mat->nrows], "gk_csr_Dup: rowval")); - - /* copy the col structure */ - if (mat->colptr) - nmat->colptr = gk_zcopy(mat->ncols+1, mat->colptr, - gk_zmalloc(mat->ncols+1, "gk_csr_Dup: colptr")); - if (mat->colids) - nmat->colids = gk_icopy(mat->ncols, mat->colids, - gk_imalloc(mat->ncols, "gk_csr_Dup: colids")); - if (mat->cnorms) - nmat->cnorms = gk_fcopy(mat->ncols, mat->cnorms, - gk_fmalloc(mat->ncols, "gk_csr_Dup: cnorms")); - if (mat->colind) - nmat->colind = gk_icopy(mat->colptr[mat->ncols], mat->colind, - gk_imalloc(mat->colptr[mat->ncols], "gk_csr_Dup: colind")); - if (mat->colval) - nmat->colval = gk_fcopy(mat->colptr[mat->ncols], mat->colval, - gk_fmalloc(mat->colptr[mat->ncols], "gk_csr_Dup: colval")); - - return nmat; -} - - -/*************************************************************************/ -/*! Returns a submatrix containint a set of consecutive rows. - \param mat is the original matrix. - \param rstart is the starting row. - \param nrows is the number of rows from rstart to extract. - \returns the row structure of the newly created submatrix. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_ExtractSubmatrix(gk_csr_t *mat, int rstart, int nrows) -{ - ssize_t i; - gk_csr_t *nmat; - - if (rstart+nrows > mat->nrows) - return NULL; - - nmat = gk_csr_Create(); - - nmat->nrows = nrows; - nmat->ncols = mat->ncols; - - /* copy the row structure */ - if (mat->rowptr) - nmat->rowptr = gk_zcopy(nrows+1, mat->rowptr+rstart, - gk_zmalloc(nrows+1, "gk_csr_ExtractSubmatrix: rowptr")); - for (i=nrows; i>=0; i--) - nmat->rowptr[i] -= nmat->rowptr[0]; - ASSERT(nmat->rowptr[0] == 0); - - if (mat->rowids) - nmat->rowids = gk_icopy(nrows, mat->rowids+rstart, - gk_imalloc(nrows, "gk_csr_ExtractSubmatrix: rowids")); - if (mat->rnorms) - nmat->rnorms = gk_fcopy(nrows, mat->rnorms+rstart, - gk_fmalloc(nrows, "gk_csr_ExtractSubmatrix: rnorms")); - - if (mat->rsums) - nmat->rsums = gk_fcopy(nrows, mat->rsums+rstart, - gk_fmalloc(nrows, "gk_csr_ExtractSubmatrix: rsums")); - - ASSERT(nmat->rowptr[nrows] == mat->rowptr[rstart+nrows]-mat->rowptr[rstart]); - if (mat->rowind) - nmat->rowind = gk_icopy(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], - mat->rowind+mat->rowptr[rstart], - gk_imalloc(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], - "gk_csr_ExtractSubmatrix: rowind")); - if (mat->rowval) - nmat->rowval = gk_fcopy(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], - mat->rowval+mat->rowptr[rstart], - gk_fmalloc(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], - "gk_csr_ExtractSubmatrix: rowval")); - - return nmat; -} - - -/*************************************************************************/ -/*! Returns a submatrix containing a certain set of rows. - \param mat is the original matrix. - \param nrows is the number of rows to extract. - \param rind is the set of row numbers to extract. - \returns the row structure of the newly created submatrix. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_ExtractRows(gk_csr_t *mat, int nrows, int *rind) -{ - ssize_t i, ii, j, nnz; - gk_csr_t *nmat; - - nmat = gk_csr_Create(); - - nmat->nrows = nrows; - nmat->ncols = mat->ncols; - - for (nnz=0, i=0; irowptr[rind[i]+1]-mat->rowptr[rind[i]]; - - nmat->rowptr = gk_zmalloc(nmat->nrows+1, "gk_csr_ExtractPartition: rowptr"); - nmat->rowind = gk_imalloc(nnz, "gk_csr_ExtractPartition: rowind"); - nmat->rowval = gk_fmalloc(nnz, "gk_csr_ExtractPartition: rowval"); - - nmat->rowptr[0] = 0; - for (nnz=0, j=0, ii=0; iirowptr[i+1]-mat->rowptr[i], mat->rowind+mat->rowptr[i], nmat->rowind+nnz); - gk_fcopy(mat->rowptr[i+1]-mat->rowptr[i], mat->rowval+mat->rowptr[i], nmat->rowval+nnz); - nnz += mat->rowptr[i+1]-mat->rowptr[i]; - nmat->rowptr[++j] = nnz; - } - ASSERT(j == nmat->nrows); - - return nmat; -} - - -/*************************************************************************/ -/*! Returns a submatrix corresponding to a specified partitioning of rows. - \param mat is the original matrix. - \param part is the partitioning vector of the rows. - \param pid is the partition ID that will be extracted. - \returns the row structure of the newly created submatrix. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_ExtractPartition(gk_csr_t *mat, int *part, int pid) -{ - ssize_t i, j, nnz; - gk_csr_t *nmat; - - nmat = gk_csr_Create(); - - nmat->nrows = 0; - nmat->ncols = mat->ncols; - - for (nnz=0, i=0; inrows; i++) { - if (part[i] == pid) { - nmat->nrows++; - nnz += mat->rowptr[i+1]-mat->rowptr[i]; - } - } - - nmat->rowptr = gk_zmalloc(nmat->nrows+1, "gk_csr_ExtractPartition: rowptr"); - nmat->rowind = gk_imalloc(nnz, "gk_csr_ExtractPartition: rowind"); - nmat->rowval = gk_fmalloc(nnz, "gk_csr_ExtractPartition: rowval"); - - nmat->rowptr[0] = 0; - for (nnz=0, j=0, i=0; inrows; i++) { - if (part[i] == pid) { - gk_icopy(mat->rowptr[i+1]-mat->rowptr[i], mat->rowind+mat->rowptr[i], nmat->rowind+nnz); - gk_fcopy(mat->rowptr[i+1]-mat->rowptr[i], mat->rowval+mat->rowptr[i], nmat->rowval+nnz); - nnz += mat->rowptr[i+1]-mat->rowptr[i]; - nmat->rowptr[++j] = nnz; - } - } - ASSERT(j == nmat->nrows); - - return nmat; -} - - -/*************************************************************************/ -/*! Splits the matrix into multiple sub-matrices based on the provided - color array. - \param mat is the original matrix. - \param color is an array of size equal to the number of non-zeros - in the matrix (row-wise structure). The matrix is split into - as many parts as the number of colors. For meaningfull results, - the colors should be numbered consecutively starting from 0. - \returns an array of matrices for each supplied color number. -*/ -/**************************************************************************/ -gk_csr_t **gk_csr_Split(gk_csr_t *mat, int *color) -{ - ssize_t i, j; - int nrows, ncolors; - ssize_t *rowptr; - int *rowind; - float *rowval; - gk_csr_t **smats; - - nrows = mat->nrows; - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - - ncolors = gk_imax(rowptr[nrows], color)+1; - - smats = (gk_csr_t **)gk_malloc(sizeof(gk_csr_t *)*ncolors, "gk_csr_Split: smats"); - for (i=0; inrows = mat->nrows; - smats[i]->ncols = mat->ncols; - smats[i]->rowptr = gk_zsmalloc(nrows+1, 0, "gk_csr_Split: smats[i]->rowptr"); - } - - for (i=0; irowptr[i]++; - } - for (i=0; irowptr); - - for (i=0; irowind = gk_imalloc(smats[i]->rowptr[nrows], "gk_csr_Split: smats[i]->rowind"); - smats[i]->rowval = gk_fmalloc(smats[i]->rowptr[nrows], "gk_csr_Split: smats[i]->rowval"); - } - - for (i=0; irowind[smats[color[j]]->rowptr[i]] = rowind[j]; - smats[color[j]]->rowval[smats[color[j]]->rowptr[i]] = rowval[j]; - smats[color[j]]->rowptr[i]++; - } - } - - for (i=0; irowptr); - - return smats; -} - - -/**************************************************************************/ -/*! Reads a CSR matrix from the supplied file and stores it the matrix's - forward structure. - \param filename is the file that stores the data. - \param format is either GK_CSR_FMT_METIS, GK_CSR_FMT_CLUTO, - GK_CSR_FMT_CSR, GK_CSR_FMT_BINROW, GK_CSR_FMT_BINCOL - specifying the type of the input format. - The GK_CSR_FMT_CSR does not contain a header - line, whereas the GK_CSR_FMT_BINROW is a binary format written - by gk_csr_Write() using the same format specifier. - \param readvals is either 1 or 0, indicating if the CSR file contains - values or it does not. It only applies when GK_CSR_FMT_CSR is - used. - \param numbering is either 1 or 0, indicating if the numbering of the - indices start from 1 or 0, respectively. If they start from 1, - they are automatically decreamented during input so that they - will start from 0. It only applies when GK_CSR_FMT_CSR is - used. - \returns the matrix that was read. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_Read(char *filename, int format, int readvals, int numbering) -{ - ssize_t i, k, l; - size_t nfields, nrows, ncols, nnz, fmt, ncon; - size_t lnlen; - ssize_t *rowptr; - int *rowind, ival; - float *rowval=NULL, fval; - int readsizes, readwgts; - char *line=NULL, *head, *tail, fmtstr[256]; - FILE *fpin; - gk_csr_t *mat=NULL; - - - if (!gk_fexists(filename)) - gk_errexit(SIGERR, "File %s does not exist!\n", filename); - - if (format == GK_CSR_FMT_BINROW) { - mat = gk_csr_Create(); - - fpin = gk_fopen(filename, "rb", "gk_csr_Read: fpin"); - if (fread(&(mat->nrows), sizeof(int32_t), 1, fpin) != 1) - gk_errexit(SIGERR, "Failed to read the nrows from file %s!\n", filename); - if (fread(&(mat->ncols), sizeof(int32_t), 1, fpin) != 1) - gk_errexit(SIGERR, "Failed to read the ncols from file %s!\n", filename); - mat->rowptr = gk_zmalloc(mat->nrows+1, "gk_csr_Read: rowptr"); - if (fread(mat->rowptr, sizeof(ssize_t), mat->nrows+1, fpin) != mat->nrows+1) - gk_errexit(SIGERR, "Failed to read the rowptr from file %s!\n", filename); - mat->rowind = gk_imalloc(mat->rowptr[mat->nrows], "gk_csr_Read: rowind"); - if (fread(mat->rowind, sizeof(int32_t), mat->rowptr[mat->nrows], fpin) != mat->rowptr[mat->nrows]) - gk_errexit(SIGERR, "Failed to read the rowind from file %s!\n", filename); - if (readvals == 1) { - mat->rowval = gk_fmalloc(mat->rowptr[mat->nrows], "gk_csr_Read: rowval"); - if (fread(mat->rowval, sizeof(float), mat->rowptr[mat->nrows], fpin) != mat->rowptr[mat->nrows]) - gk_errexit(SIGERR, "Failed to read the rowval from file %s!\n", filename); - } - - gk_fclose(fpin); - return mat; - } - - if (format == GK_CSR_FMT_BINCOL) { - mat = gk_csr_Create(); - - fpin = gk_fopen(filename, "rb", "gk_csr_Read: fpin"); - if (fread(&(mat->nrows), sizeof(int32_t), 1, fpin) != 1) - gk_errexit(SIGERR, "Failed to read the nrows from file %s!\n", filename); - if (fread(&(mat->ncols), sizeof(int32_t), 1, fpin) != 1) - gk_errexit(SIGERR, "Failed to read the ncols from file %s!\n", filename); - mat->colptr = gk_zmalloc(mat->ncols+1, "gk_csr_Read: colptr"); - if (fread(mat->colptr, sizeof(ssize_t), mat->ncols+1, fpin) != mat->ncols+1) - gk_errexit(SIGERR, "Failed to read the colptr from file %s!\n", filename); - mat->colind = gk_imalloc(mat->colptr[mat->ncols], "gk_csr_Read: colind"); - if (fread(mat->colind, sizeof(int32_t), mat->colptr[mat->ncols], fpin) != mat->colptr[mat->ncols]) - gk_errexit(SIGERR, "Failed to read the colind from file %s!\n", filename); - if (readvals) { - mat->colval = gk_fmalloc(mat->colptr[mat->ncols], "gk_csr_Read: colval"); - if (fread(mat->colval, sizeof(float), mat->colptr[mat->ncols], fpin) != mat->colptr[mat->ncols]) - gk_errexit(SIGERR, "Failed to read the colval from file %s!\n", filename); - } - - gk_fclose(fpin); - return mat; - } - - - if (format == GK_CSR_FMT_CLUTO) { - fpin = gk_fopen(filename, "r", "gk_csr_Read: fpin"); - do { - if (gk_getline(&line, &lnlen, fpin) <= 0) - gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename); - } while (line[0] == '%'); - - if (sscanf(line, "%zu %zu %zu", &nrows, &ncols, &nnz) != 3) - gk_errexit(SIGERR, "Header line must contain 3 integers.\n"); - - readsizes = 0; - readwgts = 0; - readvals = 1; - numbering = 1; - } - else if (format == GK_CSR_FMT_METIS) { - fpin = gk_fopen(filename, "r", "gk_csr_Read: fpin"); - do { - if (gk_getline(&line, &lnlen, fpin) <= 0) - gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename); - } while (line[0] == '%'); - - fmt = ncon = 0; - nfields = sscanf(line, "%zu %zu %zu %zu", &nrows, &nnz, &fmt, &ncon); - if (nfields < 2) - gk_errexit(SIGERR, "Header line must contain at least 2 integers (#vtxs and #edges).\n"); - - ncols = nrows; - nnz *= 2; - - if (fmt > 111) - gk_errexit(SIGERR, "Cannot read this type of file format [fmt=%zu]!\n", fmt); - - sprintf(fmtstr, "%03zu", fmt%1000); - readsizes = (fmtstr[0] == '1'); - readwgts = (fmtstr[1] == '1'); - readvals = (fmtstr[2] == '1'); - numbering = 1; - ncon = (ncon == 0 ? 1 : ncon); - } - else { - readsizes = 0; - readwgts = 0; - - gk_getfilestats(filename, &nrows, &nnz, NULL, NULL); - - if (readvals == 1 && nnz%2 == 1) - gk_errexit(SIGERR, "Error: The number of numbers (%zd %d) in the input file is not even.\n", nnz, readvals); - if (readvals == 1) - nnz = nnz/2; - fpin = gk_fopen(filename, "r", "gk_csr_Read: fpin"); - } - - mat = gk_csr_Create(); - - mat->nrows = nrows; - - rowptr = mat->rowptr = gk_zmalloc(nrows+1, "gk_csr_Read: rowptr"); - rowind = mat->rowind = gk_imalloc(nnz, "gk_csr_Read: rowind"); - if (readvals != 2) - rowval = mat->rowval = gk_fsmalloc(nnz, 1.0, "gk_csr_Read: rowval"); - - if (readsizes) - mat->rsizes = gk_fsmalloc(nrows, 0.0, "gk_csr_Read: rsizes"); - - if (readwgts) - mat->rwgts = gk_fsmalloc(nrows*ncon, 0.0, "gk_csr_Read: rwgts"); - - /*---------------------------------------------------------------------- - * Read the sparse matrix file - *---------------------------------------------------------------------*/ - numbering = (numbering ? - 1 : 0); - for (ncols=0, rowptr[0]=0, k=0, i=0; irsizes[i] = (float)strtod(head, &tail); -#else - mat->rsizes[i] = strtof(head, &tail); -#endif - if (tail == head) - gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1); - if (mat->rsizes[i] < 0) - errexit("The size for vertex %zd must be >= 0\n", i+1); - head = tail; - } - - /* Read vertex weights */ - if (readwgts) { - for (l=0; lrwgts[i*ncon+l] = (float)strtod(head, &tail); -#else - mat->rwgts[i*ncon+l] = strtof(head, &tail); -#endif - if (tail == head) - errexit("The line for vertex %zd does not have enough weights " - "for the %d constraints.\n", i+1, ncon); - if (mat->rwgts[i*ncon+l] < 0) - errexit("The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l); - head = tail; - } - } - - - /* Read the rest of the row */ - while (1) { - ival = (int)strtol(head, &tail, 0); - if (tail == head) - break; - head = tail; - - if ((rowind[k] = ival + numbering) < 0) - gk_errexit(SIGERR, "Error: Invalid column number %d at row %zd.\n", ival, i); - - ncols = gk_max(rowind[k], ncols); - - if (readvals == 1) { -#ifdef __MSC__ - fval = (float)strtod(head, &tail); -#else - fval = strtof(head, &tail); -#endif - if (tail == head) - gk_errexit(SIGERR, "Value could not be found for column! Row:%zd, NNZ:%zd\n", i, k); - head = tail; - - rowval[k] = fval; - } - k++; - } - rowptr[i+1] = k; - } - - if (format == GK_CSR_FMT_METIS) { - ASSERT(ncols+1 == mat->nrows); - mat->ncols = mat->nrows; - } - else { - mat->ncols = ncols+1; - } - - if (k != nnz) - gk_errexit(SIGERR, "gk_csr_Read: Something wrong with the number of nonzeros in " - "the input file. NNZ=%zd, ActualNNZ=%zd.\n", nnz, k); - - gk_fclose(fpin); - - gk_free((void **)&line, LTERM); - - return mat; -} - - -/**************************************************************************/ -/*! Writes the row-based structure of a matrix into a file. - \param mat is the matrix to be written, - \param filename is the name of the output file. - \param format is one of: GK_CSR_FMT_CLUTO, GK_CSR_FMT_CSR, - GK_CSR_FMT_BINROW, GK_CSR_FMT_BINCOL. - \param writevals is either 1 or 0 indicating if the values will be - written or not. This is only applicable when GK_CSR_FMT_CSR - is used. - \param numbering is either 1 or 0 indicating if the internal 0-based - numbering will be shifted by one or not during output. This - is only applicable when GK_CSR_FMT_CSR is used. -*/ -/**************************************************************************/ -void gk_csr_Write(gk_csr_t *mat, char *filename, int format, int writevals, int numbering) -{ - ssize_t i, j; - FILE *fpout; - - if (format == GK_CSR_FMT_BINROW) { - if (filename == NULL) - gk_errexit(SIGERR, "The filename parameter cannot be NULL.\n"); - fpout = gk_fopen(filename, "wb", "gk_csr_Write: fpout"); - - fwrite(&(mat->nrows), sizeof(int32_t), 1, fpout); - fwrite(&(mat->ncols), sizeof(int32_t), 1, fpout); - fwrite(mat->rowptr, sizeof(ssize_t), mat->nrows+1, fpout); - fwrite(mat->rowind, sizeof(int32_t), mat->rowptr[mat->nrows], fpout); - if (writevals) - fwrite(mat->rowval, sizeof(float), mat->rowptr[mat->nrows], fpout); - - gk_fclose(fpout); - return; - } - - if (format == GK_CSR_FMT_BINCOL) { - if (filename == NULL) - gk_errexit(SIGERR, "The filename parameter cannot be NULL.\n"); - fpout = gk_fopen(filename, "wb", "gk_csr_Write: fpout"); - - fwrite(&(mat->nrows), sizeof(int32_t), 1, fpout); - fwrite(&(mat->ncols), sizeof(int32_t), 1, fpout); - fwrite(mat->colptr, sizeof(ssize_t), mat->ncols+1, fpout); - fwrite(mat->colind, sizeof(int32_t), mat->colptr[mat->ncols], fpout); - if (writevals) - fwrite(mat->colval, sizeof(float), mat->colptr[mat->ncols], fpout); - - gk_fclose(fpout); - return; - } - - if (filename) - fpout = gk_fopen(filename, "w", "gk_csr_Write: fpout"); - else - fpout = stdout; - - if (format == GK_CSR_FMT_CLUTO) { - fprintf(fpout, "%d %d %zd\n", mat->nrows, mat->ncols, mat->rowptr[mat->nrows]); - writevals = 1; - numbering = 1; - } - - for (i=0; inrows; i++) { - for (j=mat->rowptr[i]; jrowptr[i+1]; j++) { - fprintf(fpout, " %d", mat->rowind[j]+(numbering ? 1 : 0)); - if (writevals) - fprintf(fpout, " %f", mat->rowval[j]); - } - fprintf(fpout, "\n"); - } - if (filename) - gk_fclose(fpout); -} - - -/*************************************************************************/ -/*! Prunes certain rows/columns of the matrix. The prunning takes place - by analyzing the row structure of the matrix. The prunning takes place - by removing rows/columns but it does not affect the numbering of the - remaining rows/columns. - - \param mat the matrix to be prunned, - \param what indicates if the rows (GK_CSR_ROW) or the columns (GK_CSR_COL) - of the matrix will be prunned, - \param minf is the minimum number of rows (columns) that a column (row) must - be present in order to be kept, - \param maxf is the maximum number of rows (columns) that a column (row) must - be present at in order to be kept. - \returns the prunned matrix consisting only of its row-based structure. - The input matrix is not modified. -*/ -/**************************************************************************/ -gk_csr_t *gk_csr_Prune(gk_csr_t *mat, int what, int minf, int maxf) -{ - ssize_t i, j, nnz; - int nrows, ncols; - ssize_t *rowptr, *nrowptr; - int *rowind, *nrowind, *collen; - float *rowval, *nrowval; - gk_csr_t *nmat; - - nmat = gk_csr_Create(); - - nrows = nmat->nrows = mat->nrows; - ncols = nmat->ncols = mat->ncols; - - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - - nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_Prune: nrowptr"); - nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_Prune: nrowind"); - nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_Prune: nrowval"); - - - switch (what) { - case GK_CSR_COL: - collen = gk_ismalloc(ncols, 0, "gk_csr_Prune: collen"); - - for (i=0; i= minf && collen[i] <= maxf ? 1 : 0); - - nrowptr[0] = 0; - for (nnz=0, i=0; i= minf && rowptr[i+1]-rowptr[i] <= maxf) { - for (j=rowptr[i]; jnrows = mat->nrows; - ncols = nmat->ncols = mat->ncols; - - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - colptr = mat->colptr; - colind = mat->colind; - colval = mat->colval; - - nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_LowFilter: nrowptr"); - nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_LowFilter: nrowind"); - nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_LowFilter: nrowval"); - - - switch (what) { - case GK_CSR_COL: - if (mat->colptr == NULL) - gk_errexit(SIGERR, "Cannot filter columns when column-based structure has not been created.\n"); - - gk_zcopy(nrows+1, rowptr, nrowptr); - - for (i=0; irowptr == NULL) - gk_errexit(SIGERR, "Cannot filter rows when row-based structure has not been created.\n"); - - for (i=0; inrows = mat->nrows; - ncols = nmat->ncols = mat->ncols; - - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - colptr = mat->colptr; - colind = mat->colind; - colval = mat->colval; - - nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_LowFilter: nrowptr"); - nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_LowFilter: nrowind"); - nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_LowFilter: nrowval"); - - - switch (what) { - case GK_CSR_COL: - if (mat->colptr == NULL) - gk_errexit(SIGERR, "Cannot filter columns when column-based structure has not been created.\n"); - - cand = gk_fkvmalloc(nrows, "gk_csr_LowFilter: cand"); - - gk_zcopy(nrows+1, rowptr, nrowptr); - for (i=0; irowptr == NULL) - gk_errexit(SIGERR, "Cannot filter rows when row-based structure has not been created.\n"); - - cand = gk_fkvmalloc(ncols, "gk_csr_LowFilter: cand"); - - nrowptr[0] = 0; - for (nnz=0, i=0; inrows = mat->nrows; - nmat->ncols = mat->ncols; - - nrows = mat->nrows; - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - - nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_ZScoreFilter: nrowptr"); - nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_ZScoreFilter: nrowind"); - nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_ZScoreFilter: nrowval"); - - - switch (what) { - case GK_CSR_COL: - gk_errexit(SIGERR, "This has not been implemented yet.\n"); - break; - - case GK_CSR_ROW: - if (mat->rowptr == NULL) - gk_errexit(SIGERR, "Cannot filter rows when row-based structure has not been created.\n"); - - nrowptr[0] = 0; - for (nnz=0, i=0; i avgwgt) { - nrowind[nnz] = rowind[j]; - nrowval[nnz] = rowval[j]; - nnz++; - } - } - nrowptr[i+1] = nnz; - } - break; - - default: - gk_csr_Free(&nmat); - gk_errexit(SIGERR, "Unknown prunning type of %d\n", what); - return NULL; - } - - return nmat; -} - - -/*************************************************************************/ -/*! Compacts the column-space of the matrix by removing empty columns. - As a result of the compaction, the column numbers are renumbered. - The compaction operation is done in place and only affects the row-based - representation of the matrix. - The new columns are ordered in decreasing frequency. - - \param mat the matrix whose empty columns will be removed. -*/ -/**************************************************************************/ -void gk_csr_CompactColumns(gk_csr_t *mat) -{ - ssize_t i; - int nrows, ncols, nncols; - ssize_t *rowptr; - int *rowind, *colmap; - gk_ikv_t *clens; - - nrows = mat->nrows; - ncols = mat->ncols; - rowptr = mat->rowptr; - rowind = mat->rowind; - - colmap = gk_imalloc(ncols, "gk_csr_CompactColumns: colmap"); - - clens = gk_ikvmalloc(ncols, "gk_csr_CompactColumns: clens"); - for (i=0; i 0) - colmap[clens[i].val] = nncols++; - else - break; - } - - for (i=0; incols = nncols; - - gk_free((void **)&colmap, &clens, LTERM); -} - - -/*************************************************************************/ -/*! Sorts the indices in increasing order - \param mat the matrix itself, - \param what is either GK_CSR_ROW or GK_CSR_COL indicating which set of - indices to sort. -*/ -/**************************************************************************/ -void gk_csr_SortIndices(gk_csr_t *mat, int what) -{ - int n, nn=0; - ssize_t *ptr; - int *ind; - float *val; - - switch (what) { - case GK_CSR_ROW: - if (!mat->rowptr) - gk_errexit(SIGERR, "Row-based view of the matrix does not exists.\n"); - - n = mat->nrows; - ptr = mat->rowptr; - ind = mat->rowind; - val = mat->rowval; - break; - - case GK_CSR_COL: - if (!mat->colptr) - gk_errexit(SIGERR, "Column-based view of the matrix does not exists.\n"); - - n = mat->ncols; - ptr = mat->colptr; - ind = mat->colind; - val = mat->colval; - break; - - default: - gk_errexit(SIGERR, "Invalid index type of %d.\n", what); - return; - } - - #pragma omp parallel if (n > 100) - { - ssize_t i, j, k; - gk_ikv_t *cand; - float *tval; - - #pragma omp single - for (i=0; i ptr[i] && ind[j] < ind[j-1]) - k = 1; /* an inversion */ - cand[j-ptr[i]].val = j-ptr[i]; - cand[j-ptr[i]].key = ind[j]; - tval[j-ptr[i]] = val[j]; - } - if (k) { - gk_ikvsorti(ptr[i+1]-ptr[i], cand); - for (j=ptr[i]; jnrows; - fptr = mat->rowptr; - find = mat->rowind; - fval = mat->rowval; - - if (mat->colptr) gk_free((void **)&mat->colptr, LTERM); - if (mat->colind) gk_free((void **)&mat->colind, LTERM); - if (mat->colval) gk_free((void **)&mat->colval, LTERM); - - nr = mat->ncols; - rptr = mat->colptr = gk_zsmalloc(nr+1, 0, "gk_csr_CreateIndex: rptr"); - rind = mat->colind = gk_imalloc(fptr[nf], "gk_csr_CreateIndex: rind"); - rval = mat->colval = (fval ? gk_fmalloc(fptr[nf], "gk_csr_CreateIndex: rval") : NULL); - break; - case GK_CSR_ROW: - nf = mat->ncols; - fptr = mat->colptr; - find = mat->colind; - fval = mat->colval; - - if (mat->rowptr) gk_free((void **)&mat->rowptr, LTERM); - if (mat->rowind) gk_free((void **)&mat->rowind, LTERM); - if (mat->rowval) gk_free((void **)&mat->rowval, LTERM); - - nr = mat->nrows; - rptr = mat->rowptr = gk_zsmalloc(nr+1, 0, "gk_csr_CreateIndex: rptr"); - rind = mat->rowind = gk_imalloc(fptr[nf], "gk_csr_CreateIndex: rind"); - rval = mat->rowval = (fval ? gk_fmalloc(fptr[nf], "gk_csr_CreateIndex: rval") : NULL); - break; - default: - gk_errexit(SIGERR, "Invalid index type of %d.\n", what); - return; - } - - - for (i=0; i 6*nr) { - for (i=0; irowval) { - n = mat->nrows; - ptr = mat->rowptr; - val = mat->rowval; - - #pragma omp parallel if (ptr[n] > OMPMINOPS) - { - #pragma omp for private(j,sum) schedule(static) - for (i=0; i 0 */ - } - if (sum > 0) { - if (norm == 2) - sum=1.0/sqrt(sum); - else if (norm == 1) - sum=1.0/sum; - for (j=ptr[i]; jcolval) { - n = mat->ncols; - ptr = mat->colptr; - val = mat->colval; - - #pragma omp parallel if (ptr[n] > OMPMINOPS) - { - #pragma omp for private(j,sum) schedule(static) - for (i=0; i 0) { - if (norm == 2) - sum=1.0/sqrt(sum); - else if (norm == 1) - sum=1.0/sum; - for (j=ptr[i]; jnrows; - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - - switch (type) { - case GK_CSR_MAXTF: /* TF' = .5 + .5*TF/MAX(TF) */ - #pragma omp parallel if (rowptr[nrows] > OMPMINOPS) - { - #pragma omp for private(j, maxtf) schedule(static) - for (i=0; i OMPMINOPS) - { - #pragma omp for private(j, maxtf) schedule(static) - for (i=0; i OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; i OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; i OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; i OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; i OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; i OMPMINOPS) - { - double logscale = 1.0/log(2.0); - #pragma omp for schedule(static,32) - for (i=0; i0.0 ? log(rowval[i]) : -log(-rowval[i]))*logscale; - } -#ifdef XXX - #pragma omp for private(j) schedule(static) - for (i=0; i0.0 ? log(rowval[j]) : -log(-rowval[j]))*logscale; - //rowval[j] = 1+sign(rowval[j], log(fabs(rowval[j]))*logscale); - } - } -#endif - } - break; - - case GK_CSR_IDF: /* TF' = TF*IDF */ - ncols = mat->ncols; - cscale = gk_fmalloc(ncols, "gk_csr_Scale: cscale"); - collen = gk_ismalloc(ncols, 0, "gk_csr_Scale: collen"); - - for (i=0; i OMPMINOPS) - { - #pragma omp for schedule(static) - for (i=0; i 0 ? log(1.0*nrows/collen[i]) : 0.0); - } - - #pragma omp parallel if (rowptr[nrows] > OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; incols; - cscale = gk_fmalloc(ncols, "gk_csr_Scale: cscale"); - collen = gk_ismalloc(ncols, 0, "gk_csr_Scale: collen"); - - for (i=0; i OMPMINOPS) - { - #pragma omp for schedule(static) reduction(+:nnzcols) - for (i=0; i 0 ? 1 : 0); - - bgfreq = gk_max(10, (ssize_t)(.5*rowptr[nrows]/nnzcols)); - printf("nnz: %zd, nnzcols: %d, bgfreq: %d\n", rowptr[nrows], nnzcols, bgfreq); - - #pragma omp for schedule(static) - for (i=0; i 0 ? log(1.0*(nrows+2*bgfreq)/(bgfreq+collen[i])) : 0.0); - } - - #pragma omp parallel if (rowptr[nrows] > OMPMINOPS) - { - #pragma omp for private(j) schedule(static) - for (i=0; inrows; - ptr = mat->rowptr; - val = mat->rowval; - - if (mat->rsums) - gk_free((void **)&mat->rsums, LTERM); - - sums = mat->rsums = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: sums"); - break; - case GK_CSR_COL: - n = mat->ncols; - ptr = mat->colptr; - val = mat->colval; - - if (mat->csums) - gk_free((void **)&mat->csums, LTERM); - - sums = mat->csums = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: sums"); - break; - default: - gk_errexit(SIGERR, "Invalid sum type of %d.\n", what); - return; - } - - #pragma omp parallel for if (ptr[n] > OMPMINOPS) schedule(static) - for (i=0; inrows; - ptr = mat->rowptr; - val = mat->rowval; - - if (mat->rnorms) gk_free((void **)&mat->rnorms, LTERM); - - norms = mat->rnorms = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: norms"); - break; - case GK_CSR_COL: - n = mat->ncols; - ptr = mat->colptr; - val = mat->colval; - - if (mat->cnorms) gk_free((void **)&mat->cnorms, LTERM); - - norms = mat->cnorms = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: norms"); - break; - default: - gk_errexit(SIGERR, "Invalid norm type of %d.\n", what); - return; - } - - #pragma omp parallel for if (ptr[n] > OMPMINOPS) schedule(static) - for (i=0; irowptr) - gk_errexit(SIGERR, "Row-based view of the matrix does not exists.\n"); - nind1 = mat->rowptr[i1+1]-mat->rowptr[i1]; - nind2 = mat->rowptr[i2+1]-mat->rowptr[i2]; - ind1 = mat->rowind + mat->rowptr[i1]; - ind2 = mat->rowind + mat->rowptr[i2]; - val1 = mat->rowval + mat->rowptr[i1]; - val2 = mat->rowval + mat->rowptr[i2]; - break; - - case GK_CSR_COL: - if (!mat->colptr) - gk_errexit(SIGERR, "Column-based view of the matrix does not exists.\n"); - nind1 = mat->colptr[i1+1]-mat->colptr[i1]; - nind2 = mat->colptr[i2+1]-mat->colptr[i2]; - ind1 = mat->colind + mat->colptr[i1]; - ind2 = mat->colind + mat->colptr[i2]; - val1 = mat->colval + mat->colptr[i1]; - val2 = mat->colval + mat->colptr[i2]; - break; - - default: - gk_errexit(SIGERR, "Invalid index type of %d.\n", what); - return 0.0; - } - - - switch (simtype) { - case GK_CSR_COS: - case GK_CSR_JAC: - sim = stat1 = stat2 = 0.0; - i1 = i2 = 0; - while (i1 ind2[i2]) { - stat2 += val2[i2]*val2[i2]; - i2++; - } - else { - sim += val1[i1]*val2[i2]; - stat1 += val1[i1]*val1[i1]; - stat2 += val2[i2]*val2[i2]; - i1++; - i2++; - } - } - if (simtype == GK_CSR_COS) - sim = (stat1*stat2 > 0.0 ? sim/sqrt(stat1*stat2) : 0.0); - else - sim = (stat1+stat2-sim > 0.0 ? sim/(stat1+stat2-sim) : 0.0); - break; - - case GK_CSR_MIN: - sim = stat1 = stat2 = 0.0; - i1 = i2 = 0; - while (i1 ind2[i2]) { - stat2 += val2[i2]; - i2++; - } - else { - sim += gk_min(val1[i1],val2[i2]); - stat1 += val1[i1]; - stat2 += val2[i2]; - i1++; - i2++; - } - } - sim = (stat1+stat2-sim > 0.0 ? sim/(stat1+stat2-sim) : 0.0); - - break; - - case GK_CSR_AMIN: - sim = stat1 = stat2 = 0.0; - i1 = i2 = 0; - while (i1 ind2[i2]) { - stat2 += val2[i2]; - i2++; - } - else { - sim += gk_min(val1[i1],val2[i2]); - stat1 += val1[i1]; - stat2 += val2[i2]; - i1++; - i2++; - } - } - sim = (stat1 > 0.0 ? sim/stat1 : 0.0); - - break; - - default: - gk_errexit(SIGERR, "Unknown similarity measure %d\n", simtype); - return -1; - } - - return sim; - -} - - -/*************************************************************************/ -/*! Finds the n most similar rows (neighbors) to the query using cosine - similarity. - - \param mat the matrix itself - \param nqterms is the number of columns in the query - \param qind is the list of query columns - \param qval is the list of correspodning query weights - \param simtype is the type of similarity and is one of GK_CSR_COS, - GK_CSR_JAC, GK_CSR_MIN, GK_CSR_AMIN - \param nsim is the maximum number of requested most similar rows. - If -1 is provided, then everything is returned unsorted. - \param minsim is the minimum similarity of the requested most - similar rows - \param hits is the result set. This array should be at least - of length nsim. - \param i_marker is an array of size equal to the number of rows - whose values are initialized to -1. If NULL is provided - then this array is allocated and freed internally. - \param i_cand is an array of size equal to the number of rows. - If NULL is provided then this array is allocated and freed - internally. - \returns the number of identified most similar rows, which can be - smaller than the requested number of nnbrs in those cases - in which there are no sufficiently many neighbors. -*/ -/**************************************************************************/ -int gk_csr_GetSimilarRows(gk_csr_t *mat, int nqterms, int *qind, - float *qval, int simtype, int nsim, float minsim, gk_fkv_t *hits, - int *i_marker, gk_fkv_t *i_cand) -{ - ssize_t i, ii, j, k; - int nrows, ncols, ncand; - ssize_t *colptr; - int *colind, *marker; - float *colval, *rnorms, mynorm, *rsums, mysum; - gk_fkv_t *cand; - - if (nqterms == 0) - return 0; - - nrows = mat->nrows; - ncols = mat->ncols; - colptr = mat->colptr; - colind = mat->colind; - colval = mat->colval; - - marker = (i_marker ? i_marker : gk_ismalloc(nrows, -1, "gk_csr_SimilarRows: marker")); - cand = (i_cand ? i_cand : gk_fkvmalloc(nrows, "gk_csr_SimilarRows: cand")); - - switch (simtype) { - case GK_CSR_COS: - for (ncand=0, ii=0; iirnorms; - mynorm = gk_fdot(nqterms, qval, 1, qval, 1); - - for (i=0; irsums; - mysum = gk_fsum(nqterms, qval, 1); - - for (i=0; i= minsim) - cand[j++] = cand[i]; - } - ncand = j; - - if (nsim == -1 || nsim >= ncand) { - nsim = ncand; - } - else { - nsim = gk_min(nsim, ncand); - gk_dfkvkselect(ncand, nsim, cand); - gk_fkvsortd(nsim, cand); - } - - gk_fkvcopy(nsim, cand, hits); - - if (i_marker == NULL) - gk_free((void **)&marker, LTERM); - if (i_cand == NULL) - gk_free((void **)&cand, LTERM); - - return nsim; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/error.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/error.c deleted file mode 100644 index 7a58f3dd082..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/error.c +++ /dev/null @@ -1,214 +0,0 @@ -/*! -\file error.c -\brief Various error-handling functions - -This file contains functions dealing with error reporting and termination - -\author George -\date 1/1/2007 -\version\verbatim $Id: error.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - - -#define _GK_ERROR_C_ /* this is needed to properly declare the gk_jub* variables - as an extern function in GKlib.h */ - -#include - - -/* These are the jmp_buf for the graceful exit in case of severe errors. - Multiple buffers are defined to allow for recursive invokation. */ -#define MAX_JBUFS 24 -__thread int gk_cur_jbufs=-1; -__thread jmp_buf gk_jbufs[MAX_JBUFS]; -__thread jmp_buf gk_jbuf; - -typedef void (*gksighandler_t)(int); - -/* These are the holders of the old singal handlers for the trapped signals */ -static __thread gksighandler_t old_SIGMEM_handler; /* Custom signal */ -static __thread gksighandler_t old_SIGERR_handler; /* Custom signal */ -static __thread gksighandler_t old_SIGMEM_handlers[MAX_JBUFS]; /* Custom signal */ -static __thread gksighandler_t old_SIGERR_handlers[MAX_JBUFS]; /* Custom signal */ - -/* The following is used to control if the gk_errexit() will actually abort or not. - There is always a single copy of this variable */ -static int gk_exit_on_error = 1; - - -/*************************************************************************/ -/*! This function sets the gk_exit_on_error variable - */ -/*************************************************************************/ -void gk_set_exit_on_error(int value) -{ - gk_exit_on_error = value; -} - - - -/*************************************************************************/ -/*! This function prints an error message and exits - */ -/*************************************************************************/ -void errexit(char *f_str,...) -{ - va_list argp; - - va_start(argp, f_str); - vfprintf(stderr, f_str, argp); - va_end(argp); - - if (strlen(f_str) == 0 || f_str[strlen(f_str)-1] != '\n') - fprintf(stderr,"\n"); - fflush(stderr); - - if (gk_exit_on_error) - exit(-2); - - /* abort(); */ -} - - -/*************************************************************************/ -/*! This function prints an error message and raises a signum signal - */ -/*************************************************************************/ -void gk_errexit(int signum, char *f_str,...) -{ - va_list argp; - - va_start(argp, f_str); - vfprintf(stderr, f_str, argp); - va_end(argp); - - fprintf(stderr,"\n"); - fflush(stderr); - - if (gk_exit_on_error) - raise(signum); -} - - -/***************************************************************************/ -/*! This function sets a number of signal handlers and sets the return point - of a longjmp -*/ -/***************************************************************************/ -int gk_sigtrap() -{ - if (gk_cur_jbufs+1 >= MAX_JBUFS) - return 0; - - gk_cur_jbufs++; - - old_SIGMEM_handlers[gk_cur_jbufs] = signal(SIGMEM, gk_sigthrow); - old_SIGERR_handlers[gk_cur_jbufs] = signal(SIGERR, gk_sigthrow); - - return 1; -} - - -/***************************************************************************/ -/*! This function sets the handlers for the signals to their default handlers - */ -/***************************************************************************/ -int gk_siguntrap() -{ - if (gk_cur_jbufs == -1) - return 0; - - signal(SIGMEM, old_SIGMEM_handlers[gk_cur_jbufs]); - signal(SIGERR, old_SIGERR_handlers[gk_cur_jbufs]); - - gk_cur_jbufs--; - - return 1; -} - - -/*************************************************************************/ -/*! This function is the custome signal handler, which all it does is to - perform a longjump to the most recent saved environment - */ -/*************************************************************************/ -void gk_sigthrow(int signum) -{ - longjmp(gk_jbufs[gk_cur_jbufs], signum); -} - - -/*************************************************************************** -* This function sets a number of signal handlers and sets the return point -* of a longjmp -****************************************************************************/ -void gk_SetSignalHandlers() -{ - old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler); - old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler); -} - - -/*************************************************************************** -* This function sets the handlers for the signals to their default handlers -****************************************************************************/ -void gk_UnsetSignalHandlers() -{ - signal(SIGMEM, old_SIGMEM_handler); - signal(SIGERR, old_SIGERR_handler); -} - - -/************************************************************************* -* This function is the handler for SIGUSR1 that implements the cleaning up -* process prior to a non-local exit. -**************************************************************************/ -void gk_NonLocalExit_Handler(int signum) -{ - longjmp(gk_jbuf, signum); -} - - -/*************************************************************************/ -/*! \brief Thread-safe implementation of strerror() */ -/**************************************************************************/ -char *gk_strerror(int errnum) -{ -#if defined(WIN32) || defined(__MINGW32__) - return strerror(errnum); -#else -#ifndef SUNOS - static __thread char buf[1024]; - - strerror_r(errnum, buf, 1024); - - buf[1023] = '\0'; - return buf; -#else - return strerror(errnum); -#endif -#endif -} - - - -/************************************************************************* -* This function prints a backtrace of calling functions -**************************************************************************/ -void PrintBackTrace() -{ -#ifdef HAVE_EXECINFO_H - void *array[10]; - int i, size; - char **strings; - - size = backtrace(array, 10); - strings = backtrace_symbols(array, size); - - printf("Obtained %d stack frames.\n", size); - for (i=0; i - -/********************************************************************** - * This function computes the max accuracy score of a ranked list, - * given +1/-1 class list - **********************************************************************/ -float ComputeAccuracy(int n, gk_fkv_t *list) -{ - int i, P, N, TP, FN = 0; - float bAccuracy = 0.0; - float acc; - - for (P=0, i=0;i bAccuracy) - bAccuracy = acc; - } - - return bAccuracy; -} - - -/***************************************************************************** - * This function computes the ROC score of a ranked list, given a +1/-1 class - * list. - ******************************************************************************/ -float ComputeROCn(int n, int maxN, gk_fkv_t *list) -{ - int i, P, TP, FP, TPprev, FPprev, AUC; - float prev; - - FP = TP = FPprev = TPprev = AUC = 0; - prev = list[0].key -1; - - for (P=0, i=0; i 0 ? (float)(1.0*AUC/(P*FP)) : 0.0); -} - - -/***************************************************************************** -* This function computes the median rate of false positive for each positive -* instance. -******************************************************************************/ -float ComputeMedianRFP(int n, gk_fkv_t *list) -{ - int i, P, N, TP, FP; - - P = N = 0; - for (i=0; i - -/* Byte-wise swap two items of size SIZE. */ -#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0) - - -/******************************************************************************/ -/*! This function puts the 'topk' largest values in the beginning of the array */ -/*******************************************************************************/ -int gk_dfkvkselect(size_t n, int topk, gk_fkv_t *cand) -{ - int i, j, lo, hi, mid; - gk_fkv_t stmp; - float pivot; - - if (n <= topk) - return n; /* return if the array has fewer elements than we want */ - - for (lo=0, hi=n-1; lo < hi;) { - mid = lo + ((hi-lo) >> 1); - - /* select the median */ - if (cand[lo].key < cand[mid].key) - mid = lo; - if (cand[hi].key > cand[mid].key) - mid = hi; - else - goto jump_over; - if (cand[lo].key < cand[mid].key) - mid = lo; - -jump_over: - QSSWAP(cand[mid], cand[hi], stmp); - pivot = cand[hi].key; - - /* the partitioning algorithm */ - for (i=lo-1, j=lo; j= pivot) { - i++; - QSSWAP(cand[i], cand[j], stmp); - } - } - i++; - QSSWAP(cand[i], cand[hi], stmp); - - - if (i > topk) - hi = i-1; - else if (i < topk) - lo = i+1; - else - break; - } - -/* - if (cand[lo].key < cand[hi].key) - printf("Hmm Error: %d %d %d %f %f\n", i, lo, hi, cand[lo].key, cand[hi].key); - - - for (i=topk; i cand[j].key) - printf("Hmm Error: %d %d %f %f %d %d\n", i, j, cand[i].key, cand[j].key, lo, hi); - } -*/ - - return topk; -} - - -/******************************************************************************/ -/*! This function puts the 'topk' smallest values in the beginning of the array */ -/*******************************************************************************/ -int gk_ifkvkselect(size_t n, int topk, gk_fkv_t *cand) -{ - int i, j, lo, hi, mid; - gk_fkv_t stmp; - float pivot; - - if (n <= topk) - return n; /* return if the array has fewer elements than we want */ - - for (lo=0, hi=n-1; lo < hi;) { - mid = lo + ((hi-lo) >> 1); - - /* select the median */ - if (cand[lo].key > cand[mid].key) - mid = lo; - if (cand[hi].key < cand[mid].key) - mid = hi; - else - goto jump_over; - if (cand[lo].key > cand[mid].key) - mid = lo; - -jump_over: - QSSWAP(cand[mid], cand[hi], stmp); - pivot = cand[hi].key; - - /* the partitioning algorithm */ - for (i=lo-1, j=lo; j topk) - hi = i-1; - else if (i < topk) - lo = i+1; - else - break; - } - -/* - if (cand[lo].key > cand[hi].key) - printf("Hmm Error: %d %d %d %f %f\n", i, lo, hi, cand[lo].key, cand[hi].key); - - - for (i=topk; i - - - -/************************************************************************* -* This function checks if a file exists -**************************************************************************/ -int gk_fexists(char *fname) -{ - struct stat status; - - if (stat(fname, &status) == -1) - return 0; - - return S_ISREG(status.st_mode); -} - - -/************************************************************************* -* This function checks if a directory exists -**************************************************************************/ -int gk_dexists(char *dirname) -{ - struct stat status; - - if (stat(dirname, &status) == -1) - return 0; - - return S_ISDIR(status.st_mode); -} - - -/*************************************************************************/ -/*! \brief Returns the size of the file in bytes - -This function returns the size of a file as a 64 bit integer. If there -were any errors in stat'ing the file, -1 is returned. -\note That due to the -1 return code, the maximum file size is limited to - 63 bits (which I guess is okay for now). -*/ -/**************************************************************************/ -intmax_t gk_getfsize(char *filename) -{ - struct stat status; - - if (stat(filename, &status) == -1) - return -1; - - return (intmax_t)(status.st_size); -} - - -/*************************************************************************/ -/*! This function gets some basic statistics about the file. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. - \param r_ntokens is the number of tokens in the file. If it is NULL, - this information is not returned. - \param r_max_nlntokens is the maximum number of tokens in any line - in the file. If it is NULL this information is not returned. - \param r_nbytes is the number of bytes in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -void gk_getfilestats(char *fname, size_t *r_nlines, size_t *r_ntokens, - size_t *r_max_nlntokens, size_t *r_nbytes) -{ - size_t nlines=0, ntokens=0, max_nlntokens=0, nbytes=0, oldntokens=0, nread; - int intoken=0; - char buffer[2049], *cptr; - FILE *fpin; - - fpin = gk_fopen(fname, "r", "gk_GetFileStats"); - - while (!feof(fpin)) { - nread = fread(buffer, sizeof(char), 2048, fpin); - nbytes += nread; - - buffer[nread] = '\0'; /* There is space for this one */ - for (cptr=buffer; *cptr!='\0'; cptr++) { - if (*cptr == '\n') { - nlines++; - ntokens += intoken; - intoken = 0; - if (max_nlntokens < ntokens-oldntokens) - max_nlntokens = ntokens-oldntokens; - oldntokens = ntokens; - } - else if (*cptr == ' ' || *cptr == '\t') { - ntokens += intoken; - intoken = 0; - } - else { - intoken = 1; - } - } - } - ntokens += intoken; - if (max_nlntokens < ntokens-oldntokens) - max_nlntokens = ntokens-oldntokens; - - gk_fclose(fpin); - - if (r_nlines != NULL) - *r_nlines = nlines; - if (r_ntokens != NULL) - *r_ntokens = ntokens; - if (r_max_nlntokens != NULL) - *r_max_nlntokens = max_nlntokens; - if (r_nbytes != NULL) - *r_nbytes = nbytes; -} - - -/************************************************************************* -* This function takes in a potentially full path specification of a file -* and just returns a string containing just the basename of the file. -* The basename is derived from the actual filename by stripping the last -* .ext part. -**************************************************************************/ -char *gk_getbasename(char *path) -{ - char *startptr, *endptr; - char *basename; - - if ((startptr = strrchr(path, '/')) == NULL) - startptr = path; - else - startptr = startptr+1; - - basename = gk_strdup(startptr); - - if ((endptr = strrchr(basename, '.')) != NULL) - *endptr = '\0'; - - return basename; -} - -/************************************************************************* -* This function takes in a potentially full path specification of a file -* and just returns a string corresponding to its file extension. The -* extension of a file is considered to be the string right after the -* last '.' character. -**************************************************************************/ -char *gk_getextname(char *path) -{ - char *startptr; - - if ((startptr = strrchr(path, '.')) == NULL) - return gk_strdup(path); - else - return gk_strdup(startptr+1); -} - -/************************************************************************* -* This function takes in a potentially full path specification of a file -* and just returns a string containing just the filename. -**************************************************************************/ -char *gk_getfilename(char *path) -{ - char *startptr; - - if ((startptr = strrchr(path, '/')) == NULL) - return gk_strdup(path); - else - return gk_strdup(startptr+1); -} - -/************************************************************************* -* This function takes in a potentially full path specification of a file -* and extracts the directory path component if it exists, otherwise it -* returns "./" as the path. The memory for it is dynamically allocated. -**************************************************************************/ -char *getpathname(char *path) -{ - char *endptr, *tmp; - - if ((endptr = strrchr(path, '/')) == NULL) { - return gk_strdup("."); - } - else { - tmp = gk_strdup(path); - *(strrchr(tmp, '/')) = '\0'; - return tmp; - } -} - - - -/************************************************************************* -* This function creates a path -**************************************************************************/ -int gk_mkpath(char *pathname) -{ - char tmp[2048]; - - sprintf(tmp, "mkdir -p %s", pathname); - return system(tmp); -} - - -/************************************************************************* -* This function deletes a directory tree and all of its contents -**************************************************************************/ -int gk_rmpath(char *pathname) -{ - char tmp[2048]; - - sprintf(tmp, "rm -r %s", pathname); - return system(tmp); -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/getopt.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/getopt.c deleted file mode 100644 index 437befc8676..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/getopt.c +++ /dev/null @@ -1,854 +0,0 @@ -/*************************************************************************/ -/*! \file getopt.c -\brief Command line parsing - -This file contains a implementation of GNU's Getopt facility. The purpose -for including it here is to ensure portability across different unix- and -windows-based systems. - -\warning -The implementation provided here uses the \c gk_ prefix for all variables -used by the standard Getopt facility to communicate with the program. -So, do read the documentation here. - -\verbatim - Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 - Free Software Foundation, Inc. This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. -\endverbatim -*/ -/*************************************************************************/ - - -#include - -/*************************************************************************/ -/* Local function prototypes */ -/*************************************************************************/ -static void exchange (char **); -static char *gk_getopt_initialize (int, char **, char *); -static int gk_getopt_internal(int argc, char **argv, char *optstring, - struct gk_option *longopts, int *longind, int long_only); - - - -/*************************************************************************/ -/*! \brief For communication arguments to the caller. - -This variable is set by getopt to point at the value of the option argument, -for those options that accept arguments. -*/ -/*************************************************************************/ -char *gk_optarg; - - -/*************************************************************************/ -/*! \brief Index in ARGV of the next element to be scanned. - -This variable is set by getopt to the index of the next element of the argv -array to be processed. Once getopt has found all of the option arguments, -you can use this variable to determine where the remaining non-option arguments -begin. -*/ -/*************************************************************************/ -int gk_optind = 1; - - -/*************************************************************************/ -/*! \brief Controls error reporting for unrecognized options. - -If the value of this variable is nonzero, then getopt prints an error -message to the standard error stream if it encounters an unknown option -character or an option with a missing required argument. This is the default -behavior. If you set this variable to zero, getopt does not print any messages, -but it still returns the character ? to indicate an error. -*/ -/*************************************************************************/ -int gk_opterr = 1; - - -/*************************************************************************/ -/*! \brief Stores unknown option characters - -When getopt encounters an unknown option character or an option with a -missing required argument, it stores that option character in this -variable. You can use this for providing your own diagnostic messages. -*/ -/*************************************************************************/ -int gk_optopt = '?'; - - -/*************************************************************************/ -/* -Records that the getopt facility has been initialized. -*/ -/*************************************************************************/ -int gk_getopt_initialized; - - -/*************************************************************************/ -/* -The next char to be scanned in the option-element in which the last option -character we returned was found. This allows us to pick up the scan where -we left off. - -If this is zero, or a null string, it means resume the scan by advancing -to the next ARGV-element. -*/ -/*************************************************************************/ -static char *nextchar; - - -/*************************************************************************/ -/* -Value of POSIXLY_CORRECT environment variable. -*/ -/*************************************************************************/ -static char *posixly_correct; - - -/*************************************************************************/ -/* -Describe how to deal with options that follow non-option ARGV-elements. - -If the caller did not specify anything, the default is REQUIRE_ORDER if -the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. - -REQUIRE_ORDER means don't recognize them as options; stop option processing -when the first non-option is seen. This is what Unix does. This mode of -operation is selected by either setting the environment variable -POSIXLY_CORRECT, or using `+' as the first character of the list of -option characters. - -PERMUTE is the default. We permute the contents of ARGV as we scan, so -that eventually all the non-options are at the end. This allows options -to be given in any order, even with programs that were not written to -expect this. - -RETURN_IN_ORDER is an option available to programs that were written -to expect options and other ARGV-elements in any order and that care -about the ordering of the two. We describe each non-option ARGV-element -as if it were the argument of an option with character code 1. -Using `-' as the first character of the list of option characters -selects this mode of operation. - -The special argument `--' forces an end of option-scanning regardless -of the value of `ordering'. In the case of RETURN_IN_ORDER, only -`--' can cause `getopt' to return -1 with `gk_optind' != ARGC. -*/ -/*************************************************************************/ -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - - - -/*************************************************************************/ -/* -Describe the part of ARGV that contains non-options that have -been skipped. `first_nonopt' is the index in ARGV of the first of them; -`last_nonopt' is the index after the last of them. -*/ -/*************************************************************************/ -static int first_nonopt; -static int last_nonopt; - - - - - -/*************************************************************************/ -/* -Handle permutation of arguments. - -Exchange two adjacent subsequences of ARGV. -One subsequence is elements [first_nonopt,last_nonopt) -which contains all the non-options that have been skipped so far. -The other is elements [last_nonopt,gk_optind), which contains all -the options processed since those non-options were skipped. - -`first_nonopt' and `last_nonopt' are relocated so that they describe -the new indices of the non-options in ARGV after they are moved. -*/ -/*************************************************************************/ -static void exchange (char **argv) -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = gk_optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - - while (top > middle && middle > bottom) { - if (top - middle > middle - bottom) { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (gk_optind - last_nonopt); - last_nonopt = gk_optind; -} - - - -/*************************************************************************/ -/* -Initialize the internal data when the first call is made. -*/ -/*************************************************************************/ -static char *gk_getopt_initialize (int argc, char **argv, char *optstring) -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = gk_optind; - - nextchar = NULL; - - posixly_correct = getenv("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - if (optstring[0] == '-') { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - - return optstring; -} - - -/*************************************************************************/ -/* - Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `gk_optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `gk_optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `gk_opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `gk_optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `gk_optarg', otherwise `gk_optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - LONGOPTS is a vector of `struct gk_option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. -*/ -/*************************************************************************/ -static int gk_getopt_internal(int argc, char **argv, char *optstring, - struct gk_option *longopts, int *longind, int long_only) -{ - int print_errors = gk_opterr; - if (optstring[0] == ':') - print_errors = 0; - - if (argc < 1) - return -1; - - gk_optarg = NULL; - - if (gk_optind == 0 || !gk_getopt_initialized) { - if (gk_optind == 0) - gk_optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = gk_getopt_initialize (argc, argv, optstring); - gk_getopt_initialized = 1; - } - - /* Test whether ARGV[gk_optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -# define NONOPTION_P (argv[gk_optind][0] != '-' || argv[gk_optind][1] == '\0') - - if (nextchar == NULL || *nextchar == '\0') { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > gk_optind) - last_nonopt = gk_optind; - if (first_nonopt > gk_optind) - first_nonopt = gk_optind; - - if (ordering == PERMUTE) { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != gk_optind) - exchange ((char **) argv); - else if (last_nonopt != gk_optind) - first_nonopt = gk_optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (gk_optind < argc && NONOPTION_P) - gk_optind++; - - last_nonopt = gk_optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (gk_optind != argc && !strcmp (argv[gk_optind], "--")) { - gk_optind++; - - if (first_nonopt != last_nonopt && last_nonopt != gk_optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = gk_optind; - last_nonopt = argc; - - gk_optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (gk_optind == argc) { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - gk_optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) { - if (ordering == REQUIRE_ORDER) - return -1; - gk_optarg = argv[gk_optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[gk_optind] + 1 + (longopts != NULL && argv[gk_optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL && (argv[gk_optind][1] == '-' || (long_only && (argv[gk_optind][2] || !strchr(optstring, argv[gk_optind][1]))))) { - char *nameend; - struct gk_option *p; - struct gk_option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) { - if (!strncmp (p->name, nextchar, nameend - nextchar)) { - if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - } - - if (ambig && !exact) { - if (print_errors) - fprintf(stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[gk_optind]); - - nextchar += strlen (nextchar); - gk_optind++; - gk_optopt = 0; - return '?'; - } - - if (pfound != NULL) { - option_index = indfound; - gk_optind++; - if (*nameend) { - /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ - if (pfound->has_arg) - gk_optarg = nameend + 1; - else { - if (print_errors) { - if (argv[gk_optind - 1][1] == '-') - /* --option */ - fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); - else - /* +option or -option */ - fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[gk_optind - 1][0], pfound->name); - } - - nextchar += strlen (nextchar); - - gk_optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) { - if (gk_optind < argc) - gk_optarg = argv[gk_optind++]; - else { - if (print_errors) - fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]); - nextchar += strlen (nextchar); - gk_optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. Otherwise interpret it as a short option. */ - if (!long_only || argv[gk_optind][1] == '-' || strchr(optstring, *nextchar) == NULL) { - if (print_errors) { - if (argv[gk_optind][1] == '-') - /* --option */ - fprintf(stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); - else - /* +option or -option */ - fprintf(stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[gk_optind][0], nextchar); - } - nextchar = (char *) ""; - gk_optind++; - gk_optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - { - char c = *nextchar++; - char *temp = strchr(optstring, c); - - /* Increment `gk_optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++gk_optind; - - if (temp == NULL || c == ':') { - if (print_errors) { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c); - else - fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); - } - gk_optopt = c; - return '?'; - } - - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') { - char *nameend; - struct gk_option *p; - struct gk_option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') { - gk_optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - gk_optind++; - } - else if (gk_optind == argc) { - if (print_errors) { - /* 1003.2 specifies the format of this message. */ - fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c); - } - gk_optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `gk_optind' once; increment it again when taking next ARGV-elt as argument. */ - gk_optarg = argv[gk_optind++]; - - /* gk_optarg is now the argument, see if it's in the table of longopts. */ - - for (nextchar = nameend = gk_optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) { - if (!strncmp (p->name, nextchar, nameend - nextchar)) { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - } - if (ambig && !exact) { - if (print_errors) - fprintf(stderr, "%s: option `-W %s' is ambiguous\n", argv[0], argv[gk_optind]); - nextchar += strlen (nextchar); - gk_optind++; - return '?'; - } - if (pfound != NULL) { - option_index = indfound; - if (*nameend) { - /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ - if (pfound->has_arg) - gk_optarg = nameend + 1; - else { - if (print_errors) - fprintf(stderr, "%s: option `-W %s' doesn't allow an argument\n", argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) { - if (gk_optind < argc) - gk_optarg = argv[gk_optind++]; - else { - if (print_errors) - fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - - if (temp[1] == ':') { - if (temp[2] == ':') { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') { - gk_optarg = nextchar; - gk_optind++; - } - else - gk_optarg = NULL; - nextchar = NULL; - } - else { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') { - gk_optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ - gk_optind++; - } - else if (gk_optind == argc) { - if (print_errors) { - /* 1003.2 specifies the format of this message. */ - fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c); - } - gk_optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `gk_optind' once; increment it again when taking next ARGV-elt as argument. */ - gk_optarg = argv[gk_optind++]; - nextchar = NULL; - } - } - return c; - } -} - - - -/*************************************************************************/ -/*! \brief Parse command-line arguments - -The gk_getopt() function gets the next option argument from the argument -list specified by the \c argv and \c argc arguments. Normally these values -come directly from the arguments received by main(). - -\param argc is the number of command line arguments passed to main(). -\param argv is an array of strings storing the above command line - arguments. -\param options is a string that specifies the option characters that - are valid for this program. An option character in this string - can be followed by a colon (`:') to indicate that it takes a - required argument. If an option character is followed by two - colons (`::'), its argument is optional; this is a GNU extension. - -\return -It returns the option character for the next command line option. When no -more option arguments are available, it returns -1. There may still be -more non-option arguments; you must compare the external variable -#gk_optind against the \c argc parameter to check this. - -\return -If the option has an argument, gk_getopt() returns the argument by storing -it in the variable #gk_optarg. You don't ordinarily need to copy the -#gk_optarg string, since it is a pointer into the original \c argv array, -not into a static area that might be overwritten. - -\return -If gk_getopt() finds an option character in \c argv that was not included -in options, or a missing option argument, it returns `?' and sets the -external variable #gk_optopt to the actual option character. -If the first character of options is a colon (`:'), then gk_getopt() -returns `:' instead of `?' to indicate a missing option argument. -In addition, if the external variable #gk_opterr is nonzero (which is -the default), gk_getopt() prints an error message. This variable is -set by gk_getopt() to point at the value of the option argument, -for those options that accept arguments. - - -gk_getopt() has three ways to deal with options that follow non-options -\c argv elements. The special argument `--' forces in all cases -the end of option scanning. - - The default is to permute the contents of \c argv while scanning it - so that eventually all the non-options are at the end. This allows - options to be given in any order, even with programs that were not - written to expect this. - - If the options argument string begins with a hyphen (`-'), this is - treated specially. It permits arguments that are not options to be - returned as if they were associated with option character `\\1'. - - POSIX demands the following behavior: The first non-option stops - option processing. This mode is selected by either setting the - environment variable POSIXLY_CORRECT or beginning the options - argument string with a plus sign (`+'). - -*/ -/*************************************************************************/ -int gk_getopt(int argc, char **argv, char *options) -{ - return gk_getopt_internal(argc, argv, options, NULL, NULL, 0); -} - - -/*************************************************************************/ -/*! \brief Parse command-line arguments with long options - -This function accepts GNU-style long options as well as single-character -options. - -\param argc is the number of command line arguments passed to main(). -\param argv is an array of strings storing the above command line - arguments. -\param options describes the short options to accept, just as it does - in gk_getopt(). -\param long_options describes the long options to accept. See the - defintion of ::gk_option for more information. -\param opt_index this is a returned variable. For any long option, - gk_getopt_long() tells you the index in the array \c long_options - of the options definition, by storing it into *opt_index. - You can get the name of the option with longopts[*opt_index].name. - So you can distinguish among long options either by the values - in their val fields or by their indices. You can also distinguish - in this way among long options that set flags. - - -\return -When gk_getopt_long() encounters a short option, it does the same thing -that gk_getopt() would do: it returns the character code for the option, -and stores the options argument (if it has one) in #gk_optarg. - -\return -When gk_getopt_long() encounters a long option, it takes actions based -on the flag and val fields of the definition of that option. - -\return -If flag is a null pointer, then gk_getopt_long() returns the contents -of val to indicate which option it found. You should arrange distinct -values in the val field for options with different meanings, so you -can decode these values after gk_getopt_long() returns. If the long -option is equivalent to a short option, you can use the short option's -character code in val. - -\return -If flag is not a null pointer, that means this option should just set -a flag in the program. The flag is a variable of type int that you -define. Put the address of the flag in the flag field. Put in the -val field the value you would like this option to store in the flag. -In this case, gk_getopt_long() returns 0. - -\return -When a long option has an argument, gk_getopt_long() puts the argument -value in the variable #gk_optarg before returning. When the option has -no argument, the value in #gk_optarg is a null pointer. This is -how you can tell whether an optional argument was supplied. - -\return -When gk_getopt_long() has no more options to handle, it returns -1, -and leaves in the variable #gk_optind the index in argv of the next -remaining argument. -*/ -/*************************************************************************/ -int gk_getopt_long( int argc, char **argv, char *options, - struct gk_option *long_options, int *opt_index) -{ - return gk_getopt_internal (argc, argv, options, long_options, opt_index, 0); -} - - - -/*************************************************************************/ -/*! \brief Parse command-line arguments with only long options - -Like gk_getopt_long(), but '-' as well as '--' can indicate a long option. -If an option that starts with '-' (not '--') doesn't match a long option, -but does match a short option, it is parsed as a short option instead. -*/ -/*************************************************************************/ -int gk_getopt_long_only(int argc, char **argv, char *options, - struct gk_option *long_options, int *opt_index) -{ - return gk_getopt_internal(argc, argv, options, long_options, opt_index, 1); -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_arch.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_arch.h deleted file mode 100644 index 05d783c9e6d..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_arch.h +++ /dev/null @@ -1,61 +0,0 @@ -/*! -\file gk_arch.h -\brief This file contains various architecture-specific declerations - -\date Started 3/27/2007 -\author George -\version\verbatim $Id: gk_arch.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#ifndef _GK_ARCH_H_ -#define _GK_ARCH_H_ - -/************************************************************************* -* Architecture-specific differences in header files -**************************************************************************/ -#ifdef LINUX -#if !defined(__USE_XOPEN) -#define __USE_XOPEN -#endif -#if !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 600 -#endif -#if !defined(__USE_XOPEN2K) -#define __USE_XOPEN2K -#endif -#endif - - -#ifdef HAVE_EXECINFO_H -#include -#endif - - -#ifdef __MSC__ - #include "ms_stdint.h" - #include "ms_inttypes.h" - #include "ms_stat.h" -#else -#ifndef SUNOS - #include -#endif - #include - #include - #include - #include -#endif - - -/************************************************************************* -* Architecture-specific modifications -**************************************************************************/ -#ifdef WIN32 -typedef ptrdiff_t ssize_t; -#endif - - -#ifdef SUNOS -#define PTRDIFF_MAX INT64_MAX -#endif - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_defs.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_defs.h deleted file mode 100644 index d75e72d24b8..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_defs.h +++ /dev/null @@ -1,69 +0,0 @@ -/*! -\file gk_defs.h -\brief This file contains various constants definitions - -\date Started 3/27/2007 -\author George -\version\verbatim $Id: gk_defs.h 12732 2012-09-24 20:54:50Z karypis $ \endverbatim -*/ - -#ifndef _GK_DEFS_H_ -#define _GK_DEFS_H_ - - -#define LTERM (void **) 0 /* List terminator for GKfree() */ - -/* mopt_t types */ -#define GK_MOPT_MARK 1 -#define GK_MOPT_CORE 2 -#define GK_MOPT_HEAP 3 - -#define HTABLE_EMPTY -1 -#define HTABLE_DELETED -2 -#define HTABLE_FIRST 1 -#define HTABLE_NEXT 2 - -/* pdb corruption bit switches */ -#define CRP_ALTLOCS 1 -#define CRP_MISSINGCA 2 -#define CRP_MISSINGBB 4 -#define CRP_MULTICHAIN 8 -#define CRP_MULTICA 16 -#define CRP_MULTIBB 32 - -#define MAXLINELEN 300000 - -/* GKlib signals to standard signal mapping */ -#define SIGMEM SIGABRT -#define SIGERR SIGTERM - - -/* CSR-related defines */ -#define GK_CSR_ROW 1 -#define GK_CSR_COL 2 - -#define GK_CSR_MAXTF 1 -#define GK_CSR_SQRT 2 -#define GK_CSR_POW25 3 -#define GK_CSR_POW65 4 -#define GK_CSR_POW75 5 -#define GK_CSR_POW85 6 -#define GK_CSR_LOG 7 -#define GK_CSR_IDF 8 -#define GK_CSR_IDF2 9 -#define GK_CSR_MAXTF2 10 - -#define GK_CSR_COS 1 -#define GK_CSR_JAC 2 -#define GK_CSR_MIN 3 -#define GK_CSR_AMIN 4 - -#define GK_CSR_FMT_CLUTO 1 -#define GK_CSR_FMT_CSR 2 -#define GK_CSR_FMT_METIS 3 -#define GK_CSR_FMT_BINROW 4 -#define GK_CSR_FMT_BINCOL 5 - -#define GK_GRAPH_FMT_METIS 1 - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_externs.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_externs.h deleted file mode 100644 index 2c0fdd9683f..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_externs.h +++ /dev/null @@ -1,25 +0,0 @@ -/*! -\file gk_externs.h -\brief This file contains definitions of external variables created by GKlib - -\date Started 3/27/2007 -\author George -\version\verbatim $Id: gk_externs.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#ifndef _GK_EXTERNS_H_ -#define _GK_EXTERNS_H_ - - -/************************************************************************* -* Extern variable definition. Hopefully, the __thread makes them thread-safe. -**************************************************************************/ -#ifndef _GK_ERROR_C_ -/* declared in error.c */ -extern __thread int gk_cur_jbufs; -extern __thread jmp_buf gk_jbufs[]; -extern __thread jmp_buf gk_jbuf; - -#endif - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_getopt.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_getopt.h deleted file mode 100644 index 56c27a2c1f9..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_getopt.h +++ /dev/null @@ -1,63 +0,0 @@ -/*! -\file gk_getopt.h -\brief This file contains GNU's externs/structs/prototypes - -\date Started 3/27/2007 -\author George -\version\verbatim $Id: gk_getopt.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#ifndef _GK_GETOPT_H_ -#define _GK_GETOPT_H_ - - -/* Externals from getopt.c */ -extern char *gk_optarg; -extern int gk_optind; -extern int gk_opterr; -extern int gk_optopt; - - -/*! \brief The structure that stores the information about the command-line options - -This structure describes a single long option name for the sake of -gk_getopt_long(). The argument long_options must be an array -of these structures, one for each long option. Terminate the array with -an element containing all zeros. -*/ -struct gk_option { - char *name; /*!< This field is the name of the option. */ - int has_arg; /*!< This field says whether the option takes an argument. - It is an integer, and there are three legitimate values: - no_argument, required_argument and optional_argument. - */ - int *flag; /*!< See the discussion on ::gk_option#val */ - int val; /*!< These fields control how to report or act on the option - when it occurs. - - If flag is a null pointer, then the val is a value which - identifies this option. Often these values are chosen - to uniquely identify particular long options. - - If flag is not a null pointer, it should be the address - of an int variable which is the flag for this option. - The value in val is the value to store in the flag to - indicate that the option was seen. */ -}; - -/* Names for the values of the `has_arg' field of `struct gk_option'. */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - - -/* Function prototypes */ -extern int gk_getopt(int argc, char** argv, char* options); -extern int gk_getopt_long(int argc, char** argv, char* options, - struct gk_option *__longopts, int *__longind); -extern int gk_getopt_long_only (int argc, char** argv, char* options, struct gk_option *__longopts, int *__longind); - - - -#endif - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_macros.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_macros.h deleted file mode 100644 index d1e288bc3d4..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_macros.h +++ /dev/null @@ -1,153 +0,0 @@ -/*! -\file gk_macros.h -\brief This file contains various macros - -\date Started 3/27/2007 -\author George -\version\verbatim $Id: gk_macros.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#ifndef _GK_MACROS_H_ -#define _GK_MACROS_H_ - -/*------------------------------------------------------------- - * Usefull commands - *-------------------------------------------------------------*/ -#define gk_max(a, b) ((a) >= (b) ? (a) : (b)) -#define gk_min(a, b) ((a) >= (b) ? (b) : (a)) -#define gk_max3(a, b, c) ((a) >= (b) && (a) >= (c) ? (a) : ((b) >= (a) && (b) >= (c) ? (b) : (c))) -#define gk_SWAP(a, b, tmp) do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0) -#define INC_DEC(a, b, val) do {(a) += (val); (b) -= (val);} while(0) -#define sign(a, b) ((a >= 0 ? b : -b)) - -#define ONEOVERRANDMAX (1.0/(RAND_MAX+1.0)) -#define RandomInRange(u) ((int) (ONEOVERRANDMAX*(u)*rand())) - -#define gk_abs(x) ((x) >= 0 ? (x) : -(x)) - - -/*------------------------------------------------------------- - * Timing macros - *-------------------------------------------------------------*/ -#define gk_clearcputimer(tmr) (tmr = 0.0) -#define gk_startcputimer(tmr) (tmr -= gk_CPUSeconds()) -#define gk_stopcputimer(tmr) (tmr += gk_CPUSeconds()) -#define gk_getcputimer(tmr) (tmr) - -#define gk_clearwctimer(tmr) (tmr = 0.0) -#define gk_startwctimer(tmr) (tmr -= gk_WClockSeconds()) -#define gk_stopwctimer(tmr) (tmr += gk_WClockSeconds()) -#define gk_getwctimer(tmr) (tmr) - -/*------------------------------------------------------------- - * dbglvl handling macros - *-------------------------------------------------------------*/ -#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd); - - -/*------------------------------------------------------------- - * gracefull library exit macro - *-------------------------------------------------------------*/ -#define GKSETJMP() (setjmp(gk_return_to_entry)) -#define gk_sigcatch() (setjmp(gk_jbufs[gk_cur_jbufs])) - - -/*------------------------------------------------------------- - * Debuging memory leaks - *-------------------------------------------------------------*/ -#ifdef DMALLOC -# define MALLOC_CHECK(ptr) \ - if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \ - printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \ - __LINE__, __FILE__); \ - abort(); \ - } -#else -# define MALLOC_CHECK(ptr) ; -#endif - - -/*------------------------------------------------------------- - * CSR conversion macros - *-------------------------------------------------------------*/ -#define MAKECSR(i, n, a) \ - do { \ - for (i=1; i0; i--) a[i] = a[i-1]; \ - a[0] = 0; \ - } while(0) - -#define SHIFTCSR(i, n, a) \ - do { \ - for (i=n; i>0; i--) a[i] = a[i-1]; \ - a[0] = 0; \ - } while(0) - - -/*------------------------------------------------------------- - * ASSERTS that cannot be turned off! - *-------------------------------------------------------------*/ -#define GKASSERT(expr) \ - if (!(expr)) { \ - printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ - __LINE__, __FILE__); \ - abort(); \ - } - -#define GKASSERTP(expr,msg) \ - if (!(expr)) { \ - printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ - __LINE__, __FILE__); \ - printf msg ; \ - printf("\n"); \ - abort(); \ - } - -#define GKCUASSERT(expr) \ - if (!(expr)) { \ - printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ - __LINE__, __FILE__); \ - } - -#define GKCUASSERTP(expr,msg) \ - if (!(expr)) { \ - printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ - __LINE__, __FILE__); \ - printf msg ; \ - printf("\n"); \ - } - -/*------------------------------------------------------------- - * Program Assertions - *-------------------------------------------------------------*/ -#ifndef NDEBUG -# define ASSERT(expr) \ - if (!(expr)) { \ - printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ - __LINE__, __FILE__); \ - assert(expr); \ - } - -# define ASSERTP(expr,msg) \ - if (!(expr)) { \ - printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ - __LINE__, __FILE__); \ - printf msg ; \ - printf("\n"); \ - assert(expr); \ - } -#else -# define ASSERT(expr) ; -# define ASSERTP(expr,msg) ; -#endif - -#ifndef NDEBUG2 -# define ASSERT2 ASSERT -# define ASSERTP2 ASSERTP -#else -# define ASSERT2(expr) ; -# define ASSERTP2(expr,msg) ; -#endif - - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkblas.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkblas.h deleted file mode 100644 index 7dd96dff27b..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkblas.h +++ /dev/null @@ -1,201 +0,0 @@ -/*! -\file gk_mkblas.h -\brief Templates for BLAS-like routines - -\date Started 3/28/07 -\author George -\version\verbatim $Id: gk_mkblas.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#ifndef _GK_MKBLAS_H_ -#define _GK_MKBLAS_H_ - - -#define GK_MKBLAS(PRFX, TYPE, OUTTYPE) \ -/*************************************************************************/\ -/*! The macro for gk_?incset()-class of routines */\ -/*************************************************************************/\ -TYPE *PRFX ## incset(size_t n, TYPE baseval, TYPE *x)\ -{\ - size_t i;\ -\ - for (i=0; i x[max] ? i : max);\ -\ - return x[max];\ -}\ -\ -\ -/*************************************************************************/\ -/*! The macro for gk_?min()-class of routines */\ -/*************************************************************************/\ -TYPE PRFX ## min(size_t n, TYPE *x)\ -{\ - size_t i, min=0;\ -\ - if (n <= 0) return (TYPE) 0;\ -\ - for (i=1; i x[max] ? i : max);\ -\ - return max;\ -}\ -\ -\ -/*************************************************************************/\ -/*! The macro for gk_?argmin()-class of routines */\ -/*************************************************************************/\ -size_t PRFX ## argmin(size_t n, TYPE *x)\ -{\ - size_t i, min=0;\ -\ - for (i=1; i 0 ? (OUTTYPE)sqrt((double)partial) : (OUTTYPE)0);\ -}\ -\ -\ -/*************************************************************************/\ -/*! The macro for gk_?dot()-class of routines */\ -/**************************************************************************/\ -OUTTYPE PRFX ## dot(size_t n, TYPE *x, size_t incx, TYPE *y, size_t incy)\ -{\ - size_t i;\ - OUTTYPE partial = 0.0;\ - \ - for (i=0; innodes = 0;\ - queue->maxnodes = maxnodes;\ -\ - queue->heap = KVMALLOC(maxnodes, "gk_PQInit: heap");\ - queue->locator = gk_idxsmalloc(maxnodes, -1, "gk_PQInit: locator");\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function resets the priority queue */\ -/**************************************************************************/\ -void FPRFX ## Reset(PQT *queue)\ -{\ - gk_idx_t i;\ - gk_idx_t *locator=queue->locator;\ - KVT *heap=queue->heap;\ -\ - for (i=queue->nnodes-1; i>=0; i--)\ - locator[heap[i].val] = -1;\ - queue->nnodes = 0;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function frees the internal datastructures of the priority queue */\ -/**************************************************************************/\ -void FPRFX ## Free(PQT *queue)\ -{\ - if (queue == NULL) return;\ - gk_free((void **)&queue->heap, &queue->locator, LTERM);\ - queue->maxnodes = 0;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function frees the internal datastructures of the priority queue \ - and the queue itself */\ -/**************************************************************************/\ -void FPRFX ## Destroy(PQT *queue)\ -{\ - if (queue == NULL) return;\ - FPRFX ## Free(queue);\ - gk_free((void **)&queue, LTERM);\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the length of the queue */\ -/**************************************************************************/\ -size_t FPRFX ## Length(PQT *queue)\ -{\ - return queue->nnodes;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function adds an item in the priority queue */\ -/**************************************************************************/\ -int FPRFX ## Insert(PQT *queue, VT node, KT key)\ -{\ - gk_idx_t i, j;\ - gk_idx_t *locator=queue->locator;\ - KVT *heap=queue->heap;\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - ASSERT(locator[node] == -1);\ -\ - i = queue->nnodes++;\ - while (i > 0) {\ - j = (i-1)>>1;\ - if (KEY_LT(key, heap[j].key)) {\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else\ - break;\ - }\ - ASSERT(i >= 0);\ - heap[i].key = key;\ - heap[i].val = node;\ - locator[node] = i;\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - return 0;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function deletes an item from the priority queue */\ -/**************************************************************************/\ -int FPRFX ## Delete(PQT *queue, VT node)\ -{\ - gk_idx_t i, j, nnodes;\ - KT newkey, oldkey;\ - gk_idx_t *locator=queue->locator;\ - KVT *heap=queue->heap;\ -\ - ASSERT(locator[node] != -1);\ - ASSERT(heap[locator[node]].val == node);\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - i = locator[node];\ - locator[node] = -1;\ -\ - if (--queue->nnodes > 0 && heap[queue->nnodes].val != node) {\ - node = heap[queue->nnodes].val;\ - newkey = heap[queue->nnodes].key;\ - oldkey = heap[i].key;\ -\ - if (KEY_LT(newkey, oldkey)) { /* Filter-up */\ - while (i > 0) {\ - j = (i-1)>>1;\ - if (KEY_LT(newkey, heap[j].key)) {\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else\ - break;\ - }\ - }\ - else { /* Filter down */\ - nnodes = queue->nnodes;\ - while ((j=(i<<1)+1) < nnodes) {\ - if (KEY_LT(heap[j].key, newkey)) {\ - if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\ - j++;\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\ - j++;\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else\ - break;\ - }\ - }\ -\ - heap[i].key = newkey;\ - heap[i].val = node;\ - locator[node] = i;\ - }\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - return 0;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function updates the key values associated for a particular item */ \ -/**************************************************************************/\ -void FPRFX ## Update(PQT *queue, VT node, KT newkey)\ -{\ - gk_idx_t i, j, nnodes;\ - KT oldkey;\ - gk_idx_t *locator=queue->locator;\ - KVT *heap=queue->heap;\ -\ - oldkey = heap[locator[node]].key;\ -\ - ASSERT(locator[node] != -1);\ - ASSERT(heap[locator[node]].val == node);\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - i = locator[node];\ -\ - if (KEY_LT(newkey, oldkey)) { /* Filter-up */\ - while (i > 0) {\ - j = (i-1)>>1;\ - if (KEY_LT(newkey, heap[j].key)) {\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else\ - break;\ - }\ - }\ - else { /* Filter down */\ - nnodes = queue->nnodes;\ - while ((j=(i<<1)+1) < nnodes) {\ - if (KEY_LT(heap[j].key, newkey)) {\ - if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\ - j++;\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\ - j++;\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else\ - break;\ - }\ - }\ -\ - heap[i].key = newkey;\ - heap[i].val = node;\ - locator[node] = i;\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - return;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the item at the top of the queue and removes\ - it from the priority queue */\ -/**************************************************************************/\ -VT FPRFX ## GetTop(PQT *queue)\ -{\ - gk_idx_t i, j;\ - gk_idx_t *locator;\ - KVT *heap;\ - VT vtx, node;\ - KT key;\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ -\ - if (queue->nnodes == 0)\ - return -1;\ -\ - queue->nnodes--;\ -\ - heap = queue->heap;\ - locator = queue->locator;\ -\ - vtx = heap[0].val;\ - locator[vtx] = -1;\ -\ - if ((i = queue->nnodes) > 0) {\ - key = heap[i].key;\ - node = heap[i].val;\ - i = 0;\ - while ((j=2*i+1) < queue->nnodes) {\ - if (KEY_LT(heap[j].key, key)) {\ - if (j+1 < queue->nnodes && KEY_LT(heap[j+1].key, heap[j].key))\ - j = j+1;\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else if (j+1 < queue->nnodes && KEY_LT(heap[j+1].key, key)) {\ - j = j+1;\ - heap[i] = heap[j];\ - locator[heap[i].val] = i;\ - i = j;\ - }\ - else\ - break;\ - }\ -\ - heap[i].key = key;\ - heap[i].val = node;\ - locator[node] = i;\ - }\ -\ - ASSERT2(FPRFX ## CheckHeap(queue));\ - return vtx;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the item at the top of the queue. The item is not\ - deleted from the queue. */\ -/**************************************************************************/\ -VT FPRFX ## SeeTopVal(PQT *queue)\ -{\ - return (queue->nnodes == 0 ? -1 : queue->heap[0].val);\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the key of the top item. The item is not\ - deleted from the queue. */\ -/**************************************************************************/\ -KT FPRFX ## SeeTopKey(PQT *queue)\ -{\ - return (queue->nnodes == 0 ? KMAX : queue->heap[0].key);\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the key of a specific item */\ -/**************************************************************************/\ -KT FPRFX ## SeeKey(PQT *queue, VT node)\ -{\ - gk_idx_t *locator;\ - KVT *heap;\ -\ - heap = queue->heap;\ - locator = queue->locator;\ -\ - return heap[locator[node]].key;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the first item in a breadth-first traversal of\ - the heap whose key is less than maxwgt. This function is here due to\ - hMETIS and is not general!*/\ -/**************************************************************************/\ -/*\ -VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts)\ -{\ - gk_idx_t i;\ -\ - if (queue->nnodes == 0)\ - return -1;\ -\ - if (maxwgt <= 1000)\ - return FPRFX ## SeeTopVal(queue);\ -\ - for (i=0; innodes; i++) {\ - if (queue->heap[i].key > 0) {\ - if (wgts[queue->heap[i].val] <= maxwgt)\ - return queue->heap[i].val;\ - }\ - else {\ - if (queue->heap[i/2].key <= 0)\ - break;\ - }\ - }\ -\ - return queue->heap[0].val;\ -\ -}\ -*/\ -\ -\ -/*************************************************************************/\ -/*! This functions checks the consistency of the heap */\ -/**************************************************************************/\ -int FPRFX ## CheckHeap(PQT *queue)\ -{\ - gk_idx_t i, j;\ - size_t nnodes;\ - gk_idx_t *locator;\ - KVT *heap;\ -\ - heap = queue->heap;\ - locator = queue->locator;\ - nnodes = queue->nnodes;\ -\ - if (nnodes == 0)\ - return 1;\ -\ - ASSERT(locator[heap[0].val] == 0);\ - for (i=1; imaxnodes; i++) {\ - if (locator[i] != -1)\ - j++;\ - }\ - ASSERTP(j == nnodes, ("%jd %jd\n", (intmax_t)j, (intmax_t)nnodes));\ -\ - return 1;\ -}\ - - -#define GK_MKPQUEUE_PROTO(FPRFX, PQT, KT, VT)\ - PQT * FPRFX ## Create(size_t maxnodes);\ - void FPRFX ## Init(PQT *queue, size_t maxnodes);\ - void FPRFX ## Reset(PQT *queue);\ - void FPRFX ## Free(PQT *queue);\ - void FPRFX ## Destroy(PQT *queue);\ - size_t FPRFX ## Length(PQT *queue);\ - int FPRFX ## Insert(PQT *queue, VT node, KT key);\ - int FPRFX ## Delete(PQT *queue, VT node);\ - void FPRFX ## Update(PQT *queue, VT node, KT newkey);\ - VT FPRFX ## GetTop(PQT *queue);\ - VT FPRFX ## SeeTopVal(PQT *queue);\ - KT FPRFX ## SeeTopKey(PQT *queue);\ - KT FPRFX ## SeeKey(PQT *queue, VT node);\ - VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts);\ - int FPRFX ## CheckHeap(PQT *queue);\ - - -/* This is how these macros are used -GK_MKPQUEUE(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX) -GK_MKPQUEUE_PROTO(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t) -*/ - - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkpqueue2.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkpqueue2.h deleted file mode 100644 index 10e8ee462de..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkpqueue2.h +++ /dev/null @@ -1,215 +0,0 @@ -/*! -\file gk_mkpqueue2.h -\brief Templates for priority queues that do not utilize locators and as such - they can use different types of values. - -\date Started 4/09/07 -\author George -\version\verbatim $Id: gk_mkpqueue2.h 13005 2012-10-23 22:34:36Z karypis $ \endverbatim -*/ - - -#ifndef _GK_MKPQUEUE2_H -#define _GK_MKPQUEUE2_H - - -#define GK_MKPQUEUE2(FPRFX, PQT, KT, VT, KMALLOC, VMALLOC, KMAX, KEY_LT)\ -/*************************************************************************/\ -/*! This function creates and initializes a priority queue */\ -/**************************************************************************/\ -PQT *FPRFX ## Create2(ssize_t maxnodes)\ -{\ - PQT *queue; \ -\ - if ((queue = (PQT *)gk_malloc(sizeof(PQT), "gk_pqCreate2: queue")) != NULL) {\ - memset(queue, 0, sizeof(PQT));\ - queue->nnodes = 0;\ - queue->maxnodes = maxnodes;\ - queue->keys = KMALLOC(maxnodes, "gk_pqCreate2: keys");\ - queue->vals = VMALLOC(maxnodes, "gk_pqCreate2: vals");\ -\ - if (queue->keys == NULL || queue->vals == NULL)\ - gk_free((void **)&queue->keys, &queue->vals, &queue, LTERM);\ - }\ -\ - return queue;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function resets the priority queue */\ -/**************************************************************************/\ -void FPRFX ## Reset2(PQT *queue)\ -{\ - queue->nnodes = 0;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function frees the internal datastructures of the priority queue */\ -/**************************************************************************/\ -void FPRFX ## Destroy2(PQT **r_queue)\ -{\ - PQT *queue = *r_queue; \ - if (queue == NULL) return;\ - gk_free((void **)&queue->keys, &queue->vals, &queue, LTERM);\ - *r_queue = NULL;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the length of the queue */\ -/**************************************************************************/\ -size_t FPRFX ## Length2(PQT *queue)\ -{\ - return queue->nnodes;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function adds an item in the priority queue. */\ -/**************************************************************************/\ -int FPRFX ## Insert2(PQT *queue, VT val, KT key)\ -{\ - ssize_t i, j;\ - KT *keys=queue->keys;\ - VT *vals=queue->vals;\ -\ - ASSERT2(FPRFX ## CheckHeap2(queue));\ -\ - if (queue->nnodes == queue->maxnodes) \ - return 0;\ -\ - ASSERT2(FPRFX ## CheckHeap2(queue));\ -\ - i = queue->nnodes++;\ - while (i > 0) {\ - j = (i-1)>>1;\ - if (KEY_LT(key, keys[j])) {\ - keys[i] = keys[j];\ - vals[i] = vals[j];\ - i = j;\ - }\ - else\ - break;\ - }\ - ASSERT(i >= 0);\ - keys[i] = key;\ - vals[i] = val;\ -\ - ASSERT2(FPRFX ## CheckHeap2(queue));\ -\ - return 1;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the item at the top of the queue and removes\ - it from the priority queue */\ -/**************************************************************************/\ -int FPRFX ## GetTop2(PQT *queue, VT *r_val)\ -{\ - ssize_t i, j;\ - KT key, *keys=queue->keys;\ - VT val, *vals=queue->vals;\ -\ - ASSERT2(FPRFX ## CheckHeap2(queue));\ -\ - if (queue->nnodes == 0)\ - return 0;\ -\ - queue->nnodes--;\ -\ - *r_val = vals[0];\ -\ - if ((i = queue->nnodes) > 0) {\ - key = keys[i];\ - val = vals[i];\ - i = 0;\ - while ((j=2*i+1) < queue->nnodes) {\ - if (KEY_LT(keys[j], key)) {\ - if (j+1 < queue->nnodes && KEY_LT(keys[j+1], keys[j]))\ - j = j+1;\ - keys[i] = keys[j];\ - vals[i] = vals[j];\ - i = j;\ - }\ - else if (j+1 < queue->nnodes && KEY_LT(keys[j+1], key)) {\ - j = j+1;\ - keys[i] = keys[j];\ - vals[i] = vals[j];\ - i = j;\ - }\ - else\ - break;\ - }\ -\ - keys[i] = key;\ - vals[i] = val;\ - }\ -\ - ASSERT2(FPRFX ## CheckHeap2(queue));\ -\ - return 1;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the item at the top of the queue. The item is not\ - deleted from the queue. */\ -/**************************************************************************/\ -int FPRFX ## SeeTopVal2(PQT *queue, VT *r_val)\ -{\ - if (queue->nnodes == 0) \ - return 0;\ -\ - *r_val = queue->vals[0];\ -\ - return 1;\ -}\ -\ -\ -/*************************************************************************/\ -/*! This function returns the key of the top item. The item is not\ - deleted from the queue. */\ -/**************************************************************************/\ -KT FPRFX ## SeeTopKey2(PQT *queue)\ -{\ - return (queue->nnodes == 0 ? KMAX : queue->keys[0]);\ -}\ -\ -\ -/*************************************************************************/\ -/*! This functions checks the consistency of the heap */\ -/**************************************************************************/\ -int FPRFX ## CheckHeap2(PQT *queue)\ -{\ - ssize_t i;\ - KT *keys=queue->keys;\ -\ - if (queue->nnodes == 0)\ - return 1;\ -\ - for (i=1; innodes; i++) {\ - ASSERT(!KEY_LT(keys[i], keys[(i-1)/2]));\ - }\ - for (i=1; innodes; i++)\ - ASSERT(!KEY_LT(keys[i], keys[0]));\ -\ - return 1;\ -}\ - - -#define GK_MKPQUEUE2_PROTO(FPRFX, PQT, KT, VT)\ - PQT * FPRFX ## Create2(ssize_t maxnodes);\ - void FPRFX ## Reset2(PQT *queue);\ - void FPRFX ## Destroy2(PQT **r_queue);\ - size_t FPRFX ## Length2(PQT *queue);\ - int FPRFX ## Insert2(PQT *queue, VT node, KT key);\ - int FPRFX ## GetTop2(PQT *queue, VT *r_val);\ - int FPRFX ## SeeTopVal2(PQT *queue, VT *r_val);\ - KT FPRFX ## SeeTopKey2(PQT *queue);\ - int FPRFX ## CheckHeap2(PQT *queue);\ - - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkrandom.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkrandom.h deleted file mode 100644 index 68d54fa3f1b..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkrandom.h +++ /dev/null @@ -1,123 +0,0 @@ -/*! -\file -\brief Templates for portable random number generation - -\date Started 5/17/07 -\author George -\version\verbatim $Id: gk_mkrandom.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - - -#ifndef _GK_MKRANDOM_H -#define _GK_MKRANDOM_H - -/*************************************************************************/\ -/*! The generator for the rand() related routines. \ - \params RNGT the datatype that defines the range of values over which\ - random numbers will be generated\ - \params VALT the datatype that defines the contents of the array to \ - be permuted by randArrayPermute() \ - \params FPRFX the function prefix \ -*/\ -/**************************************************************************/\ -#define GK_MKRANDOM(FPRFX, RNGT, VALT)\ -/*************************************************************************/\ -/*! Initializes the generator */ \ -/**************************************************************************/\ -void FPRFX ## srand(RNGT seed) \ -{\ - gk_randinit((uint64_t) seed);\ -}\ -\ -\ -/*************************************************************************/\ -/*! Returns a random number */ \ -/**************************************************************************/\ -RNGT FPRFX ## rand() \ -{\ - if (sizeof(RNGT) <= sizeof(int32_t)) \ - return (RNGT)gk_randint32(); \ - else \ - return (RNGT)gk_randint64(); \ -}\ -\ -\ -/*************************************************************************/\ -/*! Returns a random number between [0, max) */ \ -/**************************************************************************/\ -RNGT FPRFX ## randInRange(RNGT max) \ -{\ - return (RNGT)((FPRFX ## rand())%max); \ -}\ -\ -\ -/*************************************************************************/\ -/*! Randomly permutes the elements of an array p[]. \ - flag == 1, p[i] = i prior to permutation, \ - flag == 0, p[] is not initialized. */\ -/**************************************************************************/\ -void FPRFX ## randArrayPermute(RNGT n, VALT *p, RNGT nshuffles, int flag)\ -{\ - RNGT i, u, v;\ - VALT tmp;\ -\ - if (flag == 1) {\ - for (i=0; ikey < (b)->key) - * GKQSORT(struct elt, arr, n, elt_lt); - * } - * - * And so on. - */ - -/* Swap two items pointed to by A and B using temporary buffer t. */ -#define _GKQSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) - -/* Discontinue quicksort algorithm when partition gets below this size. - This particular magic number was chosen to work best on a Sun 4/260. */ -#define _GKQSORT_MAX_THRESH 4 - -/* The next 4 #defines implement a very fast in-line stack abstraction. */ -#define _GKQSORT_STACK_SIZE (8 * sizeof(size_t)) -#define _GKQSORT_PUSH(top, low, high) (((top->_lo = (low)), (top->_hi = (high)), ++top)) -#define _GKQSORT_POP(low, high, top) ((--top, (low = top->_lo), (high = top->_hi))) -#define _GKQSORT_STACK_NOT_EMPTY (_stack < _top) - - -/* The main code starts here... */ -#define GK_MKQSORT(GKQSORT_TYPE,GKQSORT_BASE,GKQSORT_NELT,GKQSORT_LT) \ -{ \ - GKQSORT_TYPE *const _base = (GKQSORT_BASE); \ - const size_t _elems = (GKQSORT_NELT); \ - GKQSORT_TYPE _hold; \ - \ - if (_elems == 0) \ - return; \ - \ - /* Don't declare two variables of type GKQSORT_TYPE in a single \ - * statement: eg `TYPE a, b;', in case if TYPE is a pointer, \ - * expands to `type* a, b;' wich isn't what we want. \ - */ \ - \ - if (_elems > _GKQSORT_MAX_THRESH) { \ - GKQSORT_TYPE *_lo = _base; \ - GKQSORT_TYPE *_hi = _lo + _elems - 1; \ - struct { \ - GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \ - } _stack[_GKQSORT_STACK_SIZE], *_top = _stack + 1; \ - \ - while (_GKQSORT_STACK_NOT_EMPTY) { \ - GKQSORT_TYPE *_left_ptr; GKQSORT_TYPE *_right_ptr; \ - \ - /* Select median value from among LO, MID, and HI. Rearrange \ - LO and HI so the three values are sorted. This lowers the \ - probability of picking a pathological pivot value and \ - skips a comparison for both the LEFT_PTR and RIGHT_PTR in \ - the while loops. */ \ - \ - GKQSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); \ - \ - if (GKQSORT_LT (_mid, _lo)) \ - _GKQSORT_SWAP (_mid, _lo, _hold); \ - if (GKQSORT_LT (_hi, _mid)) \ - _GKQSORT_SWAP (_mid, _hi, _hold); \ - else \ - goto _jump_over; \ - if (GKQSORT_LT (_mid, _lo)) \ - _GKQSORT_SWAP (_mid, _lo, _hold); \ - _jump_over:; \ - \ - _left_ptr = _lo + 1; \ - _right_ptr = _hi - 1; \ - \ - /* Here's the famous ``collapse the walls'' section of quicksort. \ - Gotta like those tight inner loops! They are the main reason \ - that this algorithm runs much faster than others. */ \ - do { \ - while (GKQSORT_LT (_left_ptr, _mid)) \ - ++_left_ptr; \ - \ - while (GKQSORT_LT (_mid, _right_ptr)) \ - --_right_ptr; \ - \ - if (_left_ptr < _right_ptr) { \ - _GKQSORT_SWAP (_left_ptr, _right_ptr, _hold); \ - if (_mid == _left_ptr) \ - _mid = _right_ptr; \ - else if (_mid == _right_ptr) \ - _mid = _left_ptr; \ - ++_left_ptr; \ - --_right_ptr; \ - } \ - else if (_left_ptr == _right_ptr) { \ - ++_left_ptr; \ - --_right_ptr; \ - break; \ - } \ - } while (_left_ptr <= _right_ptr); \ - \ - /* Set up pointers for next iteration. First determine whether \ - left and right partitions are below the threshold size. If so, \ - ignore one or both. Otherwise, push the larger partition's \ - bounds on the stack and continue sorting the smaller one. */ \ - \ - if (_right_ptr - _lo <= _GKQSORT_MAX_THRESH) { \ - if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \ - /* Ignore both small partitions. */ \ - _GKQSORT_POP (_lo, _hi, _top); \ - else \ - /* Ignore small left partition. */ \ - _lo = _left_ptr; \ - } \ - else if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \ - /* Ignore small right partition. */ \ - _hi = _right_ptr; \ - else if (_right_ptr - _lo > _hi - _left_ptr) { \ - /* Push larger left partition indices. */ \ - _GKQSORT_PUSH (_top, _lo, _right_ptr); \ - _lo = _left_ptr; \ - } \ - else { \ - /* Push larger right partition indices. */ \ - _GKQSORT_PUSH (_top, _left_ptr, _hi); \ - _hi = _right_ptr; \ - } \ - } \ - } \ - \ - /* Once the BASE array is partially sorted by quicksort the rest \ - is completely sorted using insertion sort, since this is efficient \ - for partitions below MAX_THRESH size. BASE points to the \ - beginning of the array to sort, and END_PTR points at the very \ - last element in the array (*not* one beyond it!). */ \ - \ - { \ - GKQSORT_TYPE *const _end_ptr = _base + _elems - 1; \ - GKQSORT_TYPE *_tmp_ptr = _base; \ - register GKQSORT_TYPE *_run_ptr; \ - GKQSORT_TYPE *_thresh; \ - \ - _thresh = _base + _GKQSORT_MAX_THRESH; \ - if (_thresh > _end_ptr) \ - _thresh = _end_ptr; \ - \ - /* Find smallest element in first threshold and place it at the \ - array's beginning. This is the smallest array element, \ - and the operation speeds up insertion sort's inner loop. */ \ - \ - for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) \ - if (GKQSORT_LT (_run_ptr, _tmp_ptr)) \ - _tmp_ptr = _run_ptr; \ - \ - if (_tmp_ptr != _base) \ - _GKQSORT_SWAP (_tmp_ptr, _base, _hold); \ - \ - /* Insertion sort, running from left-hand-side \ - * up to right-hand-side. */ \ - \ - _run_ptr = _base + 1; \ - while (++_run_ptr <= _end_ptr) { \ - _tmp_ptr = _run_ptr - 1; \ - while (GKQSORT_LT (_run_ptr, _tmp_ptr)) \ - --_tmp_ptr; \ - \ - ++_tmp_ptr; \ - if (_tmp_ptr != _run_ptr) { \ - GKQSORT_TYPE *_trav = _run_ptr + 1; \ - while (--_trav >= _run_ptr) { \ - GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \ - _hold = *_trav; \ - \ - for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) \ - *_hi = *_lo; \ - *_hi = _hold; \ - } \ - } \ - } \ - } \ - \ -} - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkutils.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkutils.h deleted file mode 100644 index a092f2227d3..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gk_mkutils.h +++ /dev/null @@ -1,40 +0,0 @@ -/*! -\file -\brief Templates for various utility routines - -\date Started 5/28/07 -\author George -\version\verbatim $Id: gk_mkutils.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#ifndef _GK_MKUTILS_H_ -#define _GK_MKUTILS_H_ - - -#define GK_MKARRAY2CSR(PRFX, TYPE)\ -/*************************************************************************/\ -/*! The macro for gk_?array2csr() routine */\ -/**************************************************************************/\ -void PRFX ## array2csr(TYPE n, TYPE range, TYPE *array, TYPE *ptr, TYPE *ind)\ -{\ - TYPE i;\ -\ - for (i=0; i<=range; i++)\ - ptr[i] = 0;\ -\ - for (i=0; i>1)-2) - -#define PRIGKIDX "zd" -#define SCNGKIDX "zd" - - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gkregex.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gkregex.c deleted file mode 100644 index 8a09caab785..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gkregex.c +++ /dev/null @@ -1,10704 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* this is for removing a compiler warning */ -void gkfooo() { return; } - -#ifdef USE_GKREGEX - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef _LIBC -/* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ - __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ - __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ - __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ - __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ - __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ - __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ - __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) - -# include "../locale/localeinfo.h" -#endif - -#include "GKlib.h" - - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* GKINCLUDE #include "regex_internal.h" */ -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _REGEX_INTERNAL_H -#define _REGEX_INTERNAL_H 1 - -#include -#include -#include -#include -#include - -#if defined(__MINGW32_VERSION) || defined(_MSC_VER) -#define strcasecmp stricmp -#endif - -#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC -# include -#endif -#if defined HAVE_LOCALE_H || defined _LIBC -# include -#endif -#if defined HAVE_WCHAR_H || defined _LIBC -# include -#endif /* HAVE_WCHAR_H || _LIBC */ -#if defined HAVE_WCTYPE_H || defined _LIBC -# include -#endif /* HAVE_WCTYPE_H || _LIBC */ -#if defined HAVE_STDBOOL_H || defined _LIBC -# include -#else -typedef enum { false, true } bool; -#endif /* HAVE_STDBOOL_H || _LIBC */ -#if defined HAVE_STDINT_H || defined _LIBC -# include -#endif /* HAVE_STDINT_H || _LIBC */ -#if defined _LIBC -# include -#else -# define __libc_lock_define(CLASS,NAME) -# define __libc_lock_init(NAME) do { } while (0) -# define __libc_lock_lock(NAME) do { } while (0) -# define __libc_lock_unlock(NAME) do { } while (0) -#endif - -/* In case that the system doesn't have isblank(). */ -#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank -# define isblank(ch) ((ch) == ' ' || (ch) == '\t') -#endif - -#ifdef _LIBC -# ifndef _RE_DEFINE_LOCALE_FUNCTIONS -# define _RE_DEFINE_LOCALE_FUNCTIONS 1 -# include -# include -# include -# endif -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -# include -# ifdef _LIBC -# undef gettext -# define gettext(msgid) \ - INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) -# endif -#else -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif - -/* For loser systems without the definition. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC -# define RE_ENABLE_I18N -#endif - -#if __GNUC__ >= 3 -# define BE(expr, val) __builtin_expect (expr, val) -#else -# define BE(expr, val) (expr) -# define inline -#endif - -/* Number of single byte character. */ -#define SBC_MAX 256 - -#define COLL_ELEM_LEN_MAX 8 - -/* The character which represents newline. */ -#define NEWLINE_CHAR '\n' -#define WIDE_NEWLINE_CHAR L'\n' - -/* Rename to standard API for using out of glibc. */ -#ifndef _LIBC -# define __wctype wctype -# define __iswctype iswctype -# define __btowc btowc -# define __mempcpy mempcpy -# define __wcrtomb wcrtomb -# define __regfree regfree -# define attribute_hidden -#endif /* not _LIBC */ - -#ifdef __GNUC__ -# define __attribute(arg) __attribute__ (arg) -#else -# define __attribute(arg) -#endif - -extern const char __re_error_msgid[] attribute_hidden; -extern const size_t __re_error_msgid_idx[] attribute_hidden; - -/* An integer used to represent a set of bits. It must be unsigned, - and must be at least as wide as unsigned int. */ -typedef unsigned long int bitset_word_t; -/* All bits set in a bitset_word_t. */ -#define BITSET_WORD_MAX ULONG_MAX -/* Number of bits in a bitset_word_t. */ -#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT) -/* Number of bitset_word_t in a bit_set. */ -#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS) -typedef bitset_word_t bitset_t[BITSET_WORDS]; -typedef bitset_word_t *re_bitset_ptr_t; -typedef const bitset_word_t *re_const_bitset_ptr_t; - -#define bitset_set(set,i) \ - (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS) -#define bitset_clear(set,i) \ - (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS)) -#define bitset_contain(set,i) \ - (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS)) -#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t)) -#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t)) -#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t)) - -#define PREV_WORD_CONSTRAINT 0x0001 -#define PREV_NOTWORD_CONSTRAINT 0x0002 -#define NEXT_WORD_CONSTRAINT 0x0004 -#define NEXT_NOTWORD_CONSTRAINT 0x0008 -#define PREV_NEWLINE_CONSTRAINT 0x0010 -#define NEXT_NEWLINE_CONSTRAINT 0x0020 -#define PREV_BEGBUF_CONSTRAINT 0x0040 -#define NEXT_ENDBUF_CONSTRAINT 0x0080 -#define WORD_DELIM_CONSTRAINT 0x0100 -#define NOT_WORD_DELIM_CONSTRAINT 0x0200 - -typedef enum -{ - INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - LINE_FIRST = PREV_NEWLINE_CONSTRAINT, - LINE_LAST = NEXT_NEWLINE_CONSTRAINT, - BUF_FIRST = PREV_BEGBUF_CONSTRAINT, - BUF_LAST = NEXT_ENDBUF_CONSTRAINT, - WORD_DELIM = WORD_DELIM_CONSTRAINT, - NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT -} re_context_type; - -typedef struct -{ - int alloc; - int nelem; - int *elems; -} re_node_set; - -typedef enum -{ - NON_TYPE = 0, - - /* Node type, These are used by token, node, tree. */ - CHARACTER = 1, - END_OF_RE = 2, - SIMPLE_BRACKET = 3, - OP_BACK_REF = 4, - OP_PERIOD = 5, -#ifdef RE_ENABLE_I18N - COMPLEX_BRACKET = 6, - OP_UTF8_PERIOD = 7, -#endif /* RE_ENABLE_I18N */ - - /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used - when the debugger shows values of this enum type. */ -#define EPSILON_BIT 8 - OP_OPEN_SUBEXP = EPSILON_BIT | 0, - OP_CLOSE_SUBEXP = EPSILON_BIT | 1, - OP_ALT = EPSILON_BIT | 2, - OP_DUP_ASTERISK = EPSILON_BIT | 3, - ANCHOR = EPSILON_BIT | 4, - - /* Tree type, these are used only by tree. */ - CONCAT = 16, - SUBEXP = 17, - - /* Token type, these are used only by token. */ - OP_DUP_PLUS = 18, - OP_DUP_QUESTION, - OP_OPEN_BRACKET, - OP_CLOSE_BRACKET, - OP_CHARSET_RANGE, - OP_OPEN_DUP_NUM, - OP_CLOSE_DUP_NUM, - OP_NON_MATCH_LIST, - OP_OPEN_COLL_ELEM, - OP_CLOSE_COLL_ELEM, - OP_OPEN_EQUIV_CLASS, - OP_CLOSE_EQUIV_CLASS, - OP_OPEN_CHAR_CLASS, - OP_CLOSE_CHAR_CLASS, - OP_WORD, - OP_NOTWORD, - OP_SPACE, - OP_NOTSPACE, - BACK_SLASH - -} re_token_type_t; - -#ifdef RE_ENABLE_I18N -typedef struct -{ - /* Multibyte characters. */ - wchar_t *mbchars; - - /* Collating symbols. */ -# ifdef _LIBC - int32_t *coll_syms; -# endif - - /* Equivalence classes. */ -# ifdef _LIBC - int32_t *equiv_classes; -# endif - - /* Range expressions. */ -# ifdef _LIBC - uint32_t *range_starts; - uint32_t *range_ends; -# else /* not _LIBC */ - wchar_t *range_starts; - wchar_t *range_ends; -# endif /* not _LIBC */ - - /* Character classes. */ - wctype_t *char_classes; - - /* If this character set is the non-matching list. */ - unsigned int non_match : 1; - - /* # of multibyte characters. */ - int nmbchars; - - /* # of collating symbols. */ - int ncoll_syms; - - /* # of equivalence classes. */ - int nequiv_classes; - - /* # of range expressions. */ - int nranges; - - /* # of character classes. */ - int nchar_classes; -} re_charset_t; -#endif /* RE_ENABLE_I18N */ - -typedef struct -{ - union - { - unsigned char c; /* for CHARACTER */ - re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; /* for COMPLEX_BRACKET */ -#endif /* RE_ENABLE_I18N */ - int idx; /* for BACK_REF */ - re_context_type ctx_type; /* for ANCHOR */ - } opr; -#if __GNUC__ >= 2 - re_token_type_t type : 8; -#else - re_token_type_t type; -#endif - unsigned int constraint : 10; /* context constraint */ - unsigned int duplicated : 1; - unsigned int opt_subexp : 1; -#ifdef RE_ENABLE_I18N - unsigned int accept_mb : 1; - /* These 2 bits can be moved into the union if needed (e.g. if running out - of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ - unsigned int mb_partial : 1; -#endif - unsigned int word_char : 1; -} re_token_t; - -#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) - -struct re_string_t -{ - /* Indicate the raw buffer which is the original string passed as an - argument of regexec(), re_search(), etc.. */ - const unsigned char *raw_mbs; - /* Store the multibyte string. In case of "case insensitive mode" like - REG_ICASE, upper cases of the string are stored, otherwise MBS points - the same address that RAW_MBS points. */ - unsigned char *mbs; -#ifdef RE_ENABLE_I18N - /* Store the wide character string which is corresponding to MBS. */ - wint_t *wcs; - int *offsets; - mbstate_t cur_state; -#endif - /* Index in RAW_MBS. Each character mbs[i] corresponds to - raw_mbs[raw_mbs_idx + i]. */ - int raw_mbs_idx; - /* The length of the valid characters in the buffers. */ - int valid_len; - /* The corresponding number of bytes in raw_mbs array. */ - int valid_raw_len; - /* The length of the buffers MBS and WCS. */ - int bufs_len; - /* The index in MBS, which is updated by re_string_fetch_byte. */ - int cur_idx; - /* length of RAW_MBS array. */ - int raw_len; - /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ - int len; - /* End of the buffer may be shorter than its length in the cases such - as re_match_2, re_search_2. Then, we use STOP for end of the buffer - instead of LEN. */ - int raw_stop; - /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ - int stop; - - /* The context of mbs[0]. We store the context independently, since - the context of mbs[0] may be different from raw_mbs[0], which is - the beginning of the input string. */ - unsigned int tip_context; - /* The translation passed as a part of an argument of re_compile_pattern. */ - RE_TRANSLATE_TYPE trans; - /* Copy of re_dfa_t's word_char. */ - re_const_bitset_ptr_t word_char; - /* 1 if REG_ICASE. */ - unsigned char icase; - unsigned char is_utf8; - unsigned char map_notascii; - unsigned char mbs_allocated; - unsigned char offsets_needed; - unsigned char newline_anchor; - unsigned char word_ops_used; - int mb_cur_max; -}; -typedef struct re_string_t re_string_t; - - -struct re_dfa_t; -typedef struct re_dfa_t re_dfa_t; - -#ifndef _LIBC -# ifdef __i386__ -# define internal_function __attribute ((regparm (3), stdcall)) -# else -# define internal_function -# endif -#endif - -static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, - int new_buf_len) - internal_function; -#ifdef RE_ENABLE_I18N -static void build_wcs_buffer (re_string_t *pstr) internal_function; -static int build_wcs_upper_buffer (re_string_t *pstr) internal_function; -#endif /* RE_ENABLE_I18N */ -static void build_upper_buffer (re_string_t *pstr) internal_function; -static void re_string_translate_buffer (re_string_t *pstr) internal_function; -static unsigned int re_string_context_at (const re_string_t *input, int idx, - int eflags) - internal_function __attribute ((pure)); -#define re_string_peek_byte(pstr, offset) \ - ((pstr)->mbs[(pstr)->cur_idx + offset]) -#define re_string_fetch_byte(pstr) \ - ((pstr)->mbs[(pstr)->cur_idx++]) -#define re_string_first_byte(pstr, idx) \ - ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) -#define re_string_is_single_byte_char(pstr, idx) \ - ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ - || (pstr)->wcs[(idx) + 1] != WEOF)) -#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) -#define re_string_cur_idx(pstr) ((pstr)->cur_idx) -#define re_string_get_buffer(pstr) ((pstr)->mbs) -#define re_string_length(pstr) ((pstr)->len) -#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) -#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) -#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) - -#ifdef __GNUC__ -# define alloca(size) __builtin_alloca (size) -# define HAVE_ALLOCA 1 -#elif defined(_MSC_VER) -# include -# define alloca _alloca -# define HAVE_ALLOCA 1 -#else -# error No alloca() -#endif - -#ifndef _LIBC -# if HAVE_ALLOCA -/* The OS usually guarantees only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - allocate anything larger than 4096 bytes. Also care for the possibility - of a few compiler-allocated temporary stack slots. */ -# define __libc_use_alloca(n) ((n) < 4032) -# else -/* alloca is implemented with malloc, so just use malloc. */ -# define __libc_use_alloca(n) 0 -# endif -#endif - -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) -#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) -#define re_free(p) free (p) - -struct bin_tree_t -{ - struct bin_tree_t *parent; - struct bin_tree_t *left; - struct bin_tree_t *right; - struct bin_tree_t *first; - struct bin_tree_t *next; - - re_token_t token; - - /* `node_idx' is the index in dfa->nodes, if `type' == 0. - Otherwise `type' indicate the type of this node. */ - int node_idx; -}; -typedef struct bin_tree_t bin_tree_t; - -#define BIN_TREE_STORAGE_SIZE \ - ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) - -struct bin_tree_storage_t -{ - struct bin_tree_storage_t *next; - bin_tree_t data[BIN_TREE_STORAGE_SIZE]; -}; -typedef struct bin_tree_storage_t bin_tree_storage_t; - -#define CONTEXT_WORD 1 -#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) -#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) -#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) - -#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) -#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) -#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) -#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) -#define IS_ORDINARY_CONTEXT(c) ((c) == 0) - -#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') -#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) -#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') -#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) - -#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ - ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ - || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) - -#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ - ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ - || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) - -struct re_dfastate_t -{ - unsigned int hash; - re_node_set nodes; - re_node_set non_eps_nodes; - re_node_set inveclosure; - re_node_set *entrance_nodes; - struct re_dfastate_t **trtable, **word_trtable; - unsigned int context : 4; - unsigned int halt : 1; - /* If this state can accept `multi byte'. - Note that we refer to multibyte characters, and multi character - collating elements as `multi byte'. */ - unsigned int accept_mb : 1; - /* If this state has backreference node(s). */ - unsigned int has_backref : 1; - unsigned int has_constraint : 1; -}; -typedef struct re_dfastate_t re_dfastate_t; - -struct re_state_table_entry -{ - int num; - int alloc; - re_dfastate_t **array; -}; - -/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ - -typedef struct -{ - int next_idx; - int alloc; - re_dfastate_t **array; -} state_array_t; - -/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ - -typedef struct -{ - int node; - int str_idx; /* The position NODE match at. */ - state_array_t path; -} re_sub_match_last_t; - -/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. - And information about the node, whose type is OP_CLOSE_SUBEXP, - corresponding to NODE is stored in LASTS. */ - -typedef struct -{ - int str_idx; - int node; - state_array_t *path; - int alasts; /* Allocation size of LASTS. */ - int nlasts; /* The number of LASTS. */ - re_sub_match_last_t **lasts; -} re_sub_match_top_t; - -struct re_backref_cache_entry -{ - int node; - int str_idx; - int subexp_from; - int subexp_to; - char more; - char unused; - unsigned short int eps_reachable_subexps_map; -}; - -typedef struct -{ - /* The string object corresponding to the input string. */ - re_string_t input; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - const re_dfa_t *const dfa; -#else - const re_dfa_t *dfa; -#endif - /* EFLAGS of the argument of regexec. */ - int eflags; - /* Where the matching ends. */ - int match_last; - int last_node; - /* The state log used by the matcher. */ - re_dfastate_t **state_log; - int state_log_top; - /* Back reference cache. */ - int nbkref_ents; - int abkref_ents; - struct re_backref_cache_entry *bkref_ents; - int max_mb_elem_len; - int nsub_tops; - int asub_tops; - re_sub_match_top_t **sub_tops; -} re_match_context_t; - -typedef struct -{ - re_dfastate_t **sifted_states; - re_dfastate_t **limited_states; - int last_node; - int last_str_idx; - re_node_set limits; -} re_sift_context_t; - -struct re_fail_stack_ent_t -{ - int idx; - int node; - regmatch_t *regs; - re_node_set eps_via_nodes; -}; - -struct re_fail_stack_t -{ - int num; - int alloc; - struct re_fail_stack_ent_t *stack; -}; - -struct re_dfa_t -{ - re_token_t *nodes; - size_t nodes_alloc; - size_t nodes_len; - int *nexts; - int *org_indices; - re_node_set *edests; - re_node_set *eclosures; - re_node_set *inveclosures; - struct re_state_table_entry *state_table; - re_dfastate_t *init_state; - re_dfastate_t *init_state_word; - re_dfastate_t *init_state_nl; - re_dfastate_t *init_state_begbuf; - bin_tree_t *str_tree; - bin_tree_storage_t *str_tree_storage; - re_bitset_ptr_t sb_char; - int str_tree_storage_idx; - - /* number of subexpressions `re_nsub' is in regex_t. */ - unsigned int state_hash_mask; - int init_node; - int nbackref; /* The number of backreference in this dfa. */ - - /* Bitmap expressing which backreference is used. */ - bitset_word_t used_bkref_map; - bitset_word_t completed_bkref_map; - - unsigned int has_plural_match : 1; - /* If this dfa has "multibyte node", which is a backreference or - a node which can accept multibyte character or multi character - collating element. */ - unsigned int has_mb_node : 1; - unsigned int is_utf8 : 1; - unsigned int map_notascii : 1; - unsigned int word_ops_used : 1; - int mb_cur_max; - bitset_t word_char; - reg_syntax_t syntax; - int *subexp_map; -#ifdef DEBUG - char* re_str; -#endif - __libc_lock_define (, lock) -}; - -#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) -#define re_node_set_remove(set,id) \ - (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) -#define re_node_set_empty(p) ((p)->nelem = 0) -#define re_node_set_free(set) re_free ((set)->elems) - - -typedef enum -{ - SB_CHAR, - MB_CHAR, - EQUIV_CLASS, - COLL_SYM, - CHAR_CLASS -} bracket_elem_type; - -typedef struct -{ - bracket_elem_type type; - union - { - unsigned char ch; - unsigned char *name; - wchar_t wch; - } opr; -} bracket_elem_t; - - -/* Inline functions for bitset operation. */ -static inline void -bitset_not (bitset_t set) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - set[bitset_i] = ~set[bitset_i]; -} - -static inline void -bitset_merge (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] |= src[bitset_i]; -} - -static inline void -bitset_mask (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] &= src[bitset_i]; -} - -#ifdef RE_ENABLE_I18N -/* Inline functions for re_string. */ -static inline int -internal_function __attribute ((pure)) -re_string_char_size_at (const re_string_t *pstr, int idx) -{ - int byte_idx; - if (pstr->mb_cur_max == 1) - return 1; - for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) - if (pstr->wcs[idx + byte_idx] != WEOF) - break; - return byte_idx; -} - -static inline wint_t -internal_function __attribute ((pure)) -re_string_wchar_at (const re_string_t *pstr, int idx) -{ - if (pstr->mb_cur_max == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; -} - -static int -internal_function __attribute ((pure)) -re_string_elem_size_at (const re_string_t *pstr, int idx) -{ -# ifdef _LIBC - const unsigned char *p, *extra; - const int32_t *table, *indirect; - int32_t tmp; -# include - uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - - if (nrules != 0) - { - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - p = pstr->mbs + idx; - tmp = findidx (&p); - return p - pstr->mbs - idx; - } - else -# endif /* _LIBC */ - return 1; -} -#endif /* RE_ENABLE_I18N */ - -#endif /* _REGEX_INTERNAL_H */ - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* GKINCLUDE #include "regex_internal.c" */ -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -static void re_string_construct_common (const char *str, int len, - re_string_t *pstr, - RE_TRANSLATE_TYPE trans, int icase, - const re_dfa_t *dfa) internal_function; -static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - unsigned int hash) internal_function; -static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - unsigned int context, - unsigned int hash) internal_function; - -/* Functions for string operation. */ - -/* This function allocate the buffers. It is necessary to call - re_string_reconstruct before using the object. */ - -static reg_errcode_t -internal_function -re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, - RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - int init_buf_len; - - /* Ensure at least one character fits into the buffers. */ - if (init_len < dfa->mb_cur_max) - init_len = dfa->mb_cur_max; - init_buf_len = (len + 1 < init_len) ? len + 1: init_len; - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - ret = re_string_realloc_buffers (pstr, init_buf_len); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - pstr->word_char = dfa->word_char; - pstr->word_ops_used = dfa->word_ops_used; - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; - pstr->valid_raw_len = pstr->valid_len; - return REG_NOERROR; -} - -/* This function allocate the buffers, and initialize them. */ - -static reg_errcode_t -internal_function -re_string_construct (re_string_t *pstr, const char *str, int len, - RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - memset (pstr, '\0', sizeof (re_string_t)); - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - if (len > 0) - { - ret = re_string_realloc_buffers (pstr, len + 1); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - - if (icase) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - if (pstr->valid_raw_len >= len) - break; - if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) - break; - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (trans != NULL) - re_string_translate_buffer (pstr); - else - { - pstr->valid_len = pstr->bufs_len; - pstr->valid_raw_len = pstr->bufs_len; - } - } - } - - return REG_NOERROR; -} - -/* Helper functions for re_string_allocate, and re_string_construct. */ - -static reg_errcode_t -internal_function -re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) -{ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); - if (BE (new_wcs == NULL, 0)) - return REG_ESPACE; - pstr->wcs = new_wcs; - if (pstr->offsets != NULL) - { - int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len); - if (BE (new_offsets == NULL, 0)) - return REG_ESPACE; - pstr->offsets = new_offsets; - } - } -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - { - unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, - new_buf_len); - if (BE (new_mbs == NULL, 0)) - return REG_ESPACE; - pstr->mbs = new_mbs; - } - pstr->bufs_len = new_buf_len; - return REG_NOERROR; -} - - -static void -internal_function -re_string_construct_common (const char *str, int len, re_string_t *pstr, - RE_TRANSLATE_TYPE trans, int icase, - const re_dfa_t *dfa) -{ - pstr->raw_mbs = (const unsigned char *) str; - pstr->len = len; - pstr->raw_len = len; - pstr->trans = trans; - pstr->icase = icase ? 1 : 0; - pstr->mbs_allocated = (trans != NULL || icase); - pstr->mb_cur_max = dfa->mb_cur_max; - pstr->is_utf8 = dfa->is_utf8; - pstr->map_notascii = dfa->map_notascii; - pstr->stop = pstr->len; - pstr->raw_stop = pstr->stop; -} - -#ifdef RE_ENABLE_I18N - -/* Build wide character buffer PSTR->WCS. - If the byte sequence of the string are: - (0), (1), (0), (1), - Then wide character buffer will be: - , WEOF , , WEOF , - We use WEOF for padding, they indicate that the position isn't - a first byte of a multibyte character. - - Note that this function assumes PSTR->VALID_LEN elements are already - built and starts from PSTR->VALID_LEN. */ - -static void -internal_function -build_wcs_buffer (re_string_t *pstr) -{ -#ifdef _LIBC - unsigned char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - unsigned char buf[64]; -#endif - mbstate_t prev_st; - int byte_idx, end_idx, remain_len; - size_t mbclen; - - /* Build the buffers from pstr->valid_len to either pstr->len or - pstr->bufs_len. */ - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - for (byte_idx = pstr->valid_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - /* Apply the translation if we need. */ - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; - buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; - mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a singlebyte character. */ - mbclen = 1; - wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - if (BE (pstr->trans != NULL, 0)) - wc = pstr->trans[wc]; - pstr->cur_state = prev_st; - } - - /* Write wide character and padding. */ - pstr->wcs[byte_idx++] = wc; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; -} - -/* Build wide character buffer PSTR->WCS like build_wcs_buffer, - but for REG_ICASE. */ - -static reg_errcode_t -internal_function -build_wcs_upper_buffer (re_string_t *pstr) -{ - mbstate_t prev_st; - int src_idx, byte_idx, end_idx, remain_len; - size_t mbclen; -#ifdef _LIBC - char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - char buf[64]; -#endif - - byte_idx = pstr->valid_len; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - /* The following optimization assumes that ASCII characters can be - mapped to wide characters with a simple cast. */ - if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) - { - while (byte_idx < end_idx) - { - wchar_t wc; - - if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) - && mbsinit (&pstr->cur_state)) - { - /* In case of a singlebyte character. */ - pstr->mbs[byte_idx] - = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); - /* The next step uses the assumption that wchar_t is encoded - ASCII-safe: all ASCII values can be converted like this. */ - pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; - ++byte_idx; - continue; - } - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - mbclen = mbrtowc (&wc, - ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx - + byte_idx), remain_len, &pstr->cur_state); - if (BE (mbclen + 2 > 2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb (buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else - { - src_idx = byte_idx; - goto offsets_needed; - } - } - else - memcpy (pstr->mbs + byte_idx, - pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - pstr->mbs[byte_idx] = ch; - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; - return REG_NOERROR; - } - else - for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - offsets_needed: - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; - buf[i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; - mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen + 2 > 2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else if (mbcdlen != (size_t) -1) - { - size_t i; - - if (byte_idx + mbcdlen > pstr->bufs_len) - { - pstr->cur_state = prev_st; - break; - } - - if (pstr->offsets == NULL) - { - pstr->offsets = re_malloc (int, pstr->bufs_len); - - if (pstr->offsets == NULL) - return REG_ESPACE; - } - if (!pstr->offsets_needed) - { - for (i = 0; i < (size_t) byte_idx; ++i) - pstr->offsets[i] = i; - pstr->offsets_needed = 1; - } - - memcpy (pstr->mbs + byte_idx, buf, mbcdlen); - pstr->wcs[byte_idx] = wcu; - pstr->offsets[byte_idx] = src_idx; - for (i = 1; i < mbcdlen; ++i) - { - pstr->offsets[byte_idx + i] - = src_idx + (i < mbclen ? i : mbclen - 1); - pstr->wcs[byte_idx + i] = WEOF; - } - pstr->len += mbcdlen - mbclen; - if (pstr->raw_stop > src_idx) - pstr->stop += mbcdlen - mbclen; - end_idx = (pstr->bufs_len > pstr->len) - ? pstr->len : pstr->bufs_len; - byte_idx += mbcdlen; - src_idx += mbclen; - continue; - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - - if (BE (pstr->offsets_needed != 0, 0)) - { - size_t i; - for (i = 0; i < mbclen; ++i) - pstr->offsets[byte_idx + i] = src_idx + i; - } - src_idx += mbclen; - - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; - - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans [ch]; - pstr->mbs[byte_idx] = ch; - - if (BE (pstr->offsets_needed != 0, 0)) - pstr->offsets[byte_idx] = src_idx; - ++src_idx; - - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = src_idx; - return REG_NOERROR; -} - -/* Skip characters until the index becomes greater than NEW_RAW_IDX. - Return the index. */ - -static int -internal_function -re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc) -{ - mbstate_t prev_st; - int rawbuf_idx; - size_t mbclen; - wchar_t wc = WEOF; - - /* Skip the characters which are not necessary to check. */ - for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; - rawbuf_idx < new_raw_idx;) - { - int remain_len; - remain_len = pstr->len - rawbuf_idx; - prev_st = pstr->cur_state; - mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, - remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a single byte character. */ - if (mbclen == 0 || remain_len == 0) - wc = L'\0'; - else - wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); - mbclen = 1; - pstr->cur_state = prev_st; - } - /* Then proceed the next character. */ - rawbuf_idx += mbclen; - } - *last_wc = (wint_t) wc; - return rawbuf_idx; -} -#endif /* RE_ENABLE_I18N */ - -/* Build the buffer PSTR->MBS, and apply the translation if we need. - This function is used in case of REG_ICASE. */ - -static void -internal_function -build_upper_buffer (re_string_t *pstr) -{ - int char_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans[ch]; - if (islower (ch)) - pstr->mbs[char_idx] = toupper (ch); - else - pstr->mbs[char_idx] = ch; - } - pstr->valid_len = char_idx; - pstr->valid_raw_len = char_idx; -} - -/* Apply TRANS to the buffer in PSTR. */ - -static void -internal_function -re_string_translate_buffer (re_string_t *pstr) -{ - int buf_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; - pstr->mbs[buf_idx] = pstr->trans[ch]; - } - - pstr->valid_len = buf_idx; - pstr->valid_raw_len = buf_idx; -} - -/* This function re-construct the buffers. - Concretely, convert to wide character in case of pstr->mb_cur_max > 1, - convert to upper case in case of REG_ICASE, apply translation. */ - -static reg_errcode_t -internal_function -re_string_reconstruct (re_string_t *pstr, int idx, int eflags) -{ - int offset = idx - pstr->raw_mbs_idx; - if (BE (offset < 0, 0)) - { - /* Reset buffer. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); -#endif /* RE_ENABLE_I18N */ - pstr->len = pstr->raw_len; - pstr->stop = pstr->raw_stop; - pstr->valid_len = 0; - pstr->raw_mbs_idx = 0; - pstr->valid_raw_len = 0; - pstr->offsets_needed = 0; - pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (!pstr->mbs_allocated) - pstr->mbs = (unsigned char *) pstr->raw_mbs; - offset = idx; - } - - if (BE (offset != 0, 1)) - { - /* Should the already checked characters be kept? */ - if (BE (offset < pstr->valid_raw_len, 1)) - { - /* Yes, move them to the front of the buffer. */ -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - int low = 0, high = pstr->valid_len, mid; - do - { - mid = (high + low) / 2; - if (pstr->offsets[mid] > offset) - high = mid; - else if (pstr->offsets[mid] < offset) - low = mid + 1; - else - break; - } - while (low < high); - if (pstr->offsets[mid] < offset) - ++mid; - pstr->tip_context = re_string_context_at (pstr, mid - 1, - eflags); - /* This can be quite complicated, so handle specially - only the common and easy case where the character with - different length representation of lower and upper - case is present at or after offset. */ - if (pstr->valid_len > offset - && mid == offset && pstr->offsets[mid] == offset) - { - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; - for (low = 0; low < pstr->valid_len; low++) - pstr->offsets[low] = pstr->offsets[low + offset] - offset; - } - else - { - /* Otherwise, just find out how long the partial multibyte - character at offset is and fill it with WEOF/255. */ - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - while (mid > 0 && pstr->offsets[mid - 1] == offset) - --mid; - while (mid < pstr->valid_len) - if (pstr->wcs[mid] != WEOF) - break; - else - ++mid; - if (mid == pstr->valid_len) - pstr->valid_len = 0; - else - { - pstr->valid_len = pstr->offsets[mid] - offset; - if (pstr->valid_len) - { - for (low = 0; low < pstr->valid_len; ++low) - pstr->wcs[low] = WEOF; - memset (pstr->mbs, 255, pstr->valid_len); - } - } - pstr->valid_raw_len = pstr->valid_len; - } - } - else -#endif - { - pstr->tip_context = re_string_context_at (pstr, offset - 1, - eflags); -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - memmove (pstr->mbs, pstr->mbs + offset, - pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; -#if DEBUG - assert (pstr->valid_len > 0); -#endif - } - } - else - { - /* No, skip all characters until IDX. */ - int prev_valid_len = pstr->valid_len; - -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - } -#endif - pstr->valid_len = 0; -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - int wcs_idx; - wint_t wc = WEOF; - - if (pstr->is_utf8) - { - const unsigned char *raw, *p, *q, *end; - - /* Special case UTF-8. Multi-byte chars start with any - byte other than 0x80 - 0xbf. */ - raw = pstr->raw_mbs + pstr->raw_mbs_idx; - end = raw + (offset - pstr->mb_cur_max); - if (end < pstr->raw_mbs) - end = pstr->raw_mbs; - p = raw + offset - 1; -#ifdef _LIBC - /* We know the wchar_t encoding is UCS4, so for the simple - case, ASCII characters, skip the conversion step. */ - if (isascii (*p) && BE (pstr->trans == NULL, 1)) - { - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - /* pstr->valid_len = 0; */ - wc = (wchar_t) *p; - } - else -#endif - for (; p >= end; --p) - if ((*p & 0xc0) != 0x80) - { - mbstate_t cur_state; - wchar_t wc2; - int mlen = raw + pstr->len - p; - unsigned char buf[6]; - size_t mbclen; - - q = p; - if (BE (pstr->trans != NULL, 0)) - { - int i = mlen < 6 ? mlen : 6; - while (--i >= 0) - buf[i] = pstr->trans[p[i]]; - q = buf; - } - /* XXX Don't use mbrtowc, we know which conversion - to use (UTF-8 -> UCS4). */ - memset (&cur_state, 0, sizeof (cur_state)); - mbclen = mbrtowc (&wc2, (const char *) p, mlen, - &cur_state); - if (raw + offset - p <= mbclen - && mbclen < (size_t) -2) - { - memset (&pstr->cur_state, '\0', - sizeof (mbstate_t)); - pstr->valid_len = mbclen - (raw + offset - p); - wc = wc2; - } - break; - } - } - - if (wc == WEOF) - pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; - if (wc == WEOF) - pstr->tip_context - = re_string_context_at (pstr, prev_valid_len - 1, eflags); - else - pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) - && IS_WIDE_WORD_CHAR (wc)) - ? CONTEXT_WORD - : ((IS_WIDE_NEWLINE (wc) - && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - if (BE (pstr->valid_len, 0)) - { - for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) - pstr->wcs[wcs_idx] = WEOF; - if (pstr->mbs_allocated) - memset (pstr->mbs, 255, pstr->valid_len); - } - pstr->valid_raw_len = pstr->valid_len; - } - else -#endif /* RE_ENABLE_I18N */ - { - int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; - pstr->valid_raw_len = 0; - if (pstr->trans) - c = pstr->trans[c]; - pstr->tip_context = (bitset_contain (pstr->word_char, c) - ? CONTEXT_WORD - : ((IS_NEWLINE (c) && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - } - } - if (!BE (pstr->mbs_allocated, 0)) - pstr->mbs += offset; - } - pstr->raw_mbs_idx = idx; - pstr->len -= offset; - pstr->stop -= offset; - - /* Then build the buffers. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - if (pstr->icase) - { - reg_errcode_t ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else - build_wcs_buffer (pstr); - } - else -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - { - if (pstr->icase) - build_upper_buffer (pstr); - else if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - else - pstr->valid_len = pstr->len; - - pstr->cur_idx = 0; - return REG_NOERROR; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_peek_byte_case (const re_string_t *pstr, int idx) -{ - int ch, off; - - /* Handle the common (easiest) cases first. */ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_peek_byte (pstr, idx); - -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1 - && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) - return re_string_peek_byte (pstr, idx); -#endif - - off = pstr->cur_idx + idx; -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - off = pstr->offsets[off]; -#endif - - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - -#ifdef RE_ENABLE_I18N - /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I - this function returns CAPITAL LETTER I instead of first byte of - DOTLESS SMALL LETTER I. The latter would confuse the parser, - since peek_byte_case doesn't advance cur_idx in any way. */ - if (pstr->offsets_needed && !isascii (ch)) - return re_string_peek_byte (pstr, idx); -#endif - - return ch; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_fetch_byte_case (re_string_t *pstr) -{ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_fetch_byte (pstr); - -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - { - int off, ch; - - /* For tr_TR.UTF-8 [[:islower:]] there is - [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip - in that case the whole multi-byte character and return - the original letter. On the other side, with - [[: DOTLESS SMALL LETTER I return [[:I, as doing - anything else would complicate things too much. */ - - if (!re_string_first_byte (pstr, pstr->cur_idx)) - return re_string_fetch_byte (pstr); - - off = pstr->offsets[pstr->cur_idx]; - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - - if (! isascii (ch)) - return re_string_fetch_byte (pstr); - - re_string_skip_bytes (pstr, - re_string_char_size_at (pstr, pstr->cur_idx)); - return ch; - } -#endif - - return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; -} - -static void -internal_function -re_string_destruct (re_string_t *pstr) -{ -#ifdef RE_ENABLE_I18N - re_free (pstr->wcs); - re_free (pstr->offsets); -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - re_free (pstr->mbs); -} - -/* Return the context at IDX in INPUT. */ - -static unsigned int -internal_function -re_string_context_at (const re_string_t *input, int idx, int eflags) -{ - int c; - if (BE (idx < 0, 0)) - /* In this case, we use the value stored in input->tip_context, - since we can't know the character in input->mbs[-1] here. */ - return input->tip_context; - if (BE (idx == input->len, 0)) - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc; - int wc_idx = idx; - while(input->wcs[wc_idx] == WEOF) - { -#ifdef DEBUG - /* It must not happen. */ - assert (wc_idx >= 0); -#endif - --wc_idx; - if (wc_idx < 0) - return input->tip_context; - } - wc = input->wcs[wc_idx]; - if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) - return CONTEXT_WORD; - return (IS_WIDE_NEWLINE (wc) && input->newline_anchor - ? CONTEXT_NEWLINE : 0); - } - else -#endif - { - c = re_string_byte_at (input, idx); - if (bitset_contain (input->word_char, c)) - return CONTEXT_WORD; - return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; - } -} - -/* Functions for set operation. */ - -static reg_errcode_t -internal_function -re_node_set_alloc (re_node_set *set, int size) -{ - set->alloc = size; - set->nelem = 0; - set->elems = re_malloc (int, size); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_1 (re_node_set *set, int elem) -{ - set->alloc = 1; - set->nelem = 1; - set->elems = re_malloc (int, 1); - if (BE (set->elems == NULL, 0)) - { - set->alloc = set->nelem = 0; - return REG_ESPACE; - } - set->elems[0] = elem; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_2 (re_node_set *set, int elem1, int elem2) -{ - set->alloc = 2; - set->elems = re_malloc (int, 2); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - if (elem1 == elem2) - { - set->nelem = 1; - set->elems[0] = elem1; - } - else - { - set->nelem = 2; - if (elem1 < elem2) - { - set->elems[0] = elem1; - set->elems[1] = elem2; - } - else - { - set->elems[0] = elem2; - set->elems[1] = elem1; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_copy (re_node_set *dest, const re_node_set *src) -{ - dest->nelem = src->nelem; - if (src->nelem > 0) - { - dest->alloc = dest->nelem; - dest->elems = re_malloc (int, dest->alloc); - if (BE (dest->elems == NULL, 0)) - { - dest->alloc = dest->nelem = 0; - return REG_ESPACE; - } - memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); - } - else - re_node_set_init_empty (dest); - return REG_NOERROR; -} - -/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. - Note: We assume dest->elems is NULL, when dest->alloc is 0. */ - -static reg_errcode_t -internal_function -re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - int i1, i2, is, id, delta, sbase; - if (src1->nelem == 0 || src2->nelem == 0) - return REG_NOERROR; - - /* We need dest->nelem + 2 * elems_in_intersection; this is a - conservative estimate. */ - if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) - { - int new_alloc = src1->nelem + src2->nelem + dest->alloc; - int *new_elems = re_realloc (dest->elems, int, new_alloc); - if (BE (new_elems == NULL, 0)) - return REG_ESPACE; - dest->elems = new_elems; - dest->alloc = new_alloc; - } - - /* Find the items in the intersection of SRC1 and SRC2, and copy - into the top of DEST those that are not already in DEST itself. */ - sbase = dest->nelem + src1->nelem + src2->nelem; - i1 = src1->nelem - 1; - i2 = src2->nelem - 1; - id = dest->nelem - 1; - for (;;) - { - if (src1->elems[i1] == src2->elems[i2]) - { - /* Try to find the item in DEST. Maybe we could binary search? */ - while (id >= 0 && dest->elems[id] > src1->elems[i1]) - --id; - - if (id < 0 || dest->elems[id] != src1->elems[i1]) - dest->elems[--sbase] = src1->elems[i1]; - - if (--i1 < 0 || --i2 < 0) - break; - } - - /* Lower the highest of the two items. */ - else if (src1->elems[i1] < src2->elems[i2]) - { - if (--i2 < 0) - break; - } - else - { - if (--i1 < 0) - break; - } - } - - id = dest->nelem - 1; - is = dest->nelem + src1->nelem + src2->nelem - 1; - delta = is - sbase + 1; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place; this is more or - less the same loop that is in re_node_set_merge. */ - dest->nelem += delta; - if (delta > 0 && id >= 0) - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (--id < 0) - break; - } - } - - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); - - return REG_NOERROR; -} - -/* Calculate the union set of the sets SRC1 and SRC2. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function -re_node_set_init_union (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - int i1, i2, id; - if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) - { - dest->alloc = src1->nelem + src2->nelem; - dest->elems = re_malloc (int, dest->alloc); - if (BE (dest->elems == NULL, 0)) - return REG_ESPACE; - } - else - { - if (src1 != NULL && src1->nelem > 0) - return re_node_set_init_copy (dest, src1); - else if (src2 != NULL && src2->nelem > 0) - return re_node_set_init_copy (dest, src2); - else - re_node_set_init_empty (dest); - return REG_NOERROR; - } - for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) - { - if (src1->elems[i1] > src2->elems[i2]) - { - dest->elems[id++] = src2->elems[i2++]; - continue; - } - if (src1->elems[i1] == src2->elems[i2]) - ++i2; - dest->elems[id++] = src1->elems[i1++]; - } - if (i1 < src1->nelem) - { - memcpy (dest->elems + id, src1->elems + i1, - (src1->nelem - i1) * sizeof (int)); - id += src1->nelem - i1; - } - else if (i2 < src2->nelem) - { - memcpy (dest->elems + id, src2->elems + i2, - (src2->nelem - i2) * sizeof (int)); - id += src2->nelem - i2; - } - dest->nelem = id; - return REG_NOERROR; -} - -/* Calculate the union set of the sets DEST and SRC. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function -re_node_set_merge (re_node_set *dest, const re_node_set *src) -{ - int is, id, sbase, delta; - if (src == NULL || src->nelem == 0) - return REG_NOERROR; - if (dest->alloc < 2 * src->nelem + dest->nelem) - { - int new_alloc = 2 * (src->nelem + dest->alloc); - int *new_buffer = re_realloc (dest->elems, int, new_alloc); - if (BE (new_buffer == NULL, 0)) - return REG_ESPACE; - dest->elems = new_buffer; - dest->alloc = new_alloc; - } - - if (BE (dest->nelem == 0, 0)) - { - dest->nelem = src->nelem; - memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); - return REG_NOERROR; - } - - /* Copy into the top of DEST the items of SRC that are not - found in DEST. Maybe we could binary search in DEST? */ - for (sbase = dest->nelem + 2 * src->nelem, - is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) - { - if (dest->elems[id] == src->elems[is]) - is--, id--; - else if (dest->elems[id] < src->elems[is]) - dest->elems[--sbase] = src->elems[is--]; - else /* if (dest->elems[id] > src->elems[is]) */ - --id; - } - - if (is >= 0) - { - /* If DEST is exhausted, the remaining items of SRC must be unique. */ - sbase -= is + 1; - memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int)); - } - - id = dest->nelem - 1; - is = dest->nelem + 2 * src->nelem - 1; - delta = is - sbase + 1; - if (delta == 0) - return REG_NOERROR; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place. */ - dest->nelem += delta; - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (--id < 0) - { - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, - delta * sizeof (int)); - break; - } - } - } - - return REG_NOERROR; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have ELEM. - return -1 if an error is occured, return 1 otherwise. */ - -static int -internal_function -re_node_set_insert (re_node_set *set, int elem) -{ - int idx; - /* In case the set is empty. */ - if (set->alloc == 0) - { - if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1)) - return 1; - else - return -1; - } - - if (BE (set->nelem, 0) == 0) - { - /* We already guaranteed above that set->alloc != 0. */ - set->elems[0] = elem; - ++set->nelem; - return 1; - } - - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - int *new_elems; - set->alloc = set->alloc * 2; - new_elems = re_realloc (set->elems, int, set->alloc); - if (BE (new_elems == NULL, 0)) - return -1; - set->elems = new_elems; - } - - /* Move the elements which follows the new element. Test the - first element separately to skip a check in the inner loop. */ - if (elem < set->elems[0]) - { - idx = 0; - for (idx = set->nelem; idx > 0; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - else - { - for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - - /* Insert the new element. */ - set->elems[idx] = elem; - ++set->nelem; - return 1; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have any element greater than or equal to ELEM. - Return -1 if an error is occured, return 1 otherwise. */ - -static int -internal_function -re_node_set_insert_last (re_node_set *set, int elem) -{ - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - int *new_elems; - set->alloc = (set->alloc + 1) * 2; - new_elems = re_realloc (set->elems, int, set->alloc); - if (BE (new_elems == NULL, 0)) - return -1; - set->elems = new_elems; - } - - /* Insert the new element. */ - set->elems[set->nelem++] = elem; - return 1; -} - -/* Compare two node sets SET1 and SET2. - return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */ - -static int -internal_function __attribute ((pure)) -re_node_set_compare (const re_node_set *set1, const re_node_set *set2) -{ - int i; - if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) - return 0; - for (i = set1->nelem ; --i >= 0 ; ) - if (set1->elems[i] != set2->elems[i]) - return 0; - return 1; -} - -/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ - -static int -internal_function __attribute ((pure)) -re_node_set_contains (const re_node_set *set, int elem) -{ - unsigned int idx, right, mid; - if (set->nelem <= 0) - return 0; - - /* Binary search the element. */ - idx = 0; - right = set->nelem - 1; - while (idx < right) - { - mid = (idx + right) / 2; - if (set->elems[mid] < elem) - idx = mid + 1; - else - right = mid; - } - return set->elems[idx] == elem ? idx + 1 : 0; -} - -static void -internal_function -re_node_set_remove_at (re_node_set *set, int idx) -{ - if (idx < 0 || idx >= set->nelem) - return; - --set->nelem; - for (; idx < set->nelem; idx++) - set->elems[idx] = set->elems[idx + 1]; -} - - -/* Add the token TOKEN to dfa->nodes, and return the index of the token. - Or return -1, if an error will be occured. */ - -static int -internal_function -re_dfa_add_node (re_dfa_t *dfa, re_token_t token) -{ - int type = token.type; - if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) - { - size_t new_nodes_alloc = dfa->nodes_alloc * 2; - int *new_nexts, *new_indices; - re_node_set *new_edests, *new_eclosures; - re_token_t *new_nodes; - - /* Avoid overflows. */ - if (BE (new_nodes_alloc < dfa->nodes_alloc, 0)) - return -1; - - new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); - if (BE (new_nodes == NULL, 0)) - return -1; - dfa->nodes = new_nodes; - new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc); - new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc); - new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); - new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); - if (BE (new_nexts == NULL || new_indices == NULL - || new_edests == NULL || new_eclosures == NULL, 0)) - return -1; - dfa->nexts = new_nexts; - dfa->org_indices = new_indices; - dfa->edests = new_edests; - dfa->eclosures = new_eclosures; - dfa->nodes_alloc = new_nodes_alloc; - } - dfa->nodes[dfa->nodes_len] = token; - dfa->nodes[dfa->nodes_len].constraint = 0; -#ifdef RE_ENABLE_I18N - dfa->nodes[dfa->nodes_len].accept_mb = - (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; -#endif - dfa->nexts[dfa->nodes_len] = -1; - re_node_set_init_empty (dfa->edests + dfa->nodes_len); - re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); - return dfa->nodes_len++; -} - -static inline unsigned int -internal_function -calc_state_hash (const re_node_set *nodes, unsigned int context) -{ - unsigned int hash = nodes->nelem + context; - int i; - for (i = 0 ; i < nodes->nelem ; i++) - hash += nodes->elems[i]; - return hash; -} - -/* Search for the state whose node_set is equivalent to NODES. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function -re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes) -{ - unsigned int hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - int i; - if (BE (nodes->nelem == 0, 0)) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, 0); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (hash != state->hash) - continue; - if (re_node_set_compare (&state->nodes, nodes)) - return state; - } - - /* There are no appropriate state in the dfa, create the new one. */ - new_state = create_ci_newstate (dfa, nodes, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Search for the state whose node_set is equivalent to NODES and - whose context is equivalent to CONTEXT. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function -re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes, unsigned int context) -{ - unsigned int hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - int i; - if (nodes->nelem == 0) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, context); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (state->hash == hash - && state->context == context - && re_node_set_compare (state->entrance_nodes, nodes)) - return state; - } - /* There are no appropriate state in `dfa', create the new one. */ - new_state = create_cd_newstate (dfa, nodes, context, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Finish initialization of the new state NEWSTATE, and using its hash value - HASH put in the appropriate bucket of DFA's state table. Return value - indicates the error code if failed. */ - -static reg_errcode_t -register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, - unsigned int hash) -{ - struct re_state_table_entry *spot; - reg_errcode_t err; - int i; - - newstate->hash = hash; - err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < newstate->nodes.nelem; i++) - { - int elem = newstate->nodes.elems[i]; - if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - re_node_set_insert_last (&newstate->non_eps_nodes, elem); - } - - spot = dfa->state_table + (hash & dfa->state_hash_mask); - if (BE (spot->alloc <= spot->num, 0)) - { - int new_alloc = 2 * spot->num + 2; - re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, - new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - spot->array = new_array; - spot->alloc = new_alloc; - } - spot->array[spot->num++] = newstate; - return REG_NOERROR; -} - -static void -free_state (re_dfastate_t *state) -{ - re_node_set_free (&state->non_eps_nodes); - re_node_set_free (&state->inveclosure); - if (state->entrance_nodes != &state->nodes) - { - re_node_set_free (state->entrance_nodes); - re_free (state->entrance_nodes); - } - re_node_set_free (&state->nodes); - re_free (state->word_trtable); - re_free (state->trtable); - re_free (state); -} - -/* Create the new state which is independ of contexts. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function -create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - unsigned int hash) -{ - int i; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->entrance_nodes = &newstate->nodes; - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (type == CHARACTER && !node->constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR || node->constraint) - newstate->has_constraint = 1; - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} - -/* Create the new state which is depend on the context CONTEXT. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function -create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - unsigned int context, unsigned int hash) -{ - int i, nctx_nodes = 0; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->context = context; - newstate->entrance_nodes = &newstate->nodes; - - for (i = 0 ; i < nodes->nelem ; i++) - { - unsigned int constraint = 0; - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (node->constraint) - constraint = node->constraint; - - if (type == CHARACTER && !constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR) - constraint = node->opr.ctx_type; - - if (constraint) - { - if (newstate->entrance_nodes == &newstate->nodes) - { - newstate->entrance_nodes = re_malloc (re_node_set, 1); - if (BE (newstate->entrance_nodes == NULL, 0)) - { - free_state (newstate); - return NULL; - } - re_node_set_init_copy (newstate->entrance_nodes, nodes); - nctx_nodes = 0; - newstate->has_constraint = 1; - } - - if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) - { - re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); - ++nctx_nodes; - } - } - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* GKINCLUDE #include "regcomp.c" */ -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* Extended regular expression matching and search library. - Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, - size_t length, reg_syntax_t syntax); -static void re_compile_fastmap_iter (regex_t *bufp, - const re_dfastate_t *init_state, - char *fastmap); -static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); -#ifdef RE_ENABLE_I18N -static void free_charset (re_charset_t *cset); -#endif /* RE_ENABLE_I18N */ -static void free_workarea_compile (regex_t *preg); -static reg_errcode_t create_initial_state (re_dfa_t *dfa); -#ifdef RE_ENABLE_I18N -static void optimize_utf8 (re_dfa_t *dfa); -#endif -static reg_errcode_t analyze (regex_t *preg); -static reg_errcode_t preorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t postorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); -static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); -static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, - bin_tree_t *node); -static reg_errcode_t calc_first (void *extra, bin_tree_t *node); -static reg_errcode_t calc_next (void *extra, bin_tree_t *node); -static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); -static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint); -static int search_duplicated_node (const re_dfa_t *dfa, int org_node, - unsigned int constraint); -static reg_errcode_t calc_eclosure (re_dfa_t *dfa); -static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, - int node, int root); -static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); -static int fetch_number (re_string_t *input, re_token_t *token, - reg_syntax_t syntax); -static int peek_token (re_token_t *token, re_string_t *input, - reg_syntax_t syntax) internal_function; -static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - int nest, reg_errcode_t *err); -static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - int nest, reg_errcode_t *err); -static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - int nest, reg_errcode_t *err); -static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - int nest, reg_errcode_t *err); -static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, - re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, - reg_errcode_t *err); -static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token, int token_len, - re_dfa_t *dfa, - reg_syntax_t syntax, - int accept_hyphen); -static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token); -#ifdef RE_ENABLE_I18N -static reg_errcode_t build_equiv_class (bitset_t sbcset, - re_charset_t *mbcset, - int *equiv_class_alloc, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - re_charset_t *mbcset, - int *char_class_alloc, - const unsigned char *class_name, - reg_syntax_t syntax); -#else /* not RE_ENABLE_I18N */ -static reg_errcode_t build_equiv_class (bitset_t sbcset, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - const unsigned char *class_name, - reg_syntax_t syntax); -#endif /* not RE_ENABLE_I18N */ -static bin_tree_t *build_charclass_op (re_dfa_t *dfa, - RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, - int non_match, reg_errcode_t *err); -static bin_tree_t *create_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - re_token_type_t type); -static bin_tree_t *create_token_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - const re_token_t *token); -static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); -static void free_token (re_token_t *node); -static reg_errcode_t free_tree (void *extra, bin_tree_t *node); -static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -const char __re_error_msgid[] attribute_hidden = - { -#define REG_NOERROR_IDX 0 - gettext_noop ("Success") /* REG_NOERROR */ - "\0" -#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") - gettext_noop ("No match") /* REG_NOMATCH */ - "\0" -#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") - gettext_noop ("Invalid regular expression") /* REG_BADPAT */ - "\0" -#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") - gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ - "\0" -#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") - gettext_noop ("Invalid character class name") /* REG_ECTYPE */ - "\0" -#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") - gettext_noop ("Trailing backslash") /* REG_EESCAPE */ - "\0" -#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") - gettext_noop ("Invalid back reference") /* REG_ESUBREG */ - "\0" -#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") - gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ - "\0" -#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") - gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ - "\0" -#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") - gettext_noop ("Unmatched \\{") /* REG_EBRACE */ - "\0" -#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") - gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ - "\0" -#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") - gettext_noop ("Invalid range end") /* REG_ERANGE */ - "\0" -#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") - gettext_noop ("Memory exhausted") /* REG_ESPACE */ - "\0" -#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") - gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ - "\0" -#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") - gettext_noop ("Premature end of regular expression") /* REG_EEND */ - "\0" -#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") - gettext_noop ("Regular expression too big") /* REG_ESIZE */ - "\0" -#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") - gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ - }; - -const size_t __re_error_msgid_idx[] attribute_hidden = - { - REG_NOERROR_IDX, - REG_NOMATCH_IDX, - REG_BADPAT_IDX, - REG_ECOLLATE_IDX, - REG_ECTYPE_IDX, - REG_EESCAPE_IDX, - REG_ESUBREG_IDX, - REG_EBRACK_IDX, - REG_EPAREN_IDX, - REG_EBRACE_IDX, - REG_BADBR_IDX, - REG_ERANGE_IDX, - REG_ESPACE_IDX, - REG_BADRPT_IDX, - REG_EEND_IDX, - REG_ESIZE_IDX, - REG_ERPAREN_IDX - }; - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length LENGTH) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the `allocated' (and perhaps `buffer') and `translate' fields - are set in BUFP on entry. */ - -const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - size_t length; - struct re_pattern_buffer *bufp; -{ - reg_errcode_t ret; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub, unless RE_NO_SUB is set. */ - bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = re_compile_internal (bufp, pattern, length, re_syntax_options); - - if (!ret) - return NULL; - return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} -#ifdef _LIBC -weak_alias (__re_compile_pattern, re_compile_pattern) -#endif - -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; - return ret; -} -#ifdef _LIBC -weak_alias (__re_set_syntax, re_set_syntax) -#endif - -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - char *fastmap = bufp->fastmap; - - memset (fastmap, '\0', sizeof (char) * SBC_MAX); - re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); - if (dfa->init_state != dfa->init_state_word) - re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); - if (dfa->init_state != dfa->init_state_nl) - re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); - if (dfa->init_state != dfa->init_state_begbuf) - re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); - bufp->fastmap_accurate = 1; - return 0; -} -#ifdef _LIBC -weak_alias (__re_compile_fastmap, re_compile_fastmap) -#endif - -static inline void -__attribute ((always_inline)) -re_set_fastmap (char *fastmap, int icase, int ch) -{ - fastmap[ch] = 1; - if (icase) - fastmap[tolower (ch)] = 1; -} - -/* Helper function for re_compile_fastmap. - Compile fastmap for the initial_state INIT_STATE. */ - -static void -re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, - char *fastmap) -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - int node_cnt; - int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); - for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) - { - int node = init_state->nodes.elems[node_cnt]; - re_token_type_t type = dfa->nodes[node].type; - - if (type == CHARACTER) - { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); -#ifdef RE_ENABLE_I18N - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - unsigned char *buf = alloca (dfa->mb_cur_max), *p; - wchar_t wc; - mbstate_t state; - - p = buf; - *p++ = dfa->nodes[node].opr.c; - while (++node < dfa->nodes_len - && dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].mb_partial) - *p++ = dfa->nodes[node].opr.c; - memset (&state, '\0', sizeof (state)); - if (mbrtowc (&wc, (const char *) buf, p - buf, - &state) == p - buf - && (__wcrtomb ((char *) buf, towlower (wc), &state) - != (size_t) -1)) - re_set_fastmap (fastmap, 0, buf[0]); - } -#endif - } - else if (type == SIMPLE_BRACKET) - { - int i, ch; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - { - int j; - bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (w & ((bitset_word_t) 1 << j)) - re_set_fastmap (fastmap, icase, ch); - } - } -#ifdef RE_ENABLE_I18N - else if (type == COMPLEX_BRACKET) - { - int i; - re_charset_t *cset = dfa->nodes[node].opr.mbcset; - if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes - || cset->nranges || cset->nchar_classes) - { -# ifdef _LIBC - if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) - { - /* In this case we want to catch the bytes which are - the first byte of any collation elements. - e.g. In da_DK, we want to catch 'a' since "aa" - is a valid collation element, and don't catch - 'b' since 'b' is the only collation element - which starts from 'b'. */ - const int32_t *table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - for (i = 0; i < SBC_MAX; ++i) - if (table[i] < 0) - re_set_fastmap (fastmap, icase, i); - } -# else - if (dfa->mb_cur_max > 1) - for (i = 0; i < SBC_MAX; ++i) - if (__btowc (i) == WEOF) - re_set_fastmap (fastmap, icase, i); -# endif /* not _LIBC */ - } - for (i = 0; i < cset->nmbchars; ++i) - { - char buf[256]; - mbstate_t state; - memset (&state, '\0', sizeof (state)); - if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) - != (size_t) -1) - re_set_fastmap (fastmap, 0, *(unsigned char *) buf); - } - } - } -#endif /* RE_ENABLE_I18N */ - else if (type == OP_PERIOD -#ifdef RE_ENABLE_I18N - || type == OP_UTF8_PERIOD -#endif /* RE_ENABLE_I18N */ - || type == END_OF_RE) - { - memset (fastmap, '\1', sizeof (char) * SBC_MAX); - if (type == END_OF_RE) - bufp->can_be_null = 1; - return; - } - } -} - -/* Entry point for POSIX code. */ -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' to an allocated space for the fastmap; - `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (preg, pattern, cflags) - regex_t *__restrict preg; - const char *__restrict pattern; - int cflags; -{ - reg_errcode_t ret; - reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED - : RE_SYNTAX_POSIX_BASIC); - - preg->buffer = NULL; - preg->allocated = 0; - preg->used = 0; - - /* Try to allocate space for the fastmap. */ - preg->fastmap = re_malloc (char, SBC_MAX); - if (BE (preg->fastmap == NULL, 0)) - return REG_ESPACE; - - syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - preg->no_sub = !!(cflags & REG_NOSUB); - preg->translate = NULL; - - ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) - ret = REG_EPAREN; - - /* We have already checked preg->fastmap != NULL. */ - if (BE (ret == REG_NOERROR, 1)) - /* Compute the fastmap now, since regexec cannot modify the pattern - buffer. This function never fails in this implementation. */ - (void) re_compile_fastmap (preg); - else - { - /* Some error occurred while compiling the expression. */ - re_free (preg->fastmap); - preg->fastmap = NULL; - } - - return (int) ret; -} -#ifdef _LIBC -weak_alias (__regcomp, regcomp) -#endif - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -/* regerror ( int errcode, preg, errbuf, errbuf_size) */ -size_t -regerror ( - int errcode, - const regex_t *__restrict preg, - char *__restrict errbuf, - size_t errbuf_size) -{ - const char *msg; - size_t msg_size; - - if (BE (errcode < 0 - || errcode >= (int) (sizeof (__re_error_msgid_idx) - / sizeof (__re_error_msgid_idx[0])), 0)) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - abort (); - - msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (BE (errbuf_size != 0, 1)) - { - if (BE (msg_size > errbuf_size, 0)) - { -#if defined HAVE_MEMPCPY || defined _LIBC - *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; -#else - memcpy (errbuf, msg, errbuf_size - 1); - errbuf[errbuf_size - 1] = 0; -#endif - } - else - memcpy (errbuf, msg, msg_size); - } - - return msg_size; -} -#ifdef _LIBC -weak_alias (__regerror, regerror) -#endif - - -#ifdef RE_ENABLE_I18N -/* This static array is used for the map to single-byte characters when - UTF-8 is used. Otherwise we would allocate memory just to initialize - it the same all the time. UTF-8 is the preferred encoding so this is - a worthwhile optimization. */ -static const bitset_t utf8_sb_map = -{ - /* Set the first 128 bits. */ - [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX -}; -#endif - - -static void -free_dfa_content (re_dfa_t *dfa) -{ - int i, j; - - if (dfa->nodes) - for (i = 0; i < dfa->nodes_len; ++i) - free_token (dfa->nodes + i); - re_free (dfa->nexts); - for (i = 0; i < dfa->nodes_len; ++i) - { - if (dfa->eclosures != NULL) - re_node_set_free (dfa->eclosures + i); - if (dfa->inveclosures != NULL) - re_node_set_free (dfa->inveclosures + i); - if (dfa->edests != NULL) - re_node_set_free (dfa->edests + i); - } - re_free (dfa->edests); - re_free (dfa->eclosures); - re_free (dfa->inveclosures); - re_free (dfa->nodes); - - if (dfa->state_table) - for (i = 0; i <= dfa->state_hash_mask; ++i) - { - struct re_state_table_entry *entry = dfa->state_table + i; - for (j = 0; j < entry->num; ++j) - { - re_dfastate_t *state = entry->array[j]; - free_state (state); - } - re_free (entry->array); - } - re_free (dfa->state_table); -#ifdef RE_ENABLE_I18N - if (dfa->sb_char != utf8_sb_map) - re_free (dfa->sb_char); -#endif - re_free (dfa->subexp_map); -#ifdef DEBUG - re_free (dfa->re_str); -#endif - - re_free (dfa); -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (preg) - regex_t *preg; -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - if (BE (dfa != NULL, 1)) - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - - re_free (preg->fastmap); - preg->fastmap = NULL; - - re_free (preg->translate); - preg->translate = NULL; -} -#ifdef _LIBC -weak_alias (__regfree, regfree) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -# ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec above without link errors. */ -weak_function -# endif -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - char *fastmap; - - if (!s) - { - if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); - return 0; - } - - if (re_comp_buf.buffer) - { - fastmap = re_comp_buf.fastmap; - re_comp_buf.fastmap = NULL; - __regfree (&re_comp_buf); - memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); - re_comp_buf.fastmap = fastmap; - } - - if (re_comp_buf.fastmap == NULL) - { - re_comp_buf.fastmap = (char *) malloc (SBC_MAX); - if (re_comp_buf.fastmap == NULL) - return (char *) gettext (__re_error_msgid - + __re_error_msgid_idx[(int) REG_ESPACE]); - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); - - if (!ret) - return NULL; - - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} - -#ifdef _LIBC -libc_freeres_fn (free_mem) -{ - __regfree (&re_comp_buf); -} -#endif - -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. - Compile the regular expression PATTERN, whose length is LENGTH. - SYNTAX indicate regular expression's syntax. */ - -static reg_errcode_t -re_compile_internal (regex_t *preg, const char * pattern, size_t length, - reg_syntax_t syntax) -{ - reg_errcode_t err = REG_NOERROR; - re_dfa_t *dfa; - re_string_t regexp; - - /* Initialize the pattern buffer. */ - preg->fastmap_accurate = 0; - preg->syntax = syntax; - preg->not_bol = preg->not_eol = 0; - preg->used = 0; - preg->re_nsub = 0; - preg->can_be_null = 0; - preg->regs_allocated = REGS_UNALLOCATED; - - /* Initialize the dfa. */ - dfa = (re_dfa_t *) preg->buffer; - if (BE (preg->allocated < sizeof (re_dfa_t), 0)) - { - /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. If ->buffer is NULL this - is a simple allocation. */ - dfa = re_realloc (preg->buffer, re_dfa_t, 1); - if (dfa == NULL) - return REG_ESPACE; - preg->allocated = sizeof (re_dfa_t); - preg->buffer = (unsigned char *) dfa; - } - preg->used = sizeof (re_dfa_t); - - err = init_dfa (dfa, length); - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } -#ifdef DEBUG - /* Note: length+1 will not overflow since it is checked in init_dfa. */ - dfa->re_str = re_malloc (char, length + 1); - strncpy (dfa->re_str, pattern, length + 1); -#endif - - __libc_lock_init (dfa->lock); - - err = re_string_construct (®exp, pattern, length, preg->translate, - syntax & RE_ICASE, dfa); - if (BE (err != REG_NOERROR, 0)) - { - re_compile_internal_free_return: - free_workarea_compile (preg); - re_string_destruct (®exp); - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } - - /* Parse the regular expression, and build a structure tree. */ - preg->re_nsub = 0; - dfa->str_tree = parse (®exp, preg, syntax, &err); - if (BE (dfa->str_tree == NULL, 0)) - goto re_compile_internal_free_return; - - /* Analyze the tree and create the nfa. */ - err = analyze (preg); - if (BE (err != REG_NOERROR, 0)) - goto re_compile_internal_free_return; - -#ifdef RE_ENABLE_I18N - /* If possible, do searching in single byte encoding to speed things up. */ - if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) - optimize_utf8 (dfa); -#endif - - /* Then create the initial state of the dfa. */ - err = create_initial_state (dfa); - - /* Release work areas. */ - free_workarea_compile (preg); - re_string_destruct (®exp); - - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - } - - return err; -} - -/* Initialize DFA. We use the length of the regular expression PAT_LEN - as the initial length of some arrays. */ - -static reg_errcode_t -init_dfa (re_dfa_t *dfa, size_t pat_len) -{ - unsigned int table_size; -#ifndef _LIBC - char *codeset_name; -#endif - - memset (dfa, '\0', sizeof (re_dfa_t)); - - /* Force allocation of str_tree_storage the first time. */ - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - - /* Avoid overflows. */ - if (pat_len == SIZE_MAX) - return REG_ESPACE; - - dfa->nodes_alloc = pat_len + 1; - dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); - - /* table_size = 2 ^ ceil(log pat_len) */ - for (table_size = 1; ; table_size <<= 1) - if (table_size > pat_len) - break; - - dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); - dfa->state_hash_mask = table_size - 1; - - dfa->mb_cur_max = MB_CUR_MAX; -#ifdef _LIBC - if (dfa->mb_cur_max == 6 - && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) - dfa->is_utf8 = 1; - dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) - != 0); -#else -# ifdef HAVE_LANGINFO_CODESET - codeset_name = nl_langinfo (CODESET); -# else - codeset_name = getenv ("LC_ALL"); - if (codeset_name == NULL || codeset_name[0] == '\0') - codeset_name = getenv ("LC_CTYPE"); - if (codeset_name == NULL || codeset_name[0] == '\0') - codeset_name = getenv ("LANG"); - if (codeset_name == NULL) - codeset_name = ""; - else if (strchr (codeset_name, '.') != NULL) - codeset_name = strchr (codeset_name, '.') + 1; -# endif - - if (strcasecmp (codeset_name, "UTF-8") == 0 - || strcasecmp (codeset_name, "UTF8") == 0) - dfa->is_utf8 = 1; - - /* We check exhaustively in the loop below if this charset is a - superset of ASCII. */ - dfa->map_notascii = 0; -#endif - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - if (dfa->is_utf8) - dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; - else - { - int i, j, ch; - - dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - if (BE (dfa->sb_char == NULL, 0)) - return REG_ESPACE; - - /* Set the bits corresponding to single byte chars. */ - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - { - wint_t wch = __btowc (ch); - if (wch != WEOF) - dfa->sb_char[i] |= (bitset_word_t) 1 << j; -# ifndef _LIBC - if (isascii (ch) && wch != ch) - dfa->map_notascii = 1; -# endif - } - } - } -#endif - - if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -/* Initialize WORD_CHAR table, which indicate which character is - "word". In this case "word" means that it is the word construction - character used by some operators like "\<", "\>", etc. */ - -static void -internal_function -init_word_char (re_dfa_t *dfa) -{ - int i, j, ch; - dfa->word_ops_used = 1; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (isalnum (ch) || ch == '_') - dfa->word_char[i] |= (bitset_word_t) 1 << j; -} - -/* Free the work area which are only used while compiling. */ - -static void -free_workarea_compile (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_storage_t *storage, *next; - for (storage = dfa->str_tree_storage; storage; storage = next) - { - next = storage->next; - re_free (storage); - } - dfa->str_tree_storage = NULL; - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - dfa->str_tree = NULL; - re_free (dfa->org_indices); - dfa->org_indices = NULL; -} - -/* Create initial states for all contexts. */ - -static reg_errcode_t -create_initial_state (re_dfa_t *dfa) -{ - int first, i; - reg_errcode_t err; - re_node_set init_nodes; - - /* Initial states have the epsilon closure of the node which is - the first node of the regular expression. */ - first = dfa->str_tree->first->node_idx; - dfa->init_node = first; - err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* The back-references which are in initial states can epsilon transit, - since in this case all of the subexpressions can be null. - Then we add epsilon closures of the nodes which are the next nodes of - the back-references. */ - if (dfa->nbackref > 0) - for (i = 0; i < init_nodes.nelem; ++i) - { - int node_idx = init_nodes.elems[i]; - re_token_type_t type = dfa->nodes[node_idx].type; - - int clexp_idx; - if (type != OP_BACK_REF) - continue; - for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) - { - re_token_t *clexp_node; - clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; - if (clexp_node->type == OP_CLOSE_SUBEXP - && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) - break; - } - if (clexp_idx == init_nodes.nelem) - continue; - - if (type == OP_BACK_REF) - { - int dest_idx = dfa->edests[node_idx].elems[0]; - if (!re_node_set_contains (&init_nodes, dest_idx)) - { - re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - i = 0; - } - } - } - - /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ - if (BE (dfa->init_state == NULL, 0)) - return err; - if (dfa->init_state->has_constraint) - { - dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_WORD); - dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_NEWLINE); - dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, - &init_nodes, - CONTEXT_NEWLINE - | CONTEXT_BEGBUF); - if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return err; - } - else - dfa->init_state_word = dfa->init_state_nl - = dfa->init_state_begbuf = dfa->init_state; - - re_node_set_free (&init_nodes); - return REG_NOERROR; -} - -#ifdef RE_ENABLE_I18N -/* If it is possible to do searching in single byte encoding instead of UTF-8 - to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change - DFA nodes where needed. */ - -static void -optimize_utf8 (re_dfa_t *dfa) -{ - int node, i, mb_chars = 0, has_period = 0; - - for (node = 0; node < dfa->nodes_len; ++node) - switch (dfa->nodes[node].type) - { - case CHARACTER: - if (dfa->nodes[node].opr.c >= 0x80) - mb_chars = 1; - break; - case ANCHOR: - switch (dfa->nodes[node].opr.idx) - { - case LINE_FIRST: - case LINE_LAST: - case BUF_FIRST: - case BUF_LAST: - break; - default: - /* Word anchors etc. cannot be handled. */ - return; - } - break; - case OP_PERIOD: - has_period = 1; - break; - case OP_BACK_REF: - case OP_ALT: - case END_OF_RE: - case OP_DUP_ASTERISK: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - break; - case COMPLEX_BRACKET: - return; - case SIMPLE_BRACKET: - /* Just double check. The non-ASCII range starts at 0x80. */ - assert (0x80 % BITSET_WORD_BITS == 0); - for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) - if (dfa->nodes[node].opr.sbcset[i]) - return; - break; - default: - abort (); - } - - if (mb_chars || has_period) - for (node = 0; node < dfa->nodes_len; ++node) - { - if (dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].opr.c >= 0x80) - dfa->nodes[node].mb_partial = 0; - else if (dfa->nodes[node].type == OP_PERIOD) - dfa->nodes[node].type = OP_UTF8_PERIOD; - } - - /* The search can be in single byte locale. */ - dfa->mb_cur_max = 1; - dfa->is_utf8 = 0; - dfa->has_mb_node = dfa->nbackref > 0 || has_period; -} -#endif - -/* Analyze the structure tree, and calculate "first", "next", "edest", - "eclosure", and "inveclosure". */ - -static reg_errcode_t -analyze (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - reg_errcode_t ret; - - /* Allocate arrays. */ - dfa->nexts = re_malloc (int, dfa->nodes_alloc); - dfa->org_indices = re_malloc (int, dfa->nodes_alloc); - dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); - dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); - if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL - || dfa->eclosures == NULL, 0)) - return REG_ESPACE; - - dfa->subexp_map = re_malloc (int, preg->re_nsub); - if (dfa->subexp_map != NULL) - { - int i; - for (i = 0; i < preg->re_nsub; i++) - dfa->subexp_map[i] = i; - preorder (dfa->str_tree, optimize_subexps, dfa); - for (i = 0; i < preg->re_nsub; i++) - if (dfa->subexp_map[i] != i) - break; - if (i == preg->re_nsub) - { - free (dfa->subexp_map); - dfa->subexp_map = NULL; - } - } - - ret = postorder (dfa->str_tree, lower_subexps, preg); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = postorder (dfa->str_tree, calc_first, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - preorder (dfa->str_tree, calc_next, dfa); - ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = calc_eclosure (dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - /* We only need this during the prune_impossible_nodes pass in regexec.c; - skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ - if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) - || dfa->nbackref) - { - dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); - if (BE (dfa->inveclosures == NULL, 0)) - return REG_ESPACE; - ret = calc_inveclosure (dfa); - } - - return ret; -} - -/* Our parse trees are very unbalanced, so we cannot use a stack to - implement parse tree visits. Instead, we use parent pointers and - some hairy code in these two functions. */ -static reg_errcode_t -postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node, *prev; - - for (node = root; ; ) - { - /* Descend down the tree, preferably to the left (or to the right - if that's the only child). */ - while (node->left || node->right) - if (node->left) - node = node->left; - else - node = node->right; - - do - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - if (node->parent == NULL) - return REG_NOERROR; - prev = node; - node = node->parent; - } - /* Go up while we have a node that is reached from the right. */ - while (node->right == prev || node->right == NULL); - node = node->right; - } -} - -static reg_errcode_t -preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node; - - for (node = root; ; ) - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Go to the left node, or up and to the right. */ - if (node->left) - node = node->left; - else - { - bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - if (!node) - return REG_NOERROR; - } - node = node->right; - } - } -} - -/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell - re_search_internal to map the inner one's opr.idx to this one's. Adjust - backreferences as well. Requires a preorder visit. */ -static reg_errcode_t -optimize_subexps (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - - if (node->token.type == OP_BACK_REF && dfa->subexp_map) - { - int idx = node->token.opr.idx; - node->token.opr.idx = dfa->subexp_map[idx]; - dfa->used_bkref_map |= 1 << node->token.opr.idx; - } - - else if (node->token.type == SUBEXP - && node->left && node->left->token.type == SUBEXP) - { - int other_idx = node->left->token.opr.idx; - - node->left = node->left->left; - if (node->left) - node->left->parent = node; - - dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; - if (other_idx < BITSET_WORD_BITS) - dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); - } - - return REG_NOERROR; -} - -/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation - of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ -static reg_errcode_t -lower_subexps (void *extra, bin_tree_t *node) -{ - regex_t *preg = (regex_t *) extra; - reg_errcode_t err = REG_NOERROR; - - if (node->left && node->left->token.type == SUBEXP) - { - node->left = lower_subexp (&err, preg, node->left); - if (node->left) - node->left->parent = node; - } - if (node->right && node->right->token.type == SUBEXP) - { - node->right = lower_subexp (&err, preg, node->right); - if (node->right) - node->right->parent = node; - } - - return err; -} - -static bin_tree_t * -lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *body = node->left; - bin_tree_t *op, *cls, *tree1, *tree; - - if (preg->no_sub - /* We do not optimize empty subexpressions, because otherwise we may - have bad CONCAT nodes with NULL children. This is obviously not - very common, so we do not lose much. An example that triggers - this case is the sed "script" /\(\)/x. */ - && node->left != NULL - && (node->token.opr.idx >= BITSET_WORD_BITS - || !(dfa->used_bkref_map - & ((bitset_word_t) 1 << node->token.opr.idx)))) - return node->left; - - /* Convert the SUBEXP node to the concatenation of an - OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ - op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); - cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); - tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; - tree = create_tree (dfa, op, tree1, CONCAT); - if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - - op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; - op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; - return tree; -} - -/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton - nodes. Requires a postorder visit. */ -static reg_errcode_t -calc_first (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - if (node->token.type == CONCAT) - { - node->first = node->left->first; - node->node_idx = node->left->node_idx; - } - else - { - node->first = node; - node->node_idx = re_dfa_add_node (dfa, node->token); - if (BE (node->node_idx == -1, 0)) - return REG_ESPACE; - } - return REG_NOERROR; -} - -/* Pass 2: compute NEXT on the tree. Preorder visit. */ -static reg_errcode_t -calc_next (void *extra, bin_tree_t *node) -{ - switch (node->token.type) - { - case OP_DUP_ASTERISK: - node->left->next = node; - break; - case CONCAT: - node->left->next = node->right->first; - node->right->next = node->next; - break; - default: - if (node->left) - node->left->next = node->next; - if (node->right) - node->right->next = node->next; - break; - } - return REG_NOERROR; -} - -/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ -static reg_errcode_t -link_nfa_nodes (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - int idx = node->node_idx; - reg_errcode_t err = REG_NOERROR; - - switch (node->token.type) - { - case CONCAT: - break; - - case END_OF_RE: - assert (node->next == NULL); - break; - - case OP_DUP_ASTERISK: - case OP_ALT: - { - int left, right; - dfa->has_plural_match = 1; - if (node->left != NULL) - left = node->left->first->node_idx; - else - left = node->next->node_idx; - if (node->right != NULL) - right = node->right->first->node_idx; - else - right = node->next->node_idx; - assert (left > -1); - assert (right > -1); - err = re_node_set_init_2 (dfa->edests + idx, left, right); - } - break; - - case ANCHOR: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); - break; - - case OP_BACK_REF: - dfa->nexts[idx] = node->next->node_idx; - if (node->token.type == OP_BACK_REF) - re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); - break; - - default: - assert (!IS_EPSILON_NODE (node->token.type)); - dfa->nexts[idx] = node->next->node_idx; - break; - } - - return err; -} - -/* Duplicate the epsilon closure of the node ROOT_NODE. - Note that duplicated nodes have constraint INIT_CONSTRAINT in addition - to their own constraint. */ - -static reg_errcode_t -internal_function -duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, - int root_node, unsigned int init_constraint) -{ - int org_node, clone_node, ret; - unsigned int constraint = init_constraint; - for (org_node = top_org_node, clone_node = top_clone_node;;) - { - int org_dest, clone_dest; - if (dfa->nodes[org_node].type == OP_BACK_REF) - { - /* If the back reference epsilon-transit, its destination must - also have the constraint. Then duplicate the epsilon closure - of the destination of the back reference, and store it in - edests of the back reference. */ - org_dest = dfa->nexts[org_node]; - re_node_set_empty (dfa->edests + clone_node); - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == -1, 0)) - return REG_ESPACE; - dfa->nexts[clone_node] = dfa->nexts[org_node]; - ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (ret < 0, 0)) - return REG_ESPACE; - } - else if (dfa->edests[org_node].nelem == 0) - { - /* In case of the node can't epsilon-transit, don't duplicate the - destination and store the original destination as the - destination of the node. */ - dfa->nexts[clone_node] = dfa->nexts[org_node]; - break; - } - else if (dfa->edests[org_node].nelem == 1) - { - /* In case of the node can epsilon-transit, and it has only one - destination. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - if (dfa->nodes[org_node].type == ANCHOR) - { - /* In case of the node has another constraint, append it. */ - if (org_node == root_node && clone_node != org_node) - { - /* ...but if the node is root_node itself, it means the - epsilon closure have a loop, then tie it to the - destination of the root_node. */ - ret = re_node_set_insert (dfa->edests + clone_node, - org_dest); - if (BE (ret < 0, 0)) - return REG_ESPACE; - break; - } - constraint |= dfa->nodes[org_node].opr.ctx_type; - } - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == -1, 0)) - return REG_ESPACE; - ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (ret < 0, 0)) - return REG_ESPACE; - } - else /* dfa->edests[org_node].nelem == 2 */ - { - /* In case of the node can epsilon-transit, and it has two - destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* Search for a duplicated node which satisfies the constraint. */ - clone_dest = search_duplicated_node (dfa, org_dest, constraint); - if (clone_dest == -1) - { - /* There are no such a duplicated node, create a new one. */ - reg_errcode_t err; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == -1, 0)) - return REG_ESPACE; - ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (ret < 0, 0)) - return REG_ESPACE; - err = duplicate_node_closure (dfa, org_dest, clone_dest, - root_node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - { - /* There are a duplicated node which satisfy the constraint, - use it to avoid infinite loop. */ - ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (ret < 0, 0)) - return REG_ESPACE; - } - - org_dest = dfa->edests[org_node].elems[1]; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == -1, 0)) - return REG_ESPACE; - ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (ret < 0, 0)) - return REG_ESPACE; - } - org_node = org_dest; - clone_node = clone_dest; - } - return REG_NOERROR; -} - -/* Search for a node which is duplicated from the node ORG_NODE, and - satisfies the constraint CONSTRAINT. */ - -static int -search_duplicated_node (const re_dfa_t *dfa, int org_node, - unsigned int constraint) -{ - int idx; - for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) - { - if (org_node == dfa->org_indices[idx] - && constraint == dfa->nodes[idx].constraint) - return idx; /* Found. */ - } - return -1; /* Not found. */ -} - -/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. - Return the index of the new node, or -1 if insufficient storage is - available. */ - -static int -duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint) -{ - int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); - if (BE (dup_idx != -1, 1)) - { - dfa->nodes[dup_idx].constraint = constraint; - if (dfa->nodes[org_idx].type == ANCHOR) - dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; - dfa->nodes[dup_idx].duplicated = 1; - - /* Store the index of the original node. */ - dfa->org_indices[dup_idx] = org_idx; - } - return dup_idx; -} - -static reg_errcode_t -calc_inveclosure (re_dfa_t *dfa) -{ - int src, idx, ret; - for (idx = 0; idx < dfa->nodes_len; ++idx) - re_node_set_init_empty (dfa->inveclosures + idx); - - for (src = 0; src < dfa->nodes_len; ++src) - { - int *elems = dfa->eclosures[src].elems; - for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) - { - ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); - if (BE (ret == -1, 0)) - return REG_ESPACE; - } - } - - return REG_NOERROR; -} - -/* Calculate "eclosure" for all the node in DFA. */ - -static reg_errcode_t -calc_eclosure (re_dfa_t *dfa) -{ - int node_idx, incomplete; -#ifdef DEBUG - assert (dfa->nodes_len > 0); -#endif - incomplete = 0; - /* For each nodes, calculate epsilon closure. */ - for (node_idx = 0; ; ++node_idx) - { - reg_errcode_t err; - re_node_set eclosure_elem; - if (node_idx == dfa->nodes_len) - { - if (!incomplete) - break; - incomplete = 0; - node_idx = 0; - } - -#ifdef DEBUG - assert (dfa->eclosures[node_idx].nelem != -1); -#endif - - /* If we have already calculated, skip it. */ - if (dfa->eclosures[node_idx].nelem != 0) - continue; - /* Calculate epsilon closure of `node_idx'. */ - err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (dfa->eclosures[node_idx].nelem == 0) - { - incomplete = 1; - re_node_set_free (&eclosure_elem); - } - } - return REG_NOERROR; -} - -/* Calculate epsilon closure of NODE. */ - -static reg_errcode_t -calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root) -{ - reg_errcode_t err; - unsigned int constraint; - int i, incomplete; - re_node_set eclosure; - incomplete = 0; - err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* This indicates that we are calculating this node now. - We reference this value to avoid infinite loop. */ - dfa->eclosures[node].nelem = -1; - - constraint = ((dfa->nodes[node].type == ANCHOR) - ? dfa->nodes[node].opr.ctx_type : 0); - /* If the current node has constraints, duplicate all nodes. - Since they must inherit the constraints. */ - if (constraint - && dfa->edests[node].nelem - && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) - { - err = duplicate_node_closure (dfa, node, node, node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) - for (i = 0; i < dfa->edests[node].nelem; ++i) - { - re_node_set eclosure_elem; - int edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of `edest' is in progress, - return intermediate result. */ - if (dfa->eclosures[edest].nelem == -1) - { - incomplete = 1; - continue; - } - /* If we haven't calculated the epsilon closure of `edest' yet, - calculate now. Otherwise use calculated epsilon closure. */ - if (dfa->eclosures[edest].nelem == 0) - { - err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of `edest'. */ - re_node_set_merge (&eclosure, &eclosure_elem); - /* If the epsilon closure of `edest' is incomplete, - the epsilon closure of this node is also incomplete. */ - if (dfa->eclosures[edest].nelem == 0) - { - incomplete = 1; - re_node_set_free (&eclosure_elem); - } - } - - /* Epsilon closures include itself. */ - re_node_set_insert (&eclosure, node); - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; - else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; -} - -/* Functions for token which are used in the parser. */ - -/* Fetch a token from INPUT. - We must not use this function inside bracket expressions. */ - -static void -internal_function -fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) -{ - re_string_skip_bytes (input, peek_token (result, input, syntax)); -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function inside bracket expressions. */ - -static int -internal_function -peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - - c = re_string_peek_byte (input, 0); - token->opr.c = c; - - token->word_char = 0; -#ifdef RE_ENABLE_I18N - token->mb_partial = 0; - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - token->mb_partial = 1; - return 1; - } -#endif - if (c == '\\') - { - unsigned char c2; - if (re_string_cur_idx (input) + 1 >= re_string_length (input)) - { - token->type = BACK_SLASH; - return 1; - } - - c2 = re_string_peek_byte_case (input, 1); - token->opr.c = c2; - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, - re_string_cur_idx (input) + 1); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (c2) != 0; - - switch (c2) - { - case '|': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (!(syntax & RE_NO_BK_REFS)) - { - token->type = OP_BACK_REF; - token->opr.idx = c2 - '1'; - } - break; - case '<': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_FIRST; - } - break; - case '>': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_LAST; - } - break; - case 'b': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_DELIM; - } - break; - case 'B': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = NOT_WORD_DELIM; - } - break; - case 'w': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_WORD; - break; - case 'W': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTWORD; - break; - case 's': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_SPACE; - break; - case 'S': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTSPACE; - break; - case '`': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_FIRST; - } - break; - case '\'': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_LAST; - } - break; - case '(': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_CLOSE_SUBEXP; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_CLOSE_DUP_NUM; - break; - default: - break; - } - return 2; - } - - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (token->opr.c); - - switch (c) - { - case '\n': - if (syntax & RE_NEWLINE_ALT) - token->type = OP_ALT; - break; - case '|': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '*': - token->type = OP_DUP_ASTERISK; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_CLOSE_DUP_NUM; - break; - case '(': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_CLOSE_SUBEXP; - break; - case '[': - token->type = OP_OPEN_BRACKET; - break; - case '.': - token->type = OP_PERIOD; - break; - case '^': - if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && - re_string_cur_idx (input) != 0) - { - char prev = re_string_peek_byte (input, -1); - if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_FIRST; - break; - case '$': - if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && - re_string_cur_idx (input) + 1 != re_string_length (input)) - { - re_token_t next; - re_string_skip_bytes (input, 1); - peek_token (&next, input, syntax); - re_string_skip_bytes (input, -1); - if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_LAST; - break; - default: - break; - } - return 1; -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function out of bracket expressions. */ - -static int -internal_function -peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - c = re_string_peek_byte (input, 0); - token->opr.c = c; - -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - return 1; - } -#endif /* RE_ENABLE_I18N */ - - if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) - && re_string_cur_idx (input) + 1 < re_string_length (input)) - { - /* In this case, '\' escape a character. */ - unsigned char c2; - re_string_skip_bytes (input, 1); - c2 = re_string_peek_byte (input, 0); - token->opr.c = c2; - token->type = CHARACTER; - return 1; - } - if (c == '[') /* '[' is a special char in a bracket exps. */ - { - unsigned char c2; - int token_len; - if (re_string_cur_idx (input) + 1 < re_string_length (input)) - c2 = re_string_peek_byte (input, 1); - else - c2 = 0; - token->opr.c = c2; - token_len = 2; - switch (c2) - { - case '.': - token->type = OP_OPEN_COLL_ELEM; - break; - case '=': - token->type = OP_OPEN_EQUIV_CLASS; - break; - case ':': - if (syntax & RE_CHAR_CLASSES) - { - token->type = OP_OPEN_CHAR_CLASS; - break; - } - /* else fall through. */ - default: - token->type = CHARACTER; - token->opr.c = c; - token_len = 1; - break; - } - return token_len; - } - switch (c) - { - case '-': - token->type = OP_CHARSET_RANGE; - break; - case ']': - token->type = OP_CLOSE_BRACKET; - break; - case '^': - token->type = OP_NON_MATCH_LIST; - break; - default: - token->type = CHARACTER; - } - return 1; -} - -/* Functions for parser. */ - -/* Entry point of the parser. - Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. - This function build the following tree, from regular expression : - CAT - / \ - / \ - EOR - - CAT means concatenation. - EOR means end of regular expression. */ - -static bin_tree_t * -parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, - reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *eor, *root; - re_token_t current_token; - dfa->syntax = syntax; - fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); - tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - eor = create_tree (dfa, NULL, NULL, END_OF_RE); - if (tree != NULL) - root = create_tree (dfa, tree, eor, CONCAT); - else - root = eor; - if (BE (eor == NULL || root == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - return root; -} - -/* This function build the following tree, from regular expression - |: - ALT - / \ - / \ - - - ALT means alternative, which represents the operator `|'. */ - -static bin_tree_t * -parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, int nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *branch = NULL; - tree = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type == OP_ALT) - { - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - if (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - branch = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && branch == NULL, 0)) - return NULL; - } - else - branch = NULL; - tree = create_tree (dfa, tree, branch, OP_ALT); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - return tree; -} - -/* This function build the following tree, from regular expression - : - CAT - / \ - / \ - - - CAT means concatenation. */ - -static bin_tree_t * -parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, int nest, reg_errcode_t *err) -{ - bin_tree_t *tree, *exp; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - tree = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - exp = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && exp == NULL, 0)) - { - return NULL; - } - if (tree != NULL && exp != NULL) - { - tree = create_tree (dfa, tree, exp, CONCAT); - if (tree == NULL) - { - *err = REG_ESPACE; - return NULL; - } - } - else if (tree == NULL) - tree = exp; - /* Otherwise exp == NULL, we don't need to create new tree. */ - } - return tree; -} - -/* This function build the following tree, from regular expression a*: - * - | - a -*/ - -static bin_tree_t * -parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, int nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - switch (token->type) - { - case CHARACTER: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (!re_string_eoi (regexp) - && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) - { - bin_tree_t *mbc_remain; - fetch_token (token, regexp, syntax); - mbc_remain = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree, mbc_remain, CONCAT); - if (BE (mbc_remain == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - } -#endif - break; - case OP_OPEN_SUBEXP: - tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_OPEN_BRACKET: - tree = parse_bracket_exp (regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_BACK_REF: - if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) - { - *err = REG_ESUBREG; - return NULL; - } - dfa->used_bkref_map |= 1 << token->opr.idx; - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - ++dfa->nbackref; - dfa->has_mb_node = 1; - break; - case OP_OPEN_DUP_NUM: - if (syntax & RE_CONTEXT_INVALID_DUP) - { - *err = REG_BADRPT; - return NULL; - } - /* FALLTHROUGH */ - case OP_DUP_ASTERISK: - case OP_DUP_PLUS: - case OP_DUP_QUESTION: - if (syntax & RE_CONTEXT_INVALID_OPS) - { - *err = REG_BADRPT; - return NULL; - } - else if (syntax & RE_CONTEXT_INDEP_OPS) - { - fetch_token (token, regexp, syntax); - return parse_expression (regexp, preg, token, syntax, nest, err); - } - /* else fall through */ - case OP_CLOSE_SUBEXP: - if ((token->type == OP_CLOSE_SUBEXP) && - !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) - { - *err = REG_ERPAREN; - return NULL; - } - /* else fall through */ - case OP_CLOSE_DUP_NUM: - /* We treat it as a normal character. */ - - /* Then we can these characters as normal characters. */ - token->type = CHARACTER; - /* mb_partial and word_char bits should be initialized already - by peek_token. */ - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - break; - case ANCHOR: - if ((token->opr.ctx_type - & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) - && dfa->word_ops_used == 0) - init_word_char (dfa); - if (token->opr.ctx_type == WORD_DELIM - || token->opr.ctx_type == NOT_WORD_DELIM) - { - bin_tree_t *tree_first, *tree_last; - if (token->opr.ctx_type == WORD_DELIM) - { - token->opr.ctx_type = WORD_FIRST; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = WORD_LAST; - } - else - { - token->opr.ctx_type = INSIDE_WORD; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = INSIDE_NOTWORD; - } - tree_last = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree_first, tree_last, OP_ALT); - if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - else - { - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - /* We must return here, since ANCHORs can't be followed - by repetition operators. - eg. RE"^*" is invalid or "", - it must not be "". */ - fetch_token (token, regexp, syntax); - return tree; - case OP_PERIOD: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - if (dfa->mb_cur_max > 1) - dfa->has_mb_node = 1; - break; - case OP_WORD: - case OP_NOTWORD: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "alnum", - (const unsigned char *) "_", - token->type == OP_NOTWORD, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_SPACE: - case OP_NOTSPACE: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "space", - (const unsigned char *) "", - token->type == OP_NOTSPACE, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_ALT: - case END_OF_RE: - return NULL; - case BACK_SLASH: - *err = REG_EESCAPE; - return NULL; - default: - /* Must not happen? */ -#ifdef DEBUG - assert (0); -#endif - return NULL; - } - fetch_token (token, regexp, syntax); - - while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS - || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) - { - tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - /* In BRE consecutive duplications are not allowed. */ - if ((syntax & RE_CONTEXT_INVALID_DUP) - && (token->type == OP_DUP_ASTERISK - || token->type == OP_OPEN_DUP_NUM)) - { - *err = REG_BADRPT; - return NULL; - } - } - - return tree; -} - -/* This function build the following tree, from regular expression - (): - SUBEXP - | - -*/ - -static bin_tree_t * -parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, int nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - size_t cur_nsub; - cur_nsub = preg->re_nsub++; - - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - - /* The subexpression may be a null string. */ - if (token->type == OP_CLOSE_SUBEXP) - tree = NULL; - else - { - tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); - if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) - *err = REG_EPAREN; - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - - if (cur_nsub <= '9' - '1') - dfa->completed_bkref_map |= 1 << cur_nsub; - - tree = create_tree (dfa, tree, NULL, SUBEXP); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - tree->token.opr.idx = cur_nsub; - return tree; -} - -/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ - -static bin_tree_t * -parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) -{ - bin_tree_t *tree = NULL, *old_tree = NULL; - int i, start, end, start_idx = re_string_cur_idx (regexp); - re_token_t start_token = *token; - - if (token->type == OP_OPEN_DUP_NUM) - { - end = 0; - start = fetch_number (regexp, token, syntax); - if (start == -1) - { - if (token->type == CHARACTER && token->opr.c == ',') - start = 0; /* We treat "{,m}" as "{0,m}". */ - else - { - *err = REG_BADBR; /* {} is invalid. */ - return NULL; - } - } - if (BE (start != -2, 1)) - { - /* We treat "{n}" as "{n,n}". */ - end = ((token->type == OP_CLOSE_DUP_NUM) ? start - : ((token->type == CHARACTER && token->opr.c == ',') - ? fetch_number (regexp, token, syntax) : -2)); - } - if (BE (start == -2 || end == -2, 0)) - { - /* Invalid sequence. */ - if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) - { - if (token->type == END_OF_RE) - *err = REG_EBRACE; - else - *err = REG_BADBR; - - return NULL; - } - - /* If the syntax bit is set, rollback. */ - re_string_set_index (regexp, start_idx); - *token = start_token; - token->type = CHARACTER; - /* mb_partial and word_char bits should be already initialized by - peek_token. */ - return elem; - } - - if (BE (end != -1 && start > end, 0)) - { - /* First number greater than second. */ - *err = REG_BADBR; - return NULL; - } - } - else - { - start = (token->type == OP_DUP_PLUS) ? 1 : 0; - end = (token->type == OP_DUP_QUESTION) ? 1 : -1; - } - - fetch_token (token, regexp, syntax); - - if (BE (elem == NULL, 0)) - return NULL; - if (BE (start == 0 && end == 0, 0)) - { - postorder (elem, free_tree, NULL); - return NULL; - } - - /* Extract "{n,m}" to "...{0,}". */ - if (BE (start > 0, 0)) - { - tree = elem; - for (i = 2; i <= start; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (start == end) - return tree; - - /* Duplicate ELEM before it is marked optional. */ - elem = duplicate_tree (elem, dfa); - old_tree = tree; - } - else - old_tree = NULL; - - if (elem->token.type == SUBEXP) - postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); - - tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - - /* This loop is actually executed only when end != -1, - to rewrite {0,n} as ((...?)?)?... We have - already created the start+1-th copy. */ - for (i = start + 2; i <= end; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - - tree = create_tree (dfa, tree, NULL, OP_ALT); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (old_tree) - tree = create_tree (dfa, old_tree, tree, CONCAT); - - return tree; - - parse_dup_op_espace: - *err = REG_ESPACE; - return NULL; -} - -/* Size of the names for collating symbol/equivalence_class/character_class. - I'm not sure, but maybe enough. */ -#define BRACKET_NAME_BUF_SIZE 32 - -#ifndef _LIBC - /* Local function for parse_bracket_exp only used in case of NOT _LIBC. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - -static reg_errcode_t -internal_function -# ifdef RE_ENABLE_I18N -build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, - bracket_elem_t *start_elem, bracket_elem_t *end_elem) -# else /* not RE_ENABLE_I18N */ -build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, - bracket_elem_t *end_elem) -# endif /* not RE_ENABLE_I18N */ -{ - unsigned int start_ch, end_ch; - /* Equivalence Classes and Character Classes can't be a range start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - /* We can handle no multi character collating elements without libc - support. */ - if (BE ((start_elem->type == COLL_SYM - && strlen ((char *) start_elem->opr.name) > 1) - || (end_elem->type == COLL_SYM - && strlen ((char *) end_elem->opr.name) > 1), 0)) - return REG_ECOLLATE; - -# ifdef RE_ENABLE_I18N - { - wchar_t wc; - wint_t start_wc; - wint_t end_wc; - wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - - start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) - ? __btowc (start_ch) : start_elem->opr.wch); - end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) - ? __btowc (end_ch) : end_elem->opr.wch); - if (start_wc == WEOF || end_wc == WEOF) - return REG_ECOLLATE; - cmp_buf[0] = start_wc; - cmp_buf[4] = end_wc; - if (wcscoll (cmp_buf, cmp_buf + 4) > 0) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes - no MBCSET if dfa->mb_cur_max == 1. */ - if (mbcset) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - wchar_t *new_array_start, *new_array_end; - int new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - /* Use realloc since mbcset->range_starts and mbcset->range_ends - are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, wchar_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_wc; - mbcset->range_ends[mbcset->nranges++] = end_wc; - } - - /* Build the table for single byte characters. */ - for (wc = 0; wc < SBC_MAX; ++wc) - { - cmp_buf[2] = wc; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - bitset_set (sbcset, wc); - } - } -# else /* not RE_ENABLE_I18N */ - { - unsigned int ch; - start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - if (start_ch > end_ch) - return REG_ERANGE; - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ++ch) - if (start_ch <= ch && ch <= end_ch) - bitset_set (sbcset, ch); - } -# endif /* not RE_ENABLE_I18N */ - return REG_NOERROR; -} -#endif /* not _LIBC */ - -#ifndef _LIBC -/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ - -static reg_errcode_t -internal_function -# ifdef RE_ENABLE_I18N -build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, - int *coll_sym_alloc, const unsigned char *name) -# else /* not RE_ENABLE_I18N */ -build_collating_symbol (bitset_t sbcset, const unsigned char *name) -# endif /* not RE_ENABLE_I18N */ -{ - size_t name_len = strlen ((const char *) name); - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } -} -#endif /* not _LIBC */ - -/* This function parse bracket expression like "[abc]", "[a-c]", - "[[.a-a.]]" etc. */ - -static bin_tree_t * -parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err) -{ -#ifdef _LIBC - const unsigned char *collseqmb; - const char *collseqwc; - uint32_t nrules; - int32_t table_size; - const int32_t *symb_table; - const unsigned char *extra; - - /* Local function for parse_bracket_exp used in _LIBC environement. - Seek the collating symbol entry correspondings to NAME. - Return the index of the symbol in the SYMB_TABLE. */ - - auto inline int32_t - __attribute ((always_inline)) - seek_collating_symbol_entry (name, name_len) - const unsigned char *name; - size_t name_len; - { - int32_t hash = elem_hash ((const char *) name, name_len); - int32_t elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - int32_t second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - /* Compare the length of the name. */ - && name_len == extra[symb_table[2 * elem + 1]] - /* Compare the name. */ - && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], - name_len) == 0) - { - /* Yep, this is the entry. */ - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - return elem; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Look up the collation sequence value of BR_ELEM. - Return the value if succeeded, UINT_MAX otherwise. */ - - auto inline unsigned int - __attribute ((always_inline)) - lookup_collation_sequence_value (br_elem) - bracket_elem_t *br_elem; - { - if (br_elem->type == SB_CHAR) - { - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - return collseqmb[br_elem->opr.ch]; - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } - else if (br_elem->type == MB_CHAR) - { - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); - } - else if (br_elem->type == COLL_SYM) - { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); - if (nrules != 0) - { - int32_t elem, idx; - elem = seek_collating_symbol_entry (br_elem->opr.name, - sym_name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - /* Skip the byte sequence of the collating element. */ - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the multibyte collation sequence value. */ - idx += sizeof (unsigned int); - /* Skip the wide char sequence of the collating element. */ - idx += sizeof (unsigned int) * - (1 + *(unsigned int *) (extra + idx)); - /* Return the collation sequence value. */ - return *(unsigned int *) (extra + idx); - } - else if (symb_table[2 * elem] == 0 && sym_name_len == 1) - { - /* No valid character. Match it as a single byte - character. */ - return collseqmb[br_elem->opr.name[0]]; - } - } - else if (sym_name_len == 1) - return collseqmb[br_elem->opr.name[0]]; - } - return UINT_MAX; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) - re_charset_t *mbcset; - int *range_alloc; - bitset_t sbcset; - bracket_elem_t *start_elem, *end_elem; - { - unsigned int ch; - uint32_t start_collseq; - uint32_t end_collseq; - - /* Equivalence Classes and Character Classes can't be a range - start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - start_collseq = lookup_collation_sequence_value (start_elem); - end_collseq = lookup_collation_sequence_value (end_elem); - /* Check start/end collation sequence values. */ - if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) - return REG_ECOLLATE; - if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ - if (nrules > 0 || dfa->mb_cur_max > 1) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - uint32_t *new_array_start; - uint32_t *new_array_end; - int new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, uint32_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_collseq; - mbcset->range_ends[mbcset->nranges++] = end_collseq; - } - - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ch++) - { - uint32_t ch_collseq; - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - ch_collseq = collseqmb[ch]; - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) - bitset_set (sbcset, ch); - } - return REG_NOERROR; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument sinse we may update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) - re_charset_t *mbcset; - int *coll_sym_alloc; - bitset_t sbcset; - const unsigned char *name; - { - int32_t elem, idx; - size_t name_len = strlen ((const char *) name); - if (nrules != 0) - { - elem = seek_collating_symbol_entry (name, name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - } - else if (symb_table[2 * elem] == 0 && name_len == 1) - { - /* No valid character, treat it as a normal - character. */ - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - else - return REG_ECOLLATE; - - /* Got valid collation sequence, add it as a new entry. */ - /* Check the space of the arrays. */ - if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; - /* Use realloc since mbcset->coll_syms is NULL - if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); - if (BE (new_coll_syms == NULL, 0)) - return REG_ESPACE; - mbcset->coll_syms = new_coll_syms; - *coll_sym_alloc = new_coll_sym_alloc; - } - mbcset->coll_syms[mbcset->ncoll_syms++] = idx; - return REG_NOERROR; - } - else - { - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - } - } -#endif - - re_token_t br_token; - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; - int equiv_class_alloc = 0, char_class_alloc = 0; -#endif /* not RE_ENABLE_I18N */ - int non_match = 0; - bin_tree_t *work_tree; - int token_len; - int first_round = 1; -#ifdef _LIBC - collseqmb = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules) - { - /* - if (MB_CUR_MAX > 1) - */ - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - } -#endif - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else - if (BE (sbcset == NULL, 0)) -#endif /* RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_NON_MATCH_LIST) - { -#ifdef RE_ENABLE_I18N - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - non_match = 1; - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set (sbcset, '\0'); - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - } - - /* We treat the first ']' as a normal character. */ - if (token->type == OP_CLOSE_BRACKET) - token->type = CHARACTER; - - while (1) - { - bracket_elem_t start_elem, end_elem; - unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; - unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; - reg_errcode_t ret; - int token_len2 = 0, is_range_exp = 0; - re_token_t token2; - - start_elem.opr.name = start_name_buf; - ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, - syntax, first_round); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - first_round = 0; - - /* Get information about the next token. We need it in any case. */ - token_len = peek_token_bracket (token, regexp, syntax); - - /* Do not check for ranges if we know they are not allowed. */ - if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) - { - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CHARSET_RANGE) - { - re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ - token_len2 = peek_token_bracket (&token2, regexp, syntax); - if (BE (token2.type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token2.type == OP_CLOSE_BRACKET) - { - /* We treat the last '-' as a normal character. */ - re_string_skip_bytes (regexp, -token_len); - token->type = CHARACTER; - } - else - is_range_exp = 1; - } - } - - if (is_range_exp == 1) - { - end_elem.opr.name = end_name_buf; - ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, - dfa, syntax, 1); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - - token_len = peek_token_bracket (token, regexp, syntax); - -#ifdef _LIBC - *err = build_range_exp (sbcset, mbcset, &range_alloc, - &start_elem, &end_elem); -#else -# ifdef RE_ENABLE_I18N - *err = build_range_exp (sbcset, - dfa->mb_cur_max > 1 ? mbcset : NULL, - &range_alloc, &start_elem, &end_elem); -# else - *err = build_range_exp (sbcset, &start_elem, &end_elem); -# endif -#endif /* RE_ENABLE_I18N */ - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - } - else - { - switch (start_elem.type) - { - case SB_CHAR: - bitset_set (sbcset, start_elem.opr.ch); - break; -#ifdef RE_ENABLE_I18N - case MB_CHAR: - /* Check whether the array has enough space. */ - if (BE (mbchar_alloc == mbcset->nmbchars, 0)) - { - wchar_t *new_mbchars; - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nmbchars is 0. */ - mbchar_alloc = 2 * mbcset->nmbchars + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - new_mbchars = re_realloc (mbcset->mbchars, wchar_t, - mbchar_alloc); - if (BE (new_mbchars == NULL, 0)) - goto parse_bracket_exp_espace; - mbcset->mbchars = new_mbchars; - } - mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; - break; -#endif /* RE_ENABLE_I18N */ - case EQUIV_CLASS: - *err = build_equiv_class (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &equiv_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case COLL_SYM: - *err = build_collating_symbol (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &coll_sym_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case CHAR_CLASS: - *err = build_charclass (regexp->trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &char_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name, syntax); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - default: - assert (0); - break; - } - } - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CLOSE_BRACKET) - break; - } - - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); - - if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes - || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes - || mbcset->non_match))) - { - bin_tree_t *mbc_tree; - int sbc_idx; - /* Build a tree for complex bracket. */ - dfa->has_mb_node = 1; - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto parse_bracket_exp_espace; - for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) - if (sbcset[sbc_idx]) - break; - /* If there are no bits set in sbcset, there is no point - of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ - if (sbc_idx < BITSET_WORDS) - { - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - - /* Then join them by ALT node. */ - work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - else - { - re_free (sbcset); - work_tree = mbc_tree; - } - } - else -#endif /* not RE_ENABLE_I18N */ - { -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - return work_tree; - - parse_bracket_exp_espace: - *err = REG_ESPACE; - parse_bracket_exp_free_return: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - return NULL; -} - -/* Parse an element in the bracket expression. */ - -static reg_errcode_t -parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token, int token_len, re_dfa_t *dfa, - reg_syntax_t syntax, int accept_hyphen) -{ -#ifdef RE_ENABLE_I18N - int cur_char_size; - cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); - if (cur_char_size > 1) - { - elem->type = MB_CHAR; - elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); - re_string_skip_bytes (regexp, cur_char_size); - return REG_NOERROR; - } -#endif /* RE_ENABLE_I18N */ - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS - || token->type == OP_OPEN_EQUIV_CLASS) - return parse_bracket_symbol (elem, regexp, token); - if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) - { - /* A '-' must only appear as anything but a range indicator before - the closing bracket. Everything else is an error. */ - re_token_t token2; - (void) peek_token_bracket (&token2, regexp, syntax); - if (token2.type != OP_CLOSE_BRACKET) - /* The actual error value is not standardized since this whole - case is undefined. But ERANGE makes good sense. */ - return REG_ERANGE; - } - elem->type = SB_CHAR; - elem->opr.ch = token->opr.c; - return REG_NOERROR; -} - -/* Parse a bracket symbol in the bracket expression. Bracket symbols are - such as [::], [..], and - [==]. */ - -static reg_errcode_t -parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token) -{ - unsigned char ch, delim = token->opr.c; - int i = 0; - if (re_string_eoi(regexp)) - return REG_EBRACK; - for (;; ++i) - { - if (i >= BRACKET_NAME_BUF_SIZE) - return REG_EBRACK; - if (token->type == OP_OPEN_CHAR_CLASS) - ch = re_string_fetch_byte_case (regexp); - else - ch = re_string_fetch_byte (regexp); - if (re_string_eoi(regexp)) - return REG_EBRACK; - if (ch == delim && re_string_peek_byte (regexp, 0) == ']') - break; - elem->opr.name[i] = ch; - } - re_string_skip_bytes (regexp, 1); - elem->opr.name[i] = '\0'; - switch (token->type) - { - case OP_OPEN_COLL_ELEM: - elem->type = COLL_SYM; - break; - case OP_OPEN_EQUIV_CLASS: - elem->type = EQUIV_CLASS; - break; - case OP_OPEN_CHAR_CLASS: - elem->type = CHAR_CLASS; - break; - default: - break; - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the equivalence class which is represented by NAME. - The result are written to MBCSET and SBCSET. - EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, - int *equiv_class_alloc, const unsigned char *name) -#else /* not RE_ENABLE_I18N */ -build_equiv_class (bitset_t sbcset, const unsigned char *name) -#endif /* not RE_ENABLE_I18N */ -{ -#ifdef _LIBC - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - const int32_t *table, *indirect; - const unsigned char *weights, *extra, *cp; - unsigned char char_buf[2]; - int32_t idx1, idx2; - unsigned int ch; - size_t len; - /* This #include defines a local function! */ -# include - /* Calculate the index for equivalence class. */ - cp = name; - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - idx1 = findidx (&cp); - if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) - /* This isn't a valid character. */ - return REG_ECOLLATE; - - /* Build single byte matcing table for this equivalence class. */ - char_buf[1] = (unsigned char) '\0'; - len = weights[idx1]; - for (ch = 0; ch < SBC_MAX; ++ch) - { - char_buf[0] = ch; - cp = char_buf; - idx2 = findidx (&cp); -/* - idx2 = table[ch]; -*/ - if (idx2 == 0) - /* This isn't a valid character. */ - continue; - if (len == weights[idx2]) - { - int cnt = 0; - while (cnt <= len && - weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) - ++cnt; - - if (cnt > len) - bitset_set (sbcset, ch); - } - } - /* Check whether the array has enough space. */ - if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nequiv_classes is 0. */ - int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; - /* Use realloc since the array is NULL if *alloc == 0. */ - int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, - int32_t, - new_equiv_class_alloc); - if (BE (new_equiv_classes == NULL, 0)) - return REG_ESPACE; - mbcset->equiv_classes = new_equiv_classes; - *equiv_class_alloc = new_equiv_class_alloc; - } - mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; - } - else -#endif /* _LIBC */ - { - if (BE (strlen ((const char *) name) != 1, 0)) - return REG_ECOLLATE; - bitset_set (sbcset, *name); - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the character class which is represented by NAME. - The result are written to MBCSET and SBCSET. - CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - re_charset_t *mbcset, int *char_class_alloc, - const unsigned char *class_name, reg_syntax_t syntax) -#else /* not RE_ENABLE_I18N */ -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const unsigned char *class_name, reg_syntax_t syntax) -#endif /* not RE_ENABLE_I18N */ -{ - int i; - const char *name = (const char *) class_name; - - /* In case of REG_ICASE "upper" and "lower" match the both of - upper and lower cases. */ - if ((syntax & RE_ICASE) - && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) - name = "alpha"; - -#ifdef RE_ENABLE_I18N - /* Check the space of the arrays. */ - if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nchar_classes is 0. */ - int new_char_class_alloc = 2 * mbcset->nchar_classes + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, - new_char_class_alloc); - if (BE (new_char_classes == NULL, 0)) - return REG_ESPACE; - mbcset->char_classes = new_char_classes; - *char_class_alloc = new_char_class_alloc; - } - mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); -#endif /* RE_ENABLE_I18N */ - -#define BUILD_CHARCLASS_LOOP(ctype_func) \ - do { \ - if (BE (trans != NULL, 0)) \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, trans[i]); \ - } \ - else \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, i); \ - } \ - } while (0) - - if (strcmp (name, "alnum") == 0) - BUILD_CHARCLASS_LOOP (isalnum); - else if (strcmp (name, "cntrl") == 0) - BUILD_CHARCLASS_LOOP (iscntrl); - else if (strcmp (name, "lower") == 0) - BUILD_CHARCLASS_LOOP (islower); - else if (strcmp (name, "space") == 0) - BUILD_CHARCLASS_LOOP (isspace); - else if (strcmp (name, "alpha") == 0) - BUILD_CHARCLASS_LOOP (isalpha); - else if (strcmp (name, "digit") == 0) - BUILD_CHARCLASS_LOOP (isdigit); - else if (strcmp (name, "print") == 0) - BUILD_CHARCLASS_LOOP (isprint); - else if (strcmp (name, "upper") == 0) - BUILD_CHARCLASS_LOOP (isupper); - else if (strcmp (name, "blank") == 0) - BUILD_CHARCLASS_LOOP (isblank); - else if (strcmp (name, "graph") == 0) - BUILD_CHARCLASS_LOOP (isgraph); - else if (strcmp (name, "punct") == 0) - BUILD_CHARCLASS_LOOP (ispunct); - else if (strcmp (name, "xdigit") == 0) - BUILD_CHARCLASS_LOOP (isxdigit); - else - return REG_ECTYPE; - - return REG_NOERROR; -} - -static bin_tree_t * -build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, int non_match, - reg_errcode_t *err) -{ - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - int alloc = 0; -#endif /* not RE_ENABLE_I18N */ - reg_errcode_t ret; - re_token_t br_token; - bin_tree_t *tree; - - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ - -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else /* not RE_ENABLE_I18N */ - if (BE (sbcset == NULL, 0)) -#endif /* not RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - if (non_match) - { -#ifdef RE_ENABLE_I18N - /* - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set(cset->sbcset, '\0'); - */ - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - } - - /* We don't care the syntax in this case. */ - ret = build_charclass (trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &alloc, -#endif /* RE_ENABLE_I18N */ - class_name, 0); - - if (BE (ret != REG_NOERROR, 0)) - { - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = ret; - return NULL; - } - /* \w match '_' also. */ - for (; *extra; extra++) - bitset_set (sbcset, *extra); - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); -#endif - - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (tree == NULL, 0)) - goto build_word_op_espace; - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - bin_tree_t *mbc_tree; - /* Build a tree for complex bracket. */ - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - dfa->has_mb_node = 1; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto build_word_op_espace; - /* Then join them by ALT node. */ - tree = create_tree (dfa, tree, mbc_tree, OP_ALT); - if (BE (mbc_tree != NULL, 1)) - return tree; - } - else - { - free_charset (mbcset); - return tree; - } -#else /* not RE_ENABLE_I18N */ - return tree; -#endif /* not RE_ENABLE_I18N */ - - build_word_op_espace: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = REG_ESPACE; - return NULL; -} - -/* This is intended for the expressions like "a{1,3}". - Fetch a number from `input', and return the number. - Return -1, if the number field is empty like "{,1}". - Return -2, If an error is occured. */ - -static int -fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -{ - int num = -1; - unsigned char c; - while (1) - { - fetch_token (token, input, syntax); - c = token->opr.c; - if (BE (token->type == END_OF_RE, 0)) - return -2; - if (token->type == OP_CLOSE_DUP_NUM || c == ',') - break; - num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) - ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0')); - num = (num > RE_DUP_MAX) ? -2 : num; - } - return num; -} - -#ifdef RE_ENABLE_I18N -static void -free_charset (re_charset_t *cset) -{ - re_free (cset->mbchars); -# ifdef _LIBC - re_free (cset->coll_syms); - re_free (cset->equiv_classes); - re_free (cset->range_starts); - re_free (cset->range_ends); -# endif - re_free (cset->char_classes); - re_free (cset); -} -#endif /* RE_ENABLE_I18N */ - -/* Functions for binary tree operation. */ - -/* Create a tree node. */ - -static bin_tree_t * -create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - re_token_type_t type) -{ - re_token_t t; - t.type = type; - return create_token_tree (dfa, left, right, &t); -} - -static bin_tree_t * -create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - const re_token_t *token) -{ - bin_tree_t *tree; - if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) - { - bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); - - if (storage == NULL) - return NULL; - storage->next = dfa->str_tree_storage; - dfa->str_tree_storage = storage; - dfa->str_tree_storage_idx = 0; - } - tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; - - tree->parent = NULL; - tree->left = left; - tree->right = right; - tree->token = *token; - tree->token.duplicated = 0; - tree->token.opt_subexp = 0; - tree->first = NULL; - tree->next = NULL; - tree->node_idx = -1; - - if (left != NULL) - left->parent = tree; - if (right != NULL) - right->parent = tree; - return tree; -} - -/* Mark the tree SRC as an optional subexpression. - To be called from preorder or postorder. */ - -static reg_errcode_t -mark_opt_subexp (void *extra, bin_tree_t *node) -{ - int idx = (int) (long) extra; - if (node->token.type == SUBEXP && node->token.opr.idx == idx) - node->token.opt_subexp = 1; - - return REG_NOERROR; -} - -/* Free the allocated memory inside NODE. */ - -static void -free_token (re_token_t *node) -{ -#ifdef RE_ENABLE_I18N - if (node->type == COMPLEX_BRACKET && node->duplicated == 0) - free_charset (node->opr.mbcset); - else -#endif /* RE_ENABLE_I18N */ - if (node->type == SIMPLE_BRACKET && node->duplicated == 0) - re_free (node->opr.sbcset); -} - -/* Worker function for tree walking. Free the allocated memory inside NODE - and its children. */ - -static reg_errcode_t -free_tree (void *extra, bin_tree_t *node) -{ - free_token (&node->token); - return REG_NOERROR; -} - - -/* Duplicate the node SRC, and return new node. This is a preorder - visit similar to the one implemented by the generic visitor, but - we need more infrastructure to maintain two parallel trees --- so, - it's easier to duplicate. */ - -static bin_tree_t * -duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) -{ - const bin_tree_t *node; - bin_tree_t *dup_root; - bin_tree_t **p_new = &dup_root, *dup_node = root->parent; - - for (node = root; ; ) - { - /* Create a new tree and link it back to the current parent. */ - *p_new = create_token_tree (dfa, NULL, NULL, &node->token); - if (*p_new == NULL) - return NULL; - (*p_new)->parent = dup_node; - (*p_new)->token.duplicated = 1; - dup_node = *p_new; - - /* Go to the left node, or up and to the right. */ - if (node->left) - { - node = node->left; - p_new = &dup_node->left; - } - else - { - const bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - dup_node = dup_node->parent; - if (!node) - return dup_root; - } - node = node->right; - p_new = &dup_node->right; - } - } -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* GKINCLUDE #include "regexec.c" */ -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, - int n) internal_function; -static void match_ctx_clean (re_match_context_t *mctx) internal_function; -static void match_ctx_free (re_match_context_t *cache) internal_function; -static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, - int str_idx, int from, int to) - internal_function; -static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) - internal_function; -static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, - int str_idx) internal_function; -static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, - int node, int str_idx) - internal_function; -static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, int last_node, - int last_str_idx) - internal_function; -static reg_errcode_t re_search_internal (const regex_t *preg, - const char *string, int length, - int start, int range, int stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) internal_function; -static int re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, int length1, - const char *string2, int length2, - int start, int range, struct re_registers *regs, - int stop, int ret_len) internal_function; -static int re_search_stub (struct re_pattern_buffer *bufp, - const char *string, int length, int start, - int range, int stop, struct re_registers *regs, - int ret_len) internal_function; -static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - int nregs, int regs_allocated) internal_function; -static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) - internal_function; -static int check_matching (re_match_context_t *mctx, int fl_longest_match, - int *p_match_first) internal_function; -static int check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, int idx) - internal_function; -static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, int cur_node, - int cur_idx, int nmatch) internal_function; -static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, - int str_idx, int dest_node, int nregs, - regmatch_t *regs, - re_node_set *eps_via_nodes) - internal_function; -static reg_errcode_t set_regs (const regex_t *preg, - const re_match_context_t *mctx, - size_t nmatch, regmatch_t *pmatch, - int fl_backtrack) internal_function; -static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) - internal_function; - -#ifdef RE_ENABLE_I18N -static int sift_states_iter_mb (const re_match_context_t *mctx, - re_sift_context_t *sctx, - int node_idx, int str_idx, int max_str_idx) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, - re_sift_context_t *sctx) - internal_function; -static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, - re_sift_context_t *sctx, int str_idx, - re_node_set *cur_dest) - internal_function; -static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, - int str_idx, - re_node_set *dest_nodes) - internal_function; -static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates) - internal_function; -static int check_dst_limits (const re_match_context_t *mctx, - re_node_set *limits, - int dst_node, int dst_idx, int src_node, - int src_idx) internal_function; -static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, - int boundaries, int subexp_idx, - int from_node, int bkref_idx) - internal_function; -static int check_dst_limits_calc_pos (const re_match_context_t *mctx, - int limit, int subexp_idx, - int node, int str_idx, - int bkref_idx) internal_function; -static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates, - re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, - int str_idx) internal_function; -static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, - re_sift_context_t *sctx, - int str_idx, const re_node_set *candidates) - internal_function; -static reg_errcode_t merge_state_array (const re_dfa_t *dfa, - re_dfastate_t **dst, - re_dfastate_t **src, int num) - internal_function; -static re_dfastate_t *find_recover_state (reg_errcode_t *err, - re_match_context_t *mctx) internal_function; -static re_dfastate_t *transit_state (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *state) internal_function; -static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *next_state) - internal_function; -static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, - re_node_set *cur_nodes, - int str_idx) internal_function; -#if 0 -static re_dfastate_t *transit_state_sb (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif -#ifdef RE_ENABLE_I18N -static reg_errcode_t transit_state_mb (re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, - const re_node_set *nodes) - internal_function; -static reg_errcode_t get_subexp (re_match_context_t *mctx, - int bkref_node, int bkref_str_idx) - internal_function; -static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, - const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, - int bkref_node, int bkref_str) - internal_function; -static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - int subexp_idx, int type) internal_function; -static reg_errcode_t check_arrival (re_match_context_t *mctx, - state_array_t *path, int top_node, - int top_str, int last_node, int last_str, - int type) internal_function; -static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, - int str_idx, - re_node_set *cur_nodes, - re_node_set *next_nodes) - internal_function; -static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, - re_node_set *cur_nodes, - int ex_subexp, int type) - internal_function; -static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, - re_node_set *dst_nodes, - int target, int ex_subexp, - int type) internal_function; -static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, - re_node_set *cur_nodes, int cur_str, - int subexp_num, int type) - internal_function; -static int build_trtable (const re_dfa_t *dfa, - re_dfastate_t *state) internal_function; -#ifdef RE_ENABLE_I18N -static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, - const re_string_t *input, int idx) - internal_function; -# ifdef _LIBC -static unsigned int find_collation_sequence_value (const unsigned char *mbs, - size_t name_len) - internal_function; -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ -static int group_nodes_into_DFAstates (const re_dfa_t *dfa, - const re_dfastate_t *state, - re_node_set *states_node, - bitset_t *states_ch) internal_function; -static int check_node_accept (const re_match_context_t *mctx, - const re_token_t *node, int idx) - internal_function; -static reg_errcode_t extend_buffers (re_match_context_t *mctx) - internal_function; - -/* Entry point for POSIX code. */ - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies `execution flags' which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - We return 0 if we find a match and REG_NOMATCH if not. */ - -int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *__restrict preg; - const char *__restrict string; - size_t nmatch; - regmatch_t pmatch[]; - int eflags; -{ - reg_errcode_t err; - int start, length; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - - if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) - return REG_BADPAT; - - if (eflags & REG_STARTEND) - { - start = pmatch[0].rm_so; - length = pmatch[0].rm_eo; - } - else - { - start = 0; - length = strlen (string); - } - - __libc_lock_lock (dfa->lock); - if (preg->no_sub) - err = re_search_internal (preg, string, length, start, length - start, - length, 0, NULL, eflags); - else - err = re_search_internal (preg, string, length, start, length - start, - length, nmatch, pmatch, eflags); - __libc_lock_unlock (dfa->lock); - return err != REG_NOERROR; -} - -#ifdef _LIBC -# include -versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); - -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -__typeof__ (__regexec) __compat_regexec; - -int -attribute_compat_text_section -__compat_regexec (const regex_t *__restrict preg, - const char *__restrict string, size_t nmatch, - regmatch_t pmatch[], int eflags) -{ - return regexec (preg, string, nmatch, pmatch, - eflags & (REG_NOTBOL | REG_NOTEOL)); -} -compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); -# endif -#endif - -/* Entry points for GNU code. */ - -/* re_match, re_search, re_match_2, re_search_2 - - The former two functions operate on STRING with length LENGTH, - while the later two operate on concatenation of STRING1 and STRING2 - with lengths LENGTH1 and LENGTH2, respectively. - - re_match() matches the compiled pattern in BUFP against the string, - starting at index START. - - re_search() first tries matching at index START, then it tries to match - starting from index START + 1, and so on. The last start position tried - is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same - way as re_match().) - - The parameter STOP of re_{match,search}_2 specifies that no match exceeding - the first STOP characters of the concatenation of the strings should be - concerned. - - If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stroed in REGS. (For the "_2" variants, the offsets are - computed relative to the concatenation, not relative to the individual - strings.) - - On success, re_match* functions return the length of the match, re_search* - return the position of the start of the match. Return value -1 means no - match was found and -2 indicates an internal error. */ - -int -re_match (bufp, string, length, start, regs) - struct re_pattern_buffer *bufp; - const char *string; - int length, start; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, 0, length, regs, 1); -} -#ifdef _LIBC -weak_alias (__re_match, re_match) -#endif - -int -re_search (bufp, string, length, start, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - int length, start, range; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, range, length, regs, 0); -} -#ifdef _LIBC -weak_alias (__re_search, re_search) -#endif - -int -re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int length1, length2, start, stop; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, 0, regs, stop, 1); -} -#ifdef _LIBC -weak_alias (__re_match_2, re_match_2) -#endif - -int -re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int length1, length2, start, range, stop; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, range, regs, stop, 0); -} -#ifdef _LIBC -weak_alias (__re_search_2, re_search_2) -#endif - -static int -re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, - stop, ret_len) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int length1, length2, start, range, stop, ret_len; - struct re_registers *regs; -{ - const char *str; - int rval; - int len = length1 + length2; - int free_str = 0; - - if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) - return -2; - - /* Concatenate the strings. */ - if (length2 > 0) - if (length1 > 0) - { - char *s = re_malloc (char, len); - - if (BE (s == NULL, 0)) - return -2; -#ifdef _LIBC - memcpy (__mempcpy (s, string1, length1), string2, length2); -#else - memcpy (s, string1, length1); - memcpy (s + length1, string2, length2); -#endif - str = s; - free_str = 1; - } - else - str = string2; - else - str = string1; - - rval = re_search_stub (bufp, str, len, start, range, stop, regs, - ret_len); - if (free_str) - re_free ((char *) str); - return rval; -} - -/* The parameters have the same meaning as those of re_search. - Additional parameters: - If RET_LEN is nonzero the length of the match is returned (re_match style); - otherwise the position of the match is returned. */ - -static int -re_search_stub (bufp, string, length, start, range, stop, regs, ret_len) - struct re_pattern_buffer *bufp; - const char *string; - int length, start, range, stop, ret_len; - struct re_registers *regs; -{ - reg_errcode_t result; - regmatch_t *pmatch; - int nregs, rval; - int eflags = 0; - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - - /* Check for out-of-range. */ - if (BE (start < 0 || start > length, 0)) - return -1; - if (BE (start + range > length, 0)) - range = length - start; - else if (BE (start + range < 0, 0)) - range = -start; - - __libc_lock_lock (dfa->lock); - - eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; - eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; - - /* Compile fastmap if we haven't yet. */ - if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate) - re_compile_fastmap (bufp); - - if (BE (bufp->no_sub, 0)) - regs = NULL; - - /* We need at least 1 register. */ - if (regs == NULL) - nregs = 1; - else if (BE (bufp->regs_allocated == REGS_FIXED && - regs->num_regs < bufp->re_nsub + 1, 0)) - { - nregs = regs->num_regs; - if (BE (nregs < 1, 0)) - { - /* Nothing can be copied to regs. */ - regs = NULL; - nregs = 1; - } - } - else - nregs = bufp->re_nsub + 1; - pmatch = re_malloc (regmatch_t, nregs); - if (BE (pmatch == NULL, 0)) - { - rval = -2; - goto out; - } - - result = re_search_internal (bufp, string, length, start, range, stop, - nregs, pmatch, eflags); - - rval = 0; - - /* I hope we needn't fill ther regs with -1's when no match was found. */ - if (result != REG_NOERROR) - rval = -1; - else if (regs != NULL) - { - /* If caller wants register contents data back, copy them. */ - bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, - bufp->regs_allocated); - if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) - rval = -2; - } - - if (BE (rval == 0, 1)) - { - if (ret_len) - { - assert (pmatch[0].rm_so == start); - rval = pmatch[0].rm_eo - start; - } - else - rval = pmatch[0].rm_so; - } - re_free (pmatch); - out: - __libc_lock_unlock (dfa->lock); - return rval; -} - -static unsigned -re_copy_regs (regs, pmatch, nregs, regs_allocated) - struct re_registers *regs; - regmatch_t *pmatch; - int nregs, regs_allocated; -{ - int rval = REGS_REALLOCATE; - int i; - int need_regs = nregs + 1; - /* We need one extra element beyond `num_regs' for the `-1' marker GNU code - uses. */ - - /* Have the register data arrays been allocated? */ - if (regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. */ - regs->start = re_malloc (regoff_t, need_regs); - regs->end = re_malloc (regoff_t, need_regs); - if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0)) - return REGS_UNALLOCATED; - regs->num_regs = need_regs; - } - else if (regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (BE (need_regs > regs->num_regs, 0)) - { - regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); - regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); - if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) - return REGS_UNALLOCATED; - regs->start = new_start; - regs->end = new_end; - regs->num_regs = need_regs; - } - } - else - { - assert (regs_allocated == REGS_FIXED); - /* This function may not be called with REGS_FIXED and nregs too big. */ - assert (regs->num_regs >= nregs); - rval = REGS_FIXED; - } - - /* Copy the regs. */ - for (i = 0; i < nregs; ++i) - { - regs->start[i] = pmatch[i].rm_so; - regs->end[i] = pmatch[i].rm_eo; - } - for ( ; i < regs->num_regs; ++i) - regs->start[i] = regs->end[i] = -1; - - return rval; -} - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - unsigned num_regs; - regoff_t *starts, *ends; -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = (regoff_t *) 0; - } -} -#ifdef _LIBC -weak_alias (__re_set_registers, re_set_registers) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC -int -# ifdef _LIBC -weak_function -# endif -re_exec (s) - const char *s; -{ - return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); -} -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. */ - -/* Searches for a compiled pattern PREG in the string STRING, whose - length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same - mingings with regexec. START, and RANGE have the same meanings - with re_search. - Return REG_NOERROR if we find a match, and REG_NOMATCH if not, - otherwise return the error code. - Note: We assume front end functions already check ranges. - (START + RANGE >= 0 && START + RANGE <= LENGTH) */ - -static reg_errcode_t -re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, - eflags) - const regex_t *preg; - const char *string; - int length, start, range, stop, eflags; - size_t nmatch; - regmatch_t pmatch[]; -{ - reg_errcode_t err; - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - int left_lim, right_lim, incr; - int fl_longest_match, match_first, match_kind, match_last = -1; - int extra_nmatch; - int sb, ch; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - re_match_context_t mctx = { .dfa = dfa }; -#else - re_match_context_t mctx; -#endif - char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate - && range && !preg->can_be_null) ? preg->fastmap : NULL; - RE_TRANSLATE_TYPE t = preg->translate; - -#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) - memset (&mctx, '\0', sizeof (re_match_context_t)); - mctx.dfa = dfa; -#endif - - extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; - nmatch -= extra_nmatch; - - /* Check if the DFA haven't been compiled. */ - if (BE (preg->used == 0 || dfa->init_state == NULL - || dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return REG_NOMATCH; - -#ifdef DEBUG - /* We assume front-end functions already check them. */ - assert (start + range >= 0 && start + range <= length); -#endif - - /* If initial states with non-begbuf contexts have no elements, - the regex must be anchored. If preg->newline_anchor is set, - we'll never use init_state_nl, so do not check it. */ - if (dfa->init_state->nodes.nelem == 0 - && dfa->init_state_word->nodes.nelem == 0 - && (dfa->init_state_nl->nodes.nelem == 0 - || !preg->newline_anchor)) - { - if (start != 0 && start + range != 0) - return REG_NOMATCH; - start = range = 0; - } - - /* We must check the longest matching, if nmatch > 0. */ - fl_longest_match = (nmatch != 0 || dfa->nbackref); - - err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, - preg->translate, preg->syntax & RE_ICASE, dfa); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - mctx.input.stop = stop; - mctx.input.raw_stop = stop; - mctx.input.newline_anchor = preg->newline_anchor; - - err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* We will log all the DFA states through which the dfa pass, - if nmatch > 1, or this dfa has "multibyte node", which is a - back-reference or a node which can accept multibyte character or - multi character collating element. */ - if (nmatch > 1 || dfa->has_mb_node) - { - mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); - if (BE (mctx.state_log == NULL, 0)) - { - err = REG_ESPACE; - goto free_return; - } - } - else - mctx.state_log = NULL; - - match_first = start; - mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF; - - /* Check incrementally whether of not the input string match. */ - incr = (range < 0) ? -1 : 1; - left_lim = (range < 0) ? start + range : start; - right_lim = (range < 0) ? start : start + range; - sb = dfa->mb_cur_max == 1; - match_kind = - (fastmap - ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) - | (range >= 0 ? 2 : 0) - | (t != NULL ? 1 : 0)) - : 8); - - for (;; match_first += incr) - { - err = REG_NOMATCH; - if (match_first < left_lim || right_lim < match_first) - goto free_return; - - /* Advance as rapidly as possible through the string, until we - find a plausible place to start matching. This may be done - with varying efficiency, so there are various possibilities: - only the most common of them are specialized, in order to - save on code size. We use a switch statement for speed. */ - switch (match_kind) - { - case 8: - /* No fastmap. */ - break; - - case 7: - /* Fastmap with single-byte translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[t[(unsigned char) string[match_first]]]) - ++match_first; - goto forward_match_found_start_or_reached_end; - - case 6: - /* Fastmap without translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[(unsigned char) string[match_first]]) - ++match_first; - - forward_match_found_start_or_reached_end: - if (BE (match_first == right_lim, 0)) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (!fastmap[t ? t[ch] : ch]) - goto free_return; - } - break; - - case 4: - case 5: - /* Fastmap without multi-byte translation, match backwards. */ - while (match_first >= left_lim) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (fastmap[t ? t[ch] : ch]) - break; - --match_first; - } - if (match_first < left_lim) - goto free_return; - break; - - default: - /* In this case, we can't determine easily the current byte, - since it might be a component byte of a multibyte - character. Then we use the constructed buffer instead. */ - for (;;) - { - /* If MATCH_FIRST is out of the valid range, reconstruct the - buffers. */ - unsigned int offset = match_first - mctx.input.raw_mbs_idx; - if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) - { - err = re_string_reconstruct (&mctx.input, match_first, - eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - offset = match_first - mctx.input.raw_mbs_idx; - } - /* If MATCH_FIRST is out of the buffer, leave it as '\0'. - Note that MATCH_FIRST must not be smaller than 0. */ - ch = (match_first >= length - ? 0 : re_string_byte_at (&mctx.input, offset)); - if (fastmap[ch]) - break; - match_first += incr; - if (match_first < left_lim || match_first > right_lim) - { - err = REG_NOMATCH; - goto free_return; - } - } - break; - } - - /* Reconstruct the buffers so that the matcher can assume that - the matching starts from the beginning of the buffer. */ - err = re_string_reconstruct (&mctx.input, match_first, eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - -#ifdef RE_ENABLE_I18N - /* Don't consider this char as a possible match start if it part, - yet isn't the head, of a multibyte character. */ - if (!sb && !re_string_first_byte (&mctx.input, 0)) - continue; -#endif - - /* It seems to be appropriate one, then use the matcher. */ - /* We assume that the matching starts from 0. */ - mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; - match_last = check_matching (&mctx, fl_longest_match, - range >= 0 ? &match_first : NULL); - if (match_last != -1) - { - if (BE (match_last == -2, 0)) - { - err = REG_ESPACE; - goto free_return; - } - else - { - mctx.match_last = match_last; - if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) - { - re_dfastate_t *pstate = mctx.state_log[match_last]; - mctx.last_node = check_halt_state_context (&mctx, pstate, - match_last); - } - if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) - || dfa->nbackref) - { - err = prune_impossible_nodes (&mctx); - if (err == REG_NOERROR) - break; - if (BE (err != REG_NOMATCH, 0)) - goto free_return; - match_last = -1; - } - else - break; /* We found a match. */ - } - } - - match_ctx_clean (&mctx); - } - -#ifdef DEBUG - assert (match_last != -1); - assert (err == REG_NOERROR); -#endif - - /* Set pmatch[] if we need. */ - if (nmatch > 0) - { - int reg_idx; - - /* Initialize registers. */ - for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) - pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; - - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - - if (!preg->no_sub && nmatch > 1) - { - err = set_regs (preg, &mctx, nmatch, pmatch, - dfa->has_plural_match && dfa->nbackref > 0); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* At last, add the offset to the each registers, since we slided - the buffers so that we could assume that the matching starts - from 0. */ - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so != -1) - { -#ifdef RE_ENABLE_I18N - if (BE (mctx.input.offsets_needed != 0, 0)) - { - pmatch[reg_idx].rm_so = - (pmatch[reg_idx].rm_so == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_so]); - pmatch[reg_idx].rm_eo = - (pmatch[reg_idx].rm_eo == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_eo]); - } -#else - assert (mctx.input.offsets_needed == 0); -#endif - pmatch[reg_idx].rm_so += match_first; - pmatch[reg_idx].rm_eo += match_first; - } - for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) - { - pmatch[nmatch + reg_idx].rm_so = -1; - pmatch[nmatch + reg_idx].rm_eo = -1; - } - - if (dfa->subexp_map) - for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) - if (dfa->subexp_map[reg_idx] != reg_idx) - { - pmatch[reg_idx + 1].rm_so - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; - pmatch[reg_idx + 1].rm_eo - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; - } - } - - free_return: - re_free (mctx.state_log); - if (dfa->nbackref) - match_ctx_free (&mctx); - re_string_destruct (&mctx.input); - return err; -} - -static reg_errcode_t -prune_impossible_nodes (mctx) - re_match_context_t *mctx; -{ - const re_dfa_t *const dfa = mctx->dfa; - int halt_node, match_last; - reg_errcode_t ret; - re_dfastate_t **sifted_states; - re_dfastate_t **lim_states = NULL; - re_sift_context_t sctx; -#ifdef DEBUG - assert (mctx->state_log != NULL); -#endif - match_last = mctx->match_last; - halt_node = mctx->last_node; - sifted_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (sifted_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - if (dfa->nbackref) - { - lim_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (lim_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - while (1) - { - memset (lim_states, '\0', - sizeof (re_dfastate_t *) * (match_last + 1)); - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - if (sifted_states[0] != NULL || lim_states[0] != NULL) - break; - do - { - --match_last; - if (match_last < 0) - { - ret = REG_NOMATCH; - goto free_return; - } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); - } - ret = merge_state_array (dfa, sifted_states, lim_states, - match_last + 1); - re_free (lim_states); - lim_states = NULL; - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - else - { - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - re_free (mctx->state_log); - mctx->state_log = sifted_states; - sifted_states = NULL; - mctx->last_node = halt_node; - mctx->match_last = match_last; - ret = REG_NOERROR; - free_return: - re_free (sifted_states); - re_free (lim_states); - return ret; -} - -/* Acquire an initial state and return it. - We must select appropriate initial state depending on the context, - since initial states may have constraints like "\<", "^", etc.. */ - -static inline re_dfastate_t * -__attribute ((always_inline)) internal_function -acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, - int idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - if (dfa->init_state->has_constraint) - { - unsigned int context; - context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return dfa->init_state_word; - else if (IS_ORDINARY_CONTEXT (context)) - return dfa->init_state; - else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_begbuf; - else if (IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_nl; - else if (IS_BEGBUF_CONTEXT (context)) - { - /* It is relatively rare case, then calculate on demand. */ - return re_acquire_state_context (err, dfa, - dfa->init_state->entrance_nodes, - context); - } - else - /* Must not happen? */ - return dfa->init_state; - } - else - return dfa->init_state; -} - -/* Check whether the regular expression match input string INPUT or not, - and return the index where the matching end, return -1 if not match, - or return -2 in case of an error. - FL_LONGEST_MATCH means we want the POSIX longest matching. - If P_MATCH_FIRST is not NULL, and the match fails, it is set to the - next place where we may want to try matching. - Note that the matcher assume that the maching starts from the current - index of the buffer. */ - -static int -internal_function -check_matching (re_match_context_t *mctx, int fl_longest_match, - int *p_match_first) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - int match = 0; - int match_last = -1; - int cur_str_idx = re_string_cur_idx (&mctx->input); - re_dfastate_t *cur_state; - int at_init_state = p_match_first != NULL; - int next_start_idx = cur_str_idx; - - err = REG_NOERROR; - cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); - /* An initial state must not be NULL (invalid). */ - if (BE (cur_state == NULL, 0)) - { - assert (err == REG_ESPACE); - return -2; - } - - if (mctx->state_log != NULL) - { - mctx->state_log[cur_str_idx] = cur_state; - - /* Check OP_OPEN_SUBEXP in the initial state in case that we use them - later. E.g. Processing back references. */ - if (BE (dfa->nbackref, 0)) - { - at_init_state = 0; - err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (cur_state->has_backref) - { - err = transit_state_bkref (mctx, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - - /* If the RE accepts NULL string. */ - if (BE (cur_state->halt, 0)) - { - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, cur_str_idx)) - { - if (!fl_longest_match) - return cur_str_idx; - else - { - match_last = cur_str_idx; - match = 1; - } - } - } - - while (!re_string_eoi (&mctx->input)) - { - re_dfastate_t *old_state = cur_state; - int next_char_idx = re_string_cur_idx (&mctx->input) + 1; - - if (BE (next_char_idx >= mctx->input.bufs_len, 0) - || (BE (next_char_idx >= mctx->input.valid_len, 0) - && mctx->input.valid_len < mctx->input.len)) - { - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - { - assert (err == REG_ESPACE); - return -2; - } - } - - cur_state = transit_state (&err, mctx, cur_state); - if (mctx->state_log != NULL) - cur_state = merge_state_with_log (&err, mctx, cur_state); - - if (cur_state == NULL) - { - /* Reached the invalid state or an error. Try to recover a valid - state using the state log, if available and if we have not - already found a valid (even if not the longest) match. */ - if (BE (err != REG_NOERROR, 0)) - return -2; - - if (mctx->state_log == NULL - || (match && !fl_longest_match) - || (cur_state = find_recover_state (&err, mctx)) == NULL) - break; - } - - if (BE (at_init_state, 0)) - { - if (old_state == cur_state) - next_start_idx = next_char_idx; - else - at_init_state = 0; - } - - if (cur_state->halt) - { - /* Reached a halt state. - Check the halt state can satisfy the current context. */ - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, - re_string_cur_idx (&mctx->input))) - { - /* We found an appropriate halt state. */ - match_last = re_string_cur_idx (&mctx->input); - match = 1; - - /* We found a match, do not modify match_first below. */ - p_match_first = NULL; - if (!fl_longest_match) - break; - } - } - } - - if (p_match_first) - *p_match_first += next_start_idx; - - return match_last; -} - -/* Check NODE match the current context. */ - -static int -internal_function -check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context) -{ - re_token_type_t type = dfa->nodes[node].type; - unsigned int constraint = dfa->nodes[node].constraint; - if (type != END_OF_RE) - return 0; - if (!constraint) - return 1; - if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) - return 0; - return 1; -} - -/* Check the halt state STATE match the current context. - Return 0 if not match, if the node, STATE has, is a halt node and - match the context, return the node. */ - -static int -internal_function -check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, int idx) -{ - int i; - unsigned int context; -#ifdef DEBUG - assert (state->halt); -#endif - context = re_string_context_at (&mctx->input, idx, mctx->eflags); - for (i = 0; i < state->nodes.nelem; ++i) - if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) - return state->nodes.elems[i]; - return 0; -} - -/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA - corresponding to the DFA). - Return the destination node, and update EPS_VIA_NODES, return -1 in case - of errors. */ - -static int -internal_function -proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, - int *pidx, int node, re_node_set *eps_via_nodes, - struct re_fail_stack_t *fs) -{ - const re_dfa_t *const dfa = mctx->dfa; - int i, err; - if (IS_EPSILON_NODE (dfa->nodes[node].type)) - { - re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; - re_node_set *edests = &dfa->edests[node]; - int dest_node; - err = re_node_set_insert (eps_via_nodes, node); - if (BE (err < 0, 0)) - return -2; - /* Pick up a valid destination, or return -1 if none is found. */ - for (dest_node = -1, i = 0; i < edests->nelem; ++i) - { - int candidate = edests->elems[i]; - if (!re_node_set_contains (cur_nodes, candidate)) - continue; - if (dest_node == -1) - dest_node = candidate; - - else - { - /* In order to avoid infinite loop like "(a*)*", return the second - epsilon-transition if the first was already considered. */ - if (re_node_set_contains (eps_via_nodes, dest_node)) - return candidate; - - /* Otherwise, push the second epsilon-transition on the fail stack. */ - else if (fs != NULL - && push_fail_stack (fs, *pidx, candidate, nregs, regs, - eps_via_nodes)) - return -2; - - /* We know we are going to exit. */ - break; - } - } - return dest_node; - } - else - { - int naccepted = 0; - re_token_type_t type = dfa->nodes[node].type; - -#ifdef RE_ENABLE_I18N - if (dfa->nodes[node].accept_mb) - naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); - else -#endif /* RE_ENABLE_I18N */ - if (type == OP_BACK_REF) - { - int subexp_idx = dfa->nodes[node].opr.idx + 1; - naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; - if (fs != NULL) - { - if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) - return -1; - else if (naccepted) - { - char *buf = (char *) re_string_get_buffer (&mctx->input); - if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, - naccepted) != 0) - return -1; - } - } - - if (naccepted == 0) - { - int dest_node; - err = re_node_set_insert (eps_via_nodes, node); - if (BE (err < 0, 0)) - return -2; - dest_node = dfa->edests[node].elems[0]; - if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node)) - return dest_node; - } - } - - if (naccepted != 0 - || check_node_accept (mctx, dfa->nodes + node, *pidx)) - { - int dest_node = dfa->nexts[node]; - *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; - if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL - || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node))) - return -1; - re_node_set_empty (eps_via_nodes); - return dest_node; - } - } - return -1; -} - -static reg_errcode_t -internal_function -push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, - int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) -{ - reg_errcode_t err; - int num = fs->num++; - if (fs->num == fs->alloc) - { - struct re_fail_stack_ent_t *new_array; - new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) - * fs->alloc * 2)); - if (new_array == NULL) - return REG_ESPACE; - fs->alloc *= 2; - fs->stack = new_array; - } - fs->stack[num].idx = str_idx; - fs->stack[num].node = dest_node; - fs->stack[num].regs = re_malloc (regmatch_t, nregs); - if (fs->stack[num].regs == NULL) - return REG_ESPACE; - memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); - err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); - return err; -} - -static int -internal_function -pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, - regmatch_t *regs, re_node_set *eps_via_nodes) -{ - int num = --fs->num; - assert (num >= 0); - *pidx = fs->stack[num].idx; - memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); - re_node_set_free (eps_via_nodes); - re_free (fs->stack[num].regs); - *eps_via_nodes = fs->stack[num].eps_via_nodes; - return fs->stack[num].node; -} - -/* Set the positions where the subexpressions are starts/ends to registers - PMATCH. - Note: We assume that pmatch[0] is already set, and - pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ - -static reg_errcode_t -internal_function -set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, - regmatch_t *pmatch, int fl_backtrack) -{ - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - int idx, cur_node; - re_node_set eps_via_nodes; - struct re_fail_stack_t *fs; - struct re_fail_stack_t fs_body = { 0, 2, NULL }; - regmatch_t *prev_idx_match; - int prev_idx_match_malloced = 0; - -#ifdef DEBUG - assert (nmatch > 1); - assert (mctx->state_log != NULL); -#endif - if (fl_backtrack) - { - fs = &fs_body; - fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); - if (fs->stack == NULL) - return REG_ESPACE; - } - else - fs = NULL; - - cur_node = dfa->init_node; - re_node_set_init_empty (&eps_via_nodes); - - if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) - prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); - else - { - prev_idx_match = re_malloc (regmatch_t, nmatch); - if (prev_idx_match == NULL) - { - free_fail_stack_return (fs); - return REG_ESPACE; - } - prev_idx_match_malloced = 1; - } - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - - for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) - { - update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); - - if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) - { - int reg_idx; - if (fs) - { - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) - break; - if (reg_idx == nmatch) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); - } - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - } - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOERROR; - } - } - - /* Proceed to next node. */ - cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, - &eps_via_nodes, fs); - - if (BE (cur_node < 0, 0)) - { - if (BE (cur_node == -2, 0)) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - free_fail_stack_return (fs); - return REG_ESPACE; - } - if (fs) - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOMATCH; - } - } - } - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); -} - -static reg_errcode_t -internal_function -free_fail_stack_return (struct re_fail_stack_t *fs) -{ - if (fs) - { - int fs_idx; - for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) - { - re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); - re_free (fs->stack[fs_idx].regs); - } - re_free (fs->stack); - } - return REG_NOERROR; -} - -static void -internal_function -update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) -{ - int type = dfa->nodes[cur_node].type; - if (type == OP_OPEN_SUBEXP) - { - int reg_num = dfa->nodes[cur_node].opr.idx + 1; - - /* We are at the first node of this sub expression. */ - if (reg_num < nmatch) - { - pmatch[reg_num].rm_so = cur_idx; - pmatch[reg_num].rm_eo = -1; - } - } - else if (type == OP_CLOSE_SUBEXP) - { - int reg_num = dfa->nodes[cur_node].opr.idx + 1; - if (reg_num < nmatch) - { - /* We are at the last node of this sub expression. */ - if (pmatch[reg_num].rm_so < cur_idx) - { - pmatch[reg_num].rm_eo = cur_idx; - /* This is a non-empty match or we are not inside an optional - subexpression. Accept this right away. */ - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - } - else - { - if (dfa->nodes[cur_node].opt_subexp - && prev_idx_match[reg_num].rm_so != -1) - /* We transited through an empty match for an optional - subexpression, like (a?)*, and this is not the subexp's - first match. Copy back the old content of the registers - so that matches of an inner subexpression are undone as - well, like in ((a?))*. */ - memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); - else - /* We completed a subexpression, but it may be part of - an optional one, so do not update PREV_IDX_MATCH. */ - pmatch[reg_num].rm_eo = cur_idx; - } - } - } -} - -/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 - and sift the nodes in each states according to the following rules. - Updated state_log will be wrote to STATE_LOG. - - Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... - 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If `a' isn't the LAST_NODE and `a' can't epsilon transit to - the LAST_NODE, we throw away the node `a'. - 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts - string `s' and transit to `b': - i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node `a'. - 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': - i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node `a'. */ - -#define STATE_NODE_CONTAINS(state,node) \ - ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) - -static reg_errcode_t -internal_function -sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) -{ - reg_errcode_t err; - int null_cnt = 0; - int str_idx = sctx->last_str_idx; - re_node_set cur_dest; - -#ifdef DEBUG - assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); -#endif - - /* Build sifted state_log[str_idx]. It has the nodes which can epsilon - transit to the last_node and the last_node itself. */ - err = re_node_set_init_1 (&cur_dest, sctx->last_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* Then check each states in the state_log. */ - while (str_idx > 0) - { - /* Update counters. */ - null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; - if (null_cnt > mctx->max_mb_elem_len) - { - memset (sctx->sifted_states, '\0', - sizeof (re_dfastate_t *) * str_idx); - re_node_set_free (&cur_dest); - return REG_NOERROR; - } - re_node_set_empty (&cur_dest); - --str_idx; - - if (mctx->state_log[str_idx]) - { - err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* Add all the nodes which satisfy the following conditions: - - It can epsilon transit to a node in CUR_DEST. - - It is in CUR_SRC. - And update state_log. */ - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - err = REG_NOERROR; - free_return: - re_node_set_free (&cur_dest); - return err; -} - -static reg_errcode_t -internal_function -build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, - int str_idx, re_node_set *cur_dest) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; - int i; - - /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. - Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]' - (with the epsilon nodes pre-filtered out). */ - for (i = 0; i < cur_src->nelem; i++) - { - int prev_node = cur_src->elems[i]; - int naccepted = 0; - int ret; - -#ifdef DEBUG - re_token_type_t type = dfa->nodes[prev_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[prev_node].accept_mb) - naccepted = sift_states_iter_mb (mctx, sctx, prev_node, - str_idx, sctx->last_str_idx); -#endif /* RE_ENABLE_I18N */ - - /* We don't check backreferences here. - See update_cur_sifted_state(). */ - if (!naccepted - && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) - && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], - dfa->nexts[prev_node])) - naccepted = 1; - - if (naccepted == 0) - continue; - - if (sctx->limits.nelem) - { - int to_idx = str_idx + naccepted; - if (check_dst_limits (mctx, &sctx->limits, - dfa->nexts[prev_node], to_idx, - prev_node, str_idx)) - continue; - } - ret = re_node_set_insert (cur_dest, prev_node); - if (BE (ret == -1, 0)) - return REG_ESPACE; - } - - return REG_NOERROR; -} - -/* Helper functions. */ - -static reg_errcode_t -internal_function -clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) -{ - int top = mctx->state_log_top; - - if (next_state_log_idx >= mctx->input.bufs_len - || (next_state_log_idx >= mctx->input.valid_len - && mctx->input.valid_len < mctx->input.len)) - { - reg_errcode_t err; - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (top < next_state_log_idx) - { - memset (mctx->state_log + top + 1, '\0', - sizeof (re_dfastate_t *) * (next_state_log_idx - top)); - mctx->state_log_top = next_state_log_idx; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, - re_dfastate_t **src, int num) -{ - int st_idx; - reg_errcode_t err; - for (st_idx = 0; st_idx < num; ++st_idx) - { - if (dst[st_idx] == NULL) - dst[st_idx] = src[st_idx]; - else if (src[st_idx] != NULL) - { - re_node_set merged_set; - err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, - &src[st_idx]->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); - re_node_set_free (&merged_set); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, int str_idx, - re_node_set *dest_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? NULL - : &mctx->state_log[str_idx]->nodes); - - if (dest_nodes->nelem == 0) - sctx->sifted_states[str_idx] = NULL; - else - { - if (candidates) - { - /* At first, add the nodes which can epsilon transit to a node in - DEST_NODE. */ - err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Then, check the limitations in the current sift_context. */ - if (sctx->limits.nelem) - { - err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, - mctx->bkref_ents, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - - sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (candidates && mctx->state_log[str_idx]->has_backref) - { - err = sift_states_bkref (mctx, sctx, str_idx, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - reg_errcode_t err = REG_NOERROR; - int i; - - re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (!state->inveclosure.alloc) - { - err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < dest_nodes->nelem; i++) - re_node_set_merge (&state->inveclosure, - dfa->inveclosures + dest_nodes->elems[i]); - } - return re_node_set_add_intersect (dest_nodes, candidates, - &state->inveclosure); -} - -static reg_errcode_t -internal_function -sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - int ecl_idx; - reg_errcode_t err; - re_node_set *inv_eclosure = dfa->inveclosures + node; - re_node_set except_nodes; - re_node_set_init_empty (&except_nodes); - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - int cur_node = inv_eclosure->elems[ecl_idx]; - if (cur_node == node) - continue; - if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) - { - int edst1 = dfa->edests[cur_node].elems[0]; - int edst2 = ((dfa->edests[cur_node].nelem > 1) - ? dfa->edests[cur_node].elems[1] : -1); - if ((!re_node_set_contains (inv_eclosure, edst1) - && re_node_set_contains (dest_nodes, edst1)) - || (edst2 > 0 - && !re_node_set_contains (inv_eclosure, edst2) - && re_node_set_contains (dest_nodes, edst2))) - { - err = re_node_set_add_intersect (&except_nodes, candidates, - dfa->inveclosures + cur_node); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&except_nodes); - return err; - } - } - } - } - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - int cur_node = inv_eclosure->elems[ecl_idx]; - if (!re_node_set_contains (&except_nodes, cur_node)) - { - int idx = re_node_set_contains (dest_nodes, cur_node) - 1; - re_node_set_remove_at (dest_nodes, idx); - } - } - re_node_set_free (&except_nodes); - return REG_NOERROR; -} - -static int -internal_function -check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, - int dst_node, int dst_idx, int src_node, int src_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int lim_idx, src_pos, dst_pos; - - int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); - int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - int subexp_idx; - struct re_backref_cache_entry *ent; - ent = mctx->bkref_ents + limits->elems[lim_idx]; - subexp_idx = dfa->nodes[ent->node].opr.idx; - - dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, dst_node, dst_idx, - dst_bkref_idx); - src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, src_node, src_idx, - src_bkref_idx); - - /* In case of: - ( ) - ( ) - ( ) */ - if (src_pos == dst_pos) - continue; /* This is unrelated limitation. */ - else - return 1; - } - return 0; -} - -static int -internal_function -check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, - int subexp_idx, int from_node, int bkref_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *eclosures = dfa->eclosures + from_node; - int node_idx; - - /* Else, we are on the boundary: examine the nodes on the epsilon - closure. */ - for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) - { - int node = eclosures->elems[node_idx]; - switch (dfa->nodes[node].type) - { - case OP_BACK_REF: - if (bkref_idx != -1) - { - struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; - do - { - int dst, cpos; - - if (ent->node != node) - continue; - - if (subexp_idx < BITSET_WORD_BITS - && !(ent->eps_reachable_subexps_map - & ((bitset_word_t) 1 << subexp_idx))) - continue; - - /* Recurse trying to reach the OP_OPEN_SUBEXP and - OP_CLOSE_SUBEXP cases below. But, if the - destination node is the same node as the source - node, don't recurse because it would cause an - infinite loop: a regex that exhibits this behavior - is ()\1*\1* */ - dst = dfa->edests[node].elems[0]; - if (dst == from_node) - { - if (boundaries & 1) - return -1; - else /* if (boundaries & 2) */ - return 0; - } - - cpos = - check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - dst, bkref_idx); - if (cpos == -1 /* && (boundaries & 1) */) - return -1; - if (cpos == 0 && (boundaries & 2)) - return 0; - - if (subexp_idx < BITSET_WORD_BITS) - ent->eps_reachable_subexps_map - &= ~((bitset_word_t) 1 << subexp_idx); - } - while (ent++->more); - } - break; - - case OP_OPEN_SUBEXP: - if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) - return -1; - break; - - case OP_CLOSE_SUBEXP: - if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) - return 0; - break; - - default: - break; - } - } - - return (boundaries & 2) ? 1 : 0; -} - -static int -internal_function -check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, - int subexp_idx, int from_node, int str_idx, - int bkref_idx) -{ - struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; - int boundaries; - - /* If we are outside the range of the subexpression, return -1 or 1. */ - if (str_idx < lim->subexp_from) - return -1; - - if (lim->subexp_to < str_idx) - return 1; - - /* If we are within the subexpression, return 0. */ - boundaries = (str_idx == lim->subexp_from); - boundaries |= (str_idx == lim->subexp_to) << 1; - if (boundaries == 0) - return 0; - - /* Else, examine epsilon closure. */ - return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - from_node, bkref_idx); -} - -/* Check the limitations of sub expressions LIMITS, and remove the nodes - which are against limitations from DEST_NODES. */ - -static reg_errcode_t -internal_function -check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates, re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, int str_idx) -{ - reg_errcode_t err; - int node_idx, lim_idx; - - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - int subexp_idx; - struct re_backref_cache_entry *ent; - ent = bkref_ents + limits->elems[lim_idx]; - - if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) - continue; /* This is unrelated limitation. */ - - subexp_idx = dfa->nodes[ent->node].opr.idx; - if (ent->subexp_to == str_idx) - { - int ops_node = -1; - int cls_node = -1; - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - int node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_OPEN_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - ops_node = node; - else if (type == OP_CLOSE_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - cls_node = node; - } - - /* Check the limitation of the open subexpression. */ - /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ - if (ops_node >= 0) - { - err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Check the limitation of the close subexpression. */ - if (cls_node >= 0) - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - int node = dest_nodes->elems[node_idx]; - if (!re_node_set_contains (dfa->inveclosures + node, - cls_node) - && !re_node_set_contains (dfa->eclosures + node, - cls_node)) - { - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - --node_idx; - } - } - } - else /* (ent->subexp_to != str_idx) */ - { - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - int node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) - { - if (subexp_idx != dfa->nodes[node].opr.idx) - continue; - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, - int str_idx, const re_node_set *candidates) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - int node_idx, node; - re_sift_context_t local_sctx; - int first_idx = search_cur_bkref_entry (mctx, str_idx); - - if (first_idx == -1) - return REG_NOERROR; - - local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ - - for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) - { - int enabled_idx; - re_token_type_t type; - struct re_backref_cache_entry *entry; - node = candidates->elems[node_idx]; - type = dfa->nodes[node].type; - /* Avoid infinite loop for the REs like "()\1+". */ - if (node == sctx->last_node && str_idx == sctx->last_str_idx) - continue; - if (type != OP_BACK_REF) - continue; - - entry = mctx->bkref_ents + first_idx; - enabled_idx = first_idx; - do - { - int subexp_len; - int to_idx; - int dst_node; - int ret; - re_dfastate_t *cur_state; - - if (entry->node != node) - continue; - subexp_len = entry->subexp_to - entry->subexp_from; - to_idx = str_idx + subexp_len; - dst_node = (subexp_len ? dfa->nexts[node] - : dfa->edests[node].elems[0]); - - if (to_idx > sctx->last_str_idx - || sctx->sifted_states[to_idx] == NULL - || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) - || check_dst_limits (mctx, &sctx->limits, node, - str_idx, dst_node, to_idx)) - continue; - - if (local_sctx.sifted_states == NULL) - { - local_sctx = *sctx; - err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.last_node = node; - local_sctx.last_str_idx = str_idx; - ret = re_node_set_insert (&local_sctx.limits, enabled_idx); - if (BE (ret < 0, 0)) - { - err = REG_ESPACE; - goto free_return; - } - cur_state = local_sctx.sifted_states[str_idx]; - err = sift_states_backward (mctx, &local_sctx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - if (sctx->limited_states != NULL) - { - err = merge_state_array (dfa, sctx->limited_states, - local_sctx.sifted_states, - str_idx + 1); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.sifted_states[str_idx] = cur_state; - re_node_set_remove (&local_sctx.limits, enabled_idx); - - /* mctx->bkref_ents may have changed, reload the pointer. */ - entry = mctx->bkref_ents + enabled_idx; - } - while (enabled_idx++, entry++->more); - } - err = REG_NOERROR; - free_return: - if (local_sctx.sifted_states != NULL) - { - re_node_set_free (&local_sctx.limits); - } - - return err; -} - - -#ifdef RE_ENABLE_I18N -static int -internal_function -sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, - int node_idx, int str_idx, int max_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int naccepted; - /* Check the node can accept `multi byte'. */ - naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); - if (naccepted > 0 && str_idx + naccepted <= max_str_idx && - !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], - dfa->nexts[node_idx])) - /* The node can't accept the `multi byte', or the - destination was already thrown away, then the node - could't accept the current input `multi byte'. */ - naccepted = 0; - /* Otherwise, it is sure that the node could accept - `naccepted' bytes input. */ - return naccepted; -} -#endif /* RE_ENABLE_I18N */ - - -/* Functions for state transition. */ - -/* Return the next state to which the current state STATE will transit by - accepting the current input byte, and update STATE_LOG if necessary. - If STATE can accept a multibyte char/collating element/back reference - update the destination of STATE_LOG. */ - -static re_dfastate_t * -internal_function -transit_state (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - re_dfastate_t **trtable; - unsigned char ch; - -#ifdef RE_ENABLE_I18N - /* If the current state can accept multibyte. */ - if (BE (state->accept_mb, 0)) - { - *err = transit_state_mb (mctx, state); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } -#endif /* RE_ENABLE_I18N */ - - /* Then decide the next state with the single byte. */ -#if 0 - if (0) - /* don't use transition table */ - return transit_state_sb (err, mctx, state); -#endif - - /* Use transition table */ - ch = re_string_fetch_byte (&mctx->input); - for (;;) - { - trtable = state->trtable; - if (BE (trtable != NULL, 1)) - return trtable[ch]; - - trtable = state->word_trtable; - if (BE (trtable != NULL, 1)) - { - unsigned int context; - context - = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return trtable[ch + SBC_MAX]; - else - return trtable[ch]; - } - - if (!build_trtable (mctx->dfa, state)) - { - *err = REG_ESPACE; - return NULL; - } - - /* Retry, we now have a transition table. */ - } -} - -/* Update the state_log if we need */ -re_dfastate_t * -internal_function -merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *next_state) -{ - const re_dfa_t *const dfa = mctx->dfa; - int cur_idx = re_string_cur_idx (&mctx->input); - - if (cur_idx > mctx->state_log_top) - { - mctx->state_log[cur_idx] = next_state; - mctx->state_log_top = cur_idx; - } - else if (mctx->state_log[cur_idx] == 0) - { - mctx->state_log[cur_idx] = next_state; - } - else - { - re_dfastate_t *pstate; - unsigned int context; - re_node_set next_nodes, *log_nodes, *table_nodes = NULL; - /* If (state_log[cur_idx] != 0), it implies that cur_idx is - the destination of a multibyte char/collating element/ - back reference. Then the next state is the union set of - these destinations and the results of the transition table. */ - pstate = mctx->state_log[cur_idx]; - log_nodes = pstate->entrance_nodes; - if (next_state != NULL) - { - table_nodes = next_state->entrance_nodes; - *err = re_node_set_init_union (&next_nodes, table_nodes, - log_nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - else - next_nodes = *log_nodes; - /* Note: We already add the nodes of the initial state, - then we don't need to add them here. */ - - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - next_state = mctx->state_log[cur_idx] - = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - if (table_nodes != NULL) - re_node_set_free (&next_nodes); - } - - if (BE (dfa->nbackref, 0) && next_state != NULL) - { - /* Check OP_OPEN_SUBEXP in the current state in case that we use them - later. We must check them here, since the back references in the - next state might use them. */ - *err = check_subexp_matching_top (mctx, &next_state->nodes, - cur_idx); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - - /* If the next state has back references. */ - if (next_state->has_backref) - { - *err = transit_state_bkref (mctx, &next_state->nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - next_state = mctx->state_log[cur_idx]; - } - } - - return next_state; -} - -/* Skip bytes in the input that correspond to part of a - multi-byte match, then look in the log for a state - from which to restart matching. */ -re_dfastate_t * -internal_function -find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) -{ - re_dfastate_t *cur_state; - do - { - int max = mctx->state_log_top; - int cur_str_idx = re_string_cur_idx (&mctx->input); - - do - { - if (++cur_str_idx > max) - return NULL; - re_string_skip_bytes (&mctx->input, 1); - } - while (mctx->state_log[cur_str_idx] == NULL); - - cur_state = merge_state_with_log (err, mctx, NULL); - } - while (*err == REG_NOERROR && cur_state == NULL); - return cur_state; -} - -/* Helper functions for transit_state. */ - -/* From the node set CUR_NODES, pick up the nodes whose types are - OP_OPEN_SUBEXP and which have corresponding back references in the regular - expression. And register them to use them later for evaluating the - correspoding back references. */ - -static reg_errcode_t -internal_function -check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, - int str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int node_idx; - reg_errcode_t err; - - /* TODO: This isn't efficient. - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) - { - int node = cur_nodes->elems[node_idx]; - if (dfa->nodes[node].type == OP_OPEN_SUBEXP - && dfa->nodes[node].opr.idx < BITSET_WORD_BITS - && (dfa->used_bkref_map - & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) - { - err = match_ctx_add_subtop (mctx, node, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -#if 0 -/* Return the next state to which the current state STATE will transit by - accepting the current input byte. */ - -static re_dfastate_t * -transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - const re_dfa_t *const dfa = mctx->dfa; - re_node_set next_nodes; - re_dfastate_t *next_state; - int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); - unsigned int context; - - *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) - { - int cur_node = state->nodes.elems[node_cnt]; - if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) - { - *err = re_node_set_merge (&next_nodes, - dfa->eclosures + dfa->nexts[cur_node]); - if (BE (*err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return NULL; - } - } - } - context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); - next_state = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - re_node_set_free (&next_nodes); - re_string_skip_bytes (&mctx->input, 1); - return next_state; -} -#endif - -#ifdef RE_ENABLE_I18N -static reg_errcode_t -internal_function -transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - int i; - - for (i = 0; i < pstate->nodes.nelem; ++i) - { - re_node_set dest_nodes, *new_nodes; - int cur_node_idx = pstate->nodes.elems[i]; - int naccepted, dest_idx; - unsigned int context; - re_dfastate_t *dest_state; - - if (!dfa->nodes[cur_node_idx].accept_mb) - continue; - - if (dfa->nodes[cur_node_idx].constraint) - { - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input), - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, - context)) - continue; - } - - /* How many bytes the node can accept? */ - naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, - re_string_cur_idx (&mctx->input)); - if (naccepted == 0) - continue; - - /* The node can accepts `naccepted' bytes. */ - dest_idx = re_string_cur_idx (&mctx->input) + naccepted; - mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted - : mctx->max_mb_elem_len); - err = clean_state_log_if_needed (mctx, dest_idx); - if (BE (err != REG_NOERROR, 0)) - return err; -#ifdef DEBUG - assert (dfa->nexts[cur_node_idx] != -1); -#endif - new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; - - dest_state = mctx->state_log[dest_idx]; - if (dest_state == NULL) - dest_nodes = *new_nodes; - else - { - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, new_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - context = re_string_context_at (&mctx->input, dest_idx - 1, - mctx->eflags); - mctx->state_log[dest_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - if (dest_state != NULL) - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} -#endif /* RE_ENABLE_I18N */ - -static reg_errcode_t -internal_function -transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - int i; - int cur_str_idx = re_string_cur_idx (&mctx->input); - - for (i = 0; i < nodes->nelem; ++i) - { - int dest_str_idx, prev_nelem, bkc_idx; - int node_idx = nodes->elems[i]; - unsigned int context; - const re_token_t *node = dfa->nodes + node_idx; - re_node_set *new_dest_nodes; - - /* Check whether `node' is a backreference or not. */ - if (node->type != OP_BACK_REF) - continue; - - if (node->constraint) - { - context = re_string_context_at (&mctx->input, cur_str_idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - continue; - } - - /* `node' is a backreference. - Check the substring which the substring matched. */ - bkc_idx = mctx->nbkref_ents; - err = get_subexp (mctx, node_idx, cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* And add the epsilon closures (which is `new_dest_nodes') of - the backreference to appropriate state_log. */ -#ifdef DEBUG - assert (dfa->nexts[node_idx] != -1); -#endif - for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) - { - int subexp_len; - re_dfastate_t *dest_state; - struct re_backref_cache_entry *bkref_ent; - bkref_ent = mctx->bkref_ents + bkc_idx; - if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) - continue; - subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; - new_dest_nodes = (subexp_len == 0 - ? dfa->eclosures + dfa->edests[node_idx].elems[0] - : dfa->eclosures + dfa->nexts[node_idx]); - dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - - bkref_ent->subexp_from); - context = re_string_context_at (&mctx->input, dest_str_idx - 1, - mctx->eflags); - dest_state = mctx->state_log[dest_str_idx]; - prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 - : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add `new_dest_node' to state_log. */ - if (dest_state == NULL) - { - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, new_dest_nodes, - context); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - else - { - re_node_set dest_nodes; - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, - new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&dest_nodes); - goto free_return; - } - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - /* We need to check recursively if the backreference can epsilon - transit. */ - if (subexp_len == 0 - && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) - { - err = check_subexp_matching_top (mctx, new_dest_nodes, - cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - err = transit_state_bkref (mctx, new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - } - } - err = REG_NOERROR; - free_return: - return err; -} - -/* Enumerate all the candidates which the backreference BKREF_NODE can match - at BKREF_STR_IDX, and register them by match_ctx_add_entry(). - Note that we might collect inappropriate candidates here. - However, the cost of checking them strictly here is too high, then we - delay these checking for prune_impossible_nodes(). */ - -static reg_errcode_t -internal_function -get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int subexp_num, sub_top_idx; - const char *buf = (const char *) re_string_get_buffer (&mctx->input); - /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ - int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); - if (cache_idx != -1) - { - const struct re_backref_cache_entry *entry - = mctx->bkref_ents + cache_idx; - do - if (entry->node == bkref_node) - return REG_NOERROR; /* We already checked it. */ - while (entry++->more); - } - - subexp_num = dfa->nodes[bkref_node].opr.idx; - - /* For each sub expression */ - for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) - { - reg_errcode_t err; - re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; - re_sub_match_last_t *sub_last; - int sub_last_idx, sl_str, bkref_str_off; - - if (dfa->nodes[sub_top->node].opr.idx != subexp_num) - continue; /* It isn't related. */ - - sl_str = sub_top->str_idx; - bkref_str_off = bkref_str_idx; - /* At first, check the last node of sub expressions we already - evaluated. */ - for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) - { - int sl_str_diff; - sub_last = sub_top->lasts[sub_last_idx]; - sl_str_diff = sub_last->str_idx - sl_str; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_diff > 0) - { - if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) - { - /* Not enough chars for a successful match. */ - if (bkref_str_off + sl_str_diff > mctx->input.len) - break; - - err = clean_state_log_if_needed (mctx, - bkref_str_off - + sl_str_diff); - if (BE (err != REG_NOERROR, 0)) - return err; - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) - /* We don't need to search this sub expression any more. */ - break; - } - bkref_str_off += sl_str_diff; - sl_str += sl_str_diff; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - - /* Reload buf, since the preceding call might have reallocated - the buffer. */ - buf = (const char *) re_string_get_buffer (&mctx->input); - - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (sub_last_idx < sub_top->nlasts) - continue; - if (sub_last_idx > 0) - ++sl_str; - /* Then, search for the other last nodes of the sub expression. */ - for (; sl_str <= bkref_str_idx; ++sl_str) - { - int cls_node, sl_str_off; - const re_node_set *nodes; - sl_str_off = sl_str - sub_top->str_idx; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_off > 0) - { - if (BE (bkref_str_off >= mctx->input.valid_len, 0)) - { - /* If we are at the end of the input, we cannot match. */ - if (bkref_str_off >= mctx->input.len) - break; - - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (buf [bkref_str_off++] != buf[sl_str - 1]) - break; /* We don't need to search this sub expression - any more. */ - } - if (mctx->state_log[sl_str] == NULL) - continue; - /* Does this state have a ')' of the sub expression? */ - nodes = &mctx->state_log[sl_str]->nodes; - cls_node = find_subexp_node (dfa, nodes, subexp_num, - OP_CLOSE_SUBEXP); - if (cls_node == -1) - continue; /* No. */ - if (sub_top->path == NULL) - { - sub_top->path = calloc (sizeof (state_array_t), - sl_str - sub_top->str_idx + 1); - if (sub_top->path == NULL) - return REG_ESPACE; - } - /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node - in the current context? */ - err = check_arrival (mctx, sub_top->path, sub_top->node, - sub_top->str_idx, cls_node, sl_str, - OP_CLOSE_SUBEXP); - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); - if (BE (sub_last == NULL, 0)) - return REG_ESPACE; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - if (err == REG_NOMATCH) - continue; - } - } - return REG_NOERROR; -} - -/* Helper functions for get_subexp(). */ - -/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. - If it can arrive, register the sub expression expressed with SUB_TOP - and SUB_LAST. */ - -static reg_errcode_t -internal_function -get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) -{ - reg_errcode_t err; - int to_idx; - /* Can the subexpression arrive the back reference? */ - err = check_arrival (mctx, &sub_last->path, sub_last->node, - sub_last->str_idx, bkref_node, bkref_str, - OP_OPEN_SUBEXP); - if (err != REG_NOERROR) - return err; - err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, - sub_last->str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; - return clean_state_log_if_needed (mctx, to_idx); -} - -/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. - Search '(' if FL_OPEN, or search ')' otherwise. - TODO: This function isn't efficient... - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - -static int -internal_function -find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - int subexp_idx, int type) -{ - int cls_idx; - for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) - { - int cls_node = nodes->elems[cls_idx]; - const re_token_t *node = dfa->nodes + cls_node; - if (node->type == type - && node->opr.idx == subexp_idx) - return cls_node; - } - return -1; -} - -/* Check whether the node TOP_NODE at TOP_STR can arrive to the node - LAST_NODE at LAST_STR. We record the path onto PATH since it will be - heavily reused. - Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ - -static reg_errcode_t -internal_function -check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, - int top_str, int last_node, int last_str, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - int subexp_num, backup_cur_idx, str_idx, null_cnt; - re_dfastate_t *cur_state = NULL; - re_node_set *cur_nodes, next_nodes; - re_dfastate_t **backup_state_log; - unsigned int context; - - subexp_num = dfa->nodes[top_node].opr.idx; - /* Extend the buffer if we need. */ - if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) - { - re_dfastate_t **new_array; - int old_alloc = path->alloc; - path->alloc += last_str + mctx->max_mb_elem_len + 1; - new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); - if (BE (new_array == NULL, 0)) - { - path->alloc = old_alloc; - return REG_ESPACE; - } - path->array = new_array; - memset (new_array + old_alloc, '\0', - sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); - } - - str_idx = path->next_idx ? path->next_idx : top_str; - - /* Temporary modify MCTX. */ - backup_state_log = mctx->state_log; - backup_cur_idx = mctx->input.cur_idx; - mctx->state_log = path->array; - mctx->input.cur_idx = str_idx; - - /* Setup initial node set. */ - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - if (str_idx == top_str) - { - err = re_node_set_init_1 (&next_nodes, top_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - else - { - cur_state = mctx->state_log[str_idx]; - if (cur_state && cur_state->has_backref) - { - err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - re_node_set_init_empty (&next_nodes); - } - if (str_idx == top_str || (cur_state && cur_state->has_backref)) - { - if (next_nodes.nelem) - { - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - } - - for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) - { - re_node_set_empty (&next_nodes); - if (mctx->state_log[str_idx + 1]) - { - err = re_node_set_merge (&next_nodes, - &mctx->state_log[str_idx + 1]->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - if (cur_state) - { - err = check_arrival_add_next_nodes (mctx, str_idx, - &cur_state->non_eps_nodes, - &next_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - ++str_idx; - if (next_nodes.nelem) - { - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - null_cnt = cur_state == NULL ? null_cnt + 1 : 0; - } - re_node_set_free (&next_nodes); - cur_nodes = (mctx->state_log[last_str] == NULL ? NULL - : &mctx->state_log[last_str]->nodes); - path->next_idx = str_idx; - - /* Fix MCTX. */ - mctx->state_log = backup_state_log; - mctx->input.cur_idx = backup_cur_idx; - - /* Then check the current node set has the node LAST_NODE. */ - if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) - return REG_NOERROR; - - return REG_NOMATCH; -} - -/* Helper functions for check_arrival. */ - -/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them - to NEXT_NODES. - TODO: This function is similar to the functions transit_state*(), - however this function has many additional works. - Can't we unify them? */ - -static reg_errcode_t -internal_function -check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, - re_node_set *cur_nodes, re_node_set *next_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - int result; - int cur_idx; - reg_errcode_t err = REG_NOERROR; - re_node_set union_set; - re_node_set_init_empty (&union_set); - for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) - { - int naccepted = 0; - int cur_node = cur_nodes->elems[cur_idx]; -#ifdef DEBUG - re_token_type_t type = dfa->nodes[cur_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[cur_node].accept_mb) - { - naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, - str_idx); - if (naccepted > 1) - { - re_dfastate_t *dest_state; - int next_node = dfa->nexts[cur_node]; - int next_idx = str_idx + naccepted; - dest_state = mctx->state_log[next_idx]; - re_node_set_empty (&union_set); - if (dest_state) - { - err = re_node_set_merge (&union_set, &dest_state->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - result = re_node_set_insert (&union_set, next_node); - if (BE (result < 0, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - mctx->state_log[next_idx] = re_acquire_state (&err, dfa, - &union_set); - if (BE (mctx->state_log[next_idx] == NULL - && err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - } -#endif /* RE_ENABLE_I18N */ - if (naccepted - || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) - { - result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); - if (BE (result < 0, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - } - } - re_node_set_free (&union_set); - return REG_NOERROR; -} - -/* For all the nodes in CUR_NODES, add the epsilon closures of them to - CUR_NODES, however exclude the nodes which are: - - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. -*/ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, - int ex_subexp, int type) -{ - reg_errcode_t err; - int idx, outside_node; - re_node_set new_nodes; -#ifdef DEBUG - assert (cur_nodes->nelem); -#endif - err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return err; - /* Create a new node set NEW_NODES with the nodes which are epsilon - closures of the node in CUR_NODES. */ - - for (idx = 0; idx < cur_nodes->nelem; ++idx) - { - int cur_node = cur_nodes->elems[idx]; - const re_node_set *eclosure = dfa->eclosures + cur_node; - outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); - if (outside_node == -1) - { - /* There are no problematic nodes, just merge them. */ - err = re_node_set_merge (&new_nodes, eclosure); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - else - { - /* There are problematic nodes, re-calculate incrementally. */ - err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - } - re_node_set_free (cur_nodes); - *cur_nodes = new_nodes; - return REG_NOERROR; -} - -/* Helper function for check_arrival_expand_ecl. - Check incrementally the epsilon closure of TARGET, and if it isn't - problematic append it to DST_NODES. */ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, - int target, int ex_subexp, int type) -{ - int cur_node; - for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) - { - int err; - - if (dfa->nodes[cur_node].type == type - && dfa->nodes[cur_node].opr.idx == ex_subexp) - { - if (type == OP_CLOSE_SUBEXP) - { - err = re_node_set_insert (dst_nodes, cur_node); - if (BE (err == -1, 0)) - return REG_ESPACE; - } - break; - } - err = re_node_set_insert (dst_nodes, cur_node); - if (BE (err == -1, 0)) - return REG_ESPACE; - if (dfa->edests[cur_node].nelem == 0) - break; - if (dfa->edests[cur_node].nelem == 2) - { - err = check_arrival_expand_ecl_sub (dfa, dst_nodes, - dfa->edests[cur_node].elems[1], - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - return err; - } - cur_node = dfa->edests[cur_node].elems[0]; - } - return REG_NOERROR; -} - - -/* For all the back references in the current state, calculate the - destination of the back references by the appropriate entry - in MCTX->BKREF_ENTS. */ - -static reg_errcode_t -internal_function -expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, - int cur_str, int subexp_num, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); - struct re_backref_cache_entry *ent; - - if (cache_idx_start == -1) - return REG_NOERROR; - - restart: - ent = mctx->bkref_ents + cache_idx_start; - do - { - int to_idx, next_node; - - /* Is this entry ENT is appropriate? */ - if (!re_node_set_contains (cur_nodes, ent->node)) - continue; /* No. */ - - to_idx = cur_str + ent->subexp_to - ent->subexp_from; - /* Calculate the destination of the back reference, and append it - to MCTX->STATE_LOG. */ - if (to_idx == cur_str) - { - /* The backreference did epsilon transit, we must re-check all the - node in the current state. */ - re_node_set new_dests; - reg_errcode_t err2, err3; - next_node = dfa->edests[ent->node].elems[0]; - if (re_node_set_contains (cur_nodes, next_node)) - continue; - err = re_node_set_init_1 (&new_dests, next_node); - err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); - err3 = re_node_set_merge (cur_nodes, &new_dests); - re_node_set_free (&new_dests); - if (BE (err != REG_NOERROR || err2 != REG_NOERROR - || err3 != REG_NOERROR, 0)) - { - err = (err != REG_NOERROR ? err - : (err2 != REG_NOERROR ? err2 : err3)); - return err; - } - /* TODO: It is still inefficient... */ - goto restart; - } - else - { - re_node_set union_set; - next_node = dfa->nexts[ent->node]; - if (mctx->state_log[to_idx]) - { - int ret; - if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, - next_node)) - continue; - err = re_node_set_init_copy (&union_set, - &mctx->state_log[to_idx]->nodes); - ret = re_node_set_insert (&union_set, next_node); - if (BE (err != REG_NOERROR || ret < 0, 0)) - { - re_node_set_free (&union_set); - err = err != REG_NOERROR ? err : REG_ESPACE; - return err; - } - } - else - { - err = re_node_set_init_1 (&union_set, next_node); - if (BE (err != REG_NOERROR, 0)) - return err; - } - mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); - re_node_set_free (&union_set); - if (BE (mctx->state_log[to_idx] == NULL - && err != REG_NOERROR, 0)) - return err; - } - } - while (ent++->more); - return REG_NOERROR; -} - -/* Build transition table for the state. - Return 1 if succeeded, otherwise return NULL. */ - -static int -internal_function -build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) -{ - reg_errcode_t err; - int i, j, ch, need_word_trtable = 0; - bitset_word_t elem, mask; - bool dests_node_malloced = false; - bool dest_states_malloced = false; - int ndests; /* Number of the destination states from `state'. */ - re_dfastate_t **trtable; - re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; - re_node_set follows, *dests_node; - bitset_t *dests_ch; - bitset_t acceptable; - - struct dests_alloc - { - re_node_set dests_node[SBC_MAX]; - bitset_t dests_ch[SBC_MAX]; - } *dests_alloc; - - /* We build DFA states which corresponds to the destination nodes - from `state'. `dests_node[i]' represents the nodes which i-th - destination state contains, and `dests_ch[i]' represents the - characters which i-th destination state accepts. */ - if (__libc_use_alloca (sizeof (struct dests_alloc))) - dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); - else - { - dests_alloc = re_malloc (struct dests_alloc, 1); - if (BE (dests_alloc == NULL, 0)) - return 0; - dests_node_malloced = true; - } - dests_node = dests_alloc->dests_node; - dests_ch = dests_alloc->dests_ch; - - /* Initialize transiton table. */ - state->word_trtable = state->trtable = NULL; - - /* At first, group all nodes belonging to `state' into several - destinations. */ - ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); - if (BE (ndests <= 0, 0)) - { - if (dests_node_malloced) - free (dests_alloc); - /* Return 0 in case of an error, 1 otherwise. */ - if (ndests == 0) - { - state->trtable = (re_dfastate_t **) - calloc (sizeof (re_dfastate_t *), SBC_MAX); - return 1; - } - return 0; - } - - err = re_node_set_alloc (&follows, ndests + 1); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - - if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX - + ndests * 3 * sizeof (re_dfastate_t *))) - dest_states = (re_dfastate_t **) - alloca (ndests * 3 * sizeof (re_dfastate_t *)); - else - { - dest_states = (re_dfastate_t **) - malloc (ndests * 3 * sizeof (re_dfastate_t *)); - if (BE (dest_states == NULL, 0)) - { -out_free: - if (dest_states_malloced) - free (dest_states); - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - if (dests_node_malloced) - free (dests_alloc); - return 0; - } - dest_states_malloced = true; - } - dest_states_word = dest_states + ndests; - dest_states_nl = dest_states_word + ndests; - bitset_empty (acceptable); - - /* Then build the states for all destinations. */ - for (i = 0; i < ndests; ++i) - { - int next_node; - re_node_set_empty (&follows); - /* Merge the follows of this destination states. */ - for (j = 0; j < dests_node[i].nelem; ++j) - { - next_node = dfa->nexts[dests_node[i].elems[j]]; - if (next_node != -1) - { - err = re_node_set_merge (&follows, dfa->eclosures + next_node); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - } - } - dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); - if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - /* If the new state has context constraint, - build appropriate states for these contexts. */ - if (dest_states[i]->has_constraint) - { - dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_WORD); - if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - - if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) - need_word_trtable = 1; - - dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_NEWLINE); - if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - } - else - { - dest_states_word[i] = dest_states[i]; - dest_states_nl[i] = dest_states[i]; - } - bitset_merge (acceptable, dests_ch[i]); - } - - if (!BE (need_word_trtable, 0)) - { - /* We don't care about whether the following character is a word - character, or we are in a single-byte character set so we can - discern by looking at the character code: allocate a - 256-entry transition table. */ - trtable = state->trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - if (dfa->word_char[i] & mask) - trtable[ch] = dest_states_word[j]; - else - trtable[ch] = dest_states[j]; - } - } - else - { - /* We care about whether the following character is a word - character, and we are in a multi-byte character set: discern - by looking at the character code: build two 256-entry - transition tables, one starting at trtable[0] and one - starting at trtable[SBC_MAX]. */ - trtable = state->word_trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - trtable[ch] = dest_states[j]; - trtable[ch + SBC_MAX] = dest_states_word[j]; - } - } - - /* new line */ - if (bitset_contain (acceptable, NEWLINE_CHAR)) - { - /* The current state accepts newline character. */ - for (j = 0; j < ndests; ++j) - if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) - { - /* k-th destination accepts newline character. */ - trtable[NEWLINE_CHAR] = dest_states_nl[j]; - if (need_word_trtable) - trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; - /* There must be only one destination which accepts - newline. See group_nodes_into_DFAstates. */ - break; - } - } - - if (dest_states_malloced) - free (dest_states); - - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - - if (dests_node_malloced) - free (dests_alloc); - - return 1; -} - -/* Group all nodes belonging to STATE into several destinations. - Then for all destinations, set the nodes belonging to the destination - to DESTS_NODE[i] and set the characters accepted by the destination - to DEST_CH[i]. This function return the number of destinations. */ - -static int -internal_function -group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, - re_node_set *dests_node, bitset_t *dests_ch) -{ - reg_errcode_t err; - int result; - int i, j, k; - int ndests; /* Number of the destinations from `state'. */ - bitset_t accepts; /* Characters a node can accept. */ - const re_node_set *cur_nodes = &state->nodes; - bitset_empty (accepts); - ndests = 0; - - /* For all the nodes belonging to `state', */ - for (i = 0; i < cur_nodes->nelem; ++i) - { - re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - /* Enumerate all single byte character this node can accept. */ - if (type == CHARACTER) - bitset_set (accepts, node->opr.c); - else if (type == SIMPLE_BRACKET) - { - bitset_merge (accepts, node->opr.sbcset); - } - else if (type == OP_PERIOD) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - bitset_merge (accepts, dfa->sb_char); - else -#endif - bitset_set_all (accepts); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#ifdef RE_ENABLE_I18N - else if (type == OP_UTF8_PERIOD) - { - memset (accepts, '\xff', sizeof (bitset_t) / 2); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#endif - else - continue; - - /* Check the `accepts' and sift the characters which are not - match it the context. */ - if (constraint) - { - if (constraint & NEXT_NEWLINE_CONSTRAINT) - { - bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); - bitset_empty (accepts); - if (accepts_newline) - bitset_set (accepts, NEWLINE_CHAR); - else - continue; - } - if (constraint & NEXT_ENDBUF_CONSTRAINT) - { - bitset_empty (accepts); - continue; - } - - if (constraint & NEXT_WORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && !node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= dfa->word_char[j]); - if (!any_set) - continue; - } - if (constraint & NEXT_NOTWORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~dfa->word_char[j]); - if (!any_set) - continue; - } - } - - /* Then divide `accepts' into DFA states, or create a new - state. Above, we make sure that accepts is not empty. */ - for (j = 0; j < ndests; ++j) - { - bitset_t intersec; /* Intersection sets, see below. */ - bitset_t remains; - /* Flags, see below. */ - bitset_word_t has_intersec, not_subset, not_consumed; - - /* Optimization, skip if this state doesn't accept the character. */ - if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) - continue; - - /* Enumerate the intersection set of this state and `accepts'. */ - has_intersec = 0; - for (k = 0; k < BITSET_WORDS; ++k) - has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; - /* And skip if the intersection set is empty. */ - if (!has_intersec) - continue; - - /* Then check if this state is a subset of `accepts'. */ - not_subset = not_consumed = 0; - for (k = 0; k < BITSET_WORDS; ++k) - { - not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; - not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; - } - - /* If this state isn't a subset of `accepts', create a - new group state, which has the `remains'. */ - if (not_subset) - { - bitset_copy (dests_ch[ndests], remains); - bitset_copy (dests_ch[j], intersec); - err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - } - - /* Put the position in the current group. */ - result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); - if (BE (result < 0, 0)) - goto error_return; - - /* If all characters are consumed, go to next node. */ - if (!not_consumed) - break; - } - /* Some characters remain, create a new group. */ - if (j == ndests) - { - bitset_copy (dests_ch[ndests], accepts); - err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - bitset_empty (accepts); - } - } - return ndests; - error_return: - for (j = 0; j < ndests; ++j) - re_node_set_free (dests_node + j); - return -1; -} - -#ifdef RE_ENABLE_I18N -/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. - Return the number of the bytes the node accepts. - STR_IDX is the current index of the input string. - - This function handles the nodes which can accept one character, or - one collating element like '.', '[a-z]', opposite to the other nodes - can only accept one byte. */ - -static int -internal_function -check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, - const re_string_t *input, int str_idx) -{ - const re_token_t *node = dfa->nodes + node_idx; - int char_len, elem_len; - int i; - - if (BE (node->type == OP_UTF8_PERIOD, 0)) - { - unsigned char c = re_string_byte_at (input, str_idx), d; - if (BE (c < 0xc2, 1)) - return 0; - - if (str_idx + 2 > input->len) - return 0; - - d = re_string_byte_at (input, str_idx + 1); - if (c < 0xe0) - return (d < 0x80 || d > 0xbf) ? 0 : 2; - else if (c < 0xf0) - { - char_len = 3; - if (c == 0xe0 && d < 0xa0) - return 0; - } - else if (c < 0xf8) - { - char_len = 4; - if (c == 0xf0 && d < 0x90) - return 0; - } - else if (c < 0xfc) - { - char_len = 5; - if (c == 0xf8 && d < 0x88) - return 0; - } - else if (c < 0xfe) - { - char_len = 6; - if (c == 0xfc && d < 0x84) - return 0; - } - else - return 0; - - if (str_idx + char_len > input->len) - return 0; - - for (i = 1; i < char_len; ++i) - { - d = re_string_byte_at (input, str_idx + i); - if (d < 0x80 || d > 0xbf) - return 0; - } - return char_len; - } - - char_len = re_string_char_size_at (input, str_idx); - if (node->type == OP_PERIOD) - { - if (char_len <= 1) - return 0; - /* FIXME: I don't think this if is needed, as both '\n' - and '\0' are char_len == 1. */ - /* '.' accepts any one character except the following two cases. */ - if ((!(dfa->syntax & RE_DOT_NEWLINE) && - re_string_byte_at (input, str_idx) == '\n') || - ((dfa->syntax & RE_DOT_NOT_NULL) && - re_string_byte_at (input, str_idx) == '\0')) - return 0; - return char_len; - } - - elem_len = re_string_elem_size_at (input, str_idx); - if ((elem_len <= 1 && char_len <= 1) || char_len == 0) - return 0; - - if (node->type == COMPLEX_BRACKET) - { - const re_charset_t *cset = node->opr.mbcset; -# ifdef _LIBC - const unsigned char *pin - = ((const unsigned char *) re_string_get_buffer (input) + str_idx); - int j; - uint32_t nrules; -# endif /* _LIBC */ - int match_len = 0; - wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) - ? re_string_wchar_at (input, str_idx) : 0); - - /* match with multibyte character? */ - for (i = 0; i < cset->nmbchars; ++i) - if (wc == cset->mbchars[i]) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - /* match with character_class? */ - for (i = 0; i < cset->nchar_classes; ++i) - { - wctype_t wt = cset->char_classes[i]; - if (__iswctype (wc, wt)) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - -# ifdef _LIBC - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - unsigned int in_collseq = 0; - const int32_t *table, *indirect; - const unsigned char *weights, *extra; - const char *collseqwc; - int32_t idx; - /* This #include defines a local function! */ -# include - - /* match with collating_symbol? */ - if (cset->ncoll_syms) - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - for (i = 0; i < cset->ncoll_syms; ++i) - { - const unsigned char *coll_sym = extra + cset->coll_syms[i]; - /* Compare the length of input collating element and - the length of current collating element. */ - if (*coll_sym != elem_len) - continue; - /* Compare each bytes. */ - for (j = 0; j < *coll_sym; j++) - if (pin[j] != coll_sym[1 + j]) - break; - if (j == *coll_sym) - { - /* Match if every bytes is equal. */ - match_len = j; - goto check_node_accept_bytes_match; - } - } - - if (cset->nranges) - { - if (elem_len <= char_len) - { - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - in_collseq = __collseq_table_lookup (collseqwc, wc); - } - else - in_collseq = find_collation_sequence_value (pin, elem_len); - } - /* match with range expression? */ - for (i = 0; i < cset->nranges; ++i) - if (cset->range_starts[i] <= in_collseq - && in_collseq <= cset->range_ends[i]) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - - /* match with equivalence_class? */ - if (cset->nequiv_classes) - { - const unsigned char *cp = pin; - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - idx = findidx (&cp); - if (idx > 0) - for (i = 0; i < cset->nequiv_classes; ++i) - { - int32_t equiv_class_idx = cset->equiv_classes[i]; - size_t weight_len = weights[idx]; - if (weight_len == weights[equiv_class_idx]) - { - int cnt = 0; - while (cnt <= weight_len - && (weights[equiv_class_idx + 1 + cnt] - == weights[idx + 1 + cnt])) - ++cnt; - if (cnt > weight_len) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - } - } - } - } - else -# endif /* _LIBC */ - { - /* match with range expression? */ -#if __GNUC__ >= 2 - wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; -#else - wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - cmp_buf[2] = wc; -#endif - for (i = 0; i < cset->nranges; ++i) - { - cmp_buf[0] = cset->range_starts[i]; - cmp_buf[4] = cset->range_ends[i]; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - } - check_node_accept_bytes_match: - if (!cset->non_match) - return match_len; - else - { - if (match_len > 0) - return 0; - else - return (elem_len > char_len) ? elem_len : char_len; - } - } - return 0; -} - -# ifdef _LIBC -static unsigned int -internal_function -find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) -{ - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules == 0) - { - if (mbs_len == 1) - { - /* No valid character. Match it as a single byte character. */ - const unsigned char *collseq = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - return collseq[mbs[0]]; - } - return UINT_MAX; - } - else - { - int32_t idx; - const unsigned char *extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - int32_t extrasize = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; - - for (idx = 0; idx < extrasize;) - { - int mbs_cnt, found = 0; - int32_t elem_mbs_len; - /* Skip the name of collating element name. */ - idx = idx + extra[idx] + 1; - elem_mbs_len = extra[idx++]; - if (mbs_len == elem_mbs_len) - { - for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) - if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) - break; - if (mbs_cnt == elem_mbs_len) - /* Found the entry. */ - found = 1; - } - /* Skip the byte sequence of the collating element. */ - idx += elem_mbs_len; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (extra[idx] + 1); - /* If we found the entry, return the sequence value. */ - if (found) - return *(uint32_t *) (extra + idx); - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - } - return UINT_MAX; - } -} -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ - -/* Check whether the node accepts the byte which is IDX-th - byte of the INPUT. */ - -static int -internal_function -check_node_accept (const re_match_context_t *mctx, const re_token_t *node, - int idx) -{ - unsigned char ch; - ch = re_string_byte_at (&mctx->input, idx); - switch (node->type) - { - case CHARACTER: - if (node->opr.c != ch) - return 0; - break; - - case SIMPLE_BRACKET: - if (!bitset_contain (node->opr.sbcset, ch)) - return 0; - break; - -#ifdef RE_ENABLE_I18N - case OP_UTF8_PERIOD: - if (ch >= 0x80) - return 0; - /* FALLTHROUGH */ -#endif - case OP_PERIOD: - if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) - || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) - return 0; - break; - - default: - return 0; - } - - if (node->constraint) - { - /* The node has constraints. Check whether the current context - satisfies the constraints. */ - unsigned int context = re_string_context_at (&mctx->input, idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - return 0; - } - - return 1; -} - -/* Extend the buffers, if the buffers have run out. */ - -static reg_errcode_t -internal_function -extend_buffers (re_match_context_t *mctx) -{ - reg_errcode_t ret; - re_string_t *pstr = &mctx->input; - - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - if (mctx->state_log != NULL) - { - /* And double the length of state_log. */ - /* XXX We have no indication of the size of this buffer. If this - allocation fail we have no indication that the state_log array - does not have the right size. */ - re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, - pstr->bufs_len + 1); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->state_log = new_array; - } - - /* Then reconstruct the buffers. */ - if (pstr->icase) - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - } - return REG_NOERROR; -} - - -/* Functions for matching context. */ - -/* Initialize MCTX. */ - -static reg_errcode_t -internal_function -match_ctx_init (re_match_context_t *mctx, int eflags, int n) -{ - mctx->eflags = eflags; - mctx->match_last = -1; - if (n > 0) - { - mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); - mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); - if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) - return REG_ESPACE; - } - /* Already zero-ed by the caller. - else - mctx->bkref_ents = NULL; - mctx->nbkref_ents = 0; - mctx->nsub_tops = 0; */ - mctx->abkref_ents = n; - mctx->max_mb_elem_len = 1; - mctx->asub_tops = n; - return REG_NOERROR; -} - -/* Clean the entries which depend on the current input in MCTX. - This function must be invoked when the matcher changes the start index - of the input, or changes the input string. */ - -static void -internal_function -match_ctx_clean (re_match_context_t *mctx) -{ - int st_idx; - for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) - { - int sl_idx; - re_sub_match_top_t *top = mctx->sub_tops[st_idx]; - for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) - { - re_sub_match_last_t *last = top->lasts[sl_idx]; - re_free (last->path.array); - re_free (last); - } - re_free (top->lasts); - if (top->path) - { - re_free (top->path->array); - re_free (top->path); - } - free (top); - } - - mctx->nsub_tops = 0; - mctx->nbkref_ents = 0; -} - -/* Free all the memory associated with MCTX. */ - -static void -internal_function -match_ctx_free (re_match_context_t *mctx) -{ - /* First, free all the memory associated with MCTX->SUB_TOPS. */ - match_ctx_clean (mctx); - re_free (mctx->sub_tops); - re_free (mctx->bkref_ents); -} - -/* Add a new backreference entry to MCTX. - Note that we assume that caller never call this function with duplicate - entry, and call with STR_IDX which isn't smaller than any existing entry. -*/ - -static reg_errcode_t -internal_function -match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, - int to) -{ - if (mctx->nbkref_ents >= mctx->abkref_ents) - { - struct re_backref_cache_entry* new_entry; - new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, - mctx->abkref_ents * 2); - if (BE (new_entry == NULL, 0)) - { - re_free (mctx->bkref_ents); - return REG_ESPACE; - } - mctx->bkref_ents = new_entry; - memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', - sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); - mctx->abkref_ents *= 2; - } - if (mctx->nbkref_ents > 0 - && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) - mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; - - mctx->bkref_ents[mctx->nbkref_ents].node = node; - mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; - mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; - mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; - - /* This is a cache that saves negative results of check_dst_limits_calc_pos. - If bit N is clear, means that this entry won't epsilon-transition to - an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If - it is set, check_dst_limits_calc_pos_1 will recurse and try to find one - such node. - - A backreference does not epsilon-transition unless it is empty, so set - to all zeros if FROM != TO. */ - mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map - = (from == to ? ~0 : 0); - - mctx->bkref_ents[mctx->nbkref_ents++].more = 0; - if (mctx->max_mb_elem_len < to - from) - mctx->max_mb_elem_len = to - from; - return REG_NOERROR; -} - -/* Search for the first entry which has the same str_idx, or -1 if none is - found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ - -static int -internal_function -search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) -{ - int left, right, mid, last; - last = right = mctx->nbkref_ents; - for (left = 0; left < right;) - { - mid = (left + right) / 2; - if (mctx->bkref_ents[mid].str_idx < str_idx) - left = mid + 1; - else - right = mid; - } - if (left < last && mctx->bkref_ents[left].str_idx == str_idx) - return left; - else - return -1; -} - -/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches - at STR_IDX. */ - -static reg_errcode_t -internal_function -match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) -{ -#ifdef DEBUG - assert (mctx->sub_tops != NULL); - assert (mctx->asub_tops > 0); -#endif - if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) - { - int new_asub_tops = mctx->asub_tops * 2; - re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, - re_sub_match_top_t *, - new_asub_tops); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops = new_array; - mctx->asub_tops = new_asub_tops; - } - mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); - if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops[mctx->nsub_tops]->node = node; - mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; - return REG_NOERROR; -} - -/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches - at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ - -static re_sub_match_last_t * -internal_function -match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) -{ - re_sub_match_last_t *new_entry; - if (BE (subtop->nlasts == subtop->alasts, 0)) - { - int new_alasts = 2 * subtop->alasts + 1; - re_sub_match_last_t **new_array = re_realloc (subtop->lasts, - re_sub_match_last_t *, - new_alasts); - if (BE (new_array == NULL, 0)) - return NULL; - subtop->lasts = new_array; - subtop->alasts = new_alasts; - } - new_entry = calloc (1, sizeof (re_sub_match_last_t)); - if (BE (new_entry != NULL, 1)) - { - subtop->lasts[subtop->nlasts] = new_entry; - new_entry->node = node; - new_entry->str_idx = str_idx; - ++subtop->nlasts; - } - return new_entry; -} - -static void -internal_function -sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, int last_node, int last_str_idx) -{ - sctx->sifted_states = sifted_sts; - sctx->limited_states = limited_sts; - sctx->last_node = last_node; - sctx->last_str_idx = last_str_idx; - re_node_set_init_empty (&sctx->limits); -} - - -/* Binary backward compatibility. */ -#if _LIBC -# include -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) -link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") -int re_max_failures = 2000; -# endif -#endif -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gkregex.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gkregex.h deleted file mode 100644 index 807c404ec24..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/gkregex.h +++ /dev/null @@ -1,556 +0,0 @@ -/* Definitions for data structures and routines for the regular - expression library. - Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _REGEX_H -#define _REGEX_H 1 - -#include - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* The following two types have to be signed and unsigned integer type - wide enough to hold a value of a pointer. For most ANSI compilers - ptrdiff_t and size_t should be likely OK. Still size of these two - types is 2 for Microsoft C. Ugh... */ -typedef long int s_reg_t; -typedef unsigned long int active_reg_t; - -/* The following bits are used to determine the regexp syntax we - recognize. The set/not-set meanings are chosen so that Emacs syntax - remains the value 0. The bits are given in alphabetical order, and - the definitions shifted by one from the previous bit; thus, when we - add or remove a bit, only one other definition need change. */ -typedef unsigned long int reg_syntax_t; - -/* If this bit is not set, then \ inside a bracket expression is literal. - If set, then such a \ quotes the following character. */ -#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) - -/* If this bit is not set, then + and ? are operators, and \+ and \? are - literals. - If set, then \+ and \? are operators and + and ? are literals. */ -#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) - -/* If this bit is set, then character classes are supported. They are: - [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], - [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. - If not set, then character classes are not supported. */ -#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) - -/* If this bit is set, then ^ and $ are always anchors (outside bracket - expressions, of course). - If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. - - This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because - POSIX draft 11.2 says that * etc. in leading positions is undefined. - We already implemented a previous draft which made those constructs - invalid, though, so we haven't changed the code back. */ -#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) - -/* If this bit is set, then special characters are always special - regardless of where they are in the pattern. - If this bit is not set, then special characters are special only in - some contexts; otherwise they are ordinary. Specifically, - * + ? and intervals are only special when not after the beginning, - open-group, or alternation operator. */ -#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) - -/* If this bit is set, then *, +, ?, and { cannot be first in an re or - immediately after an alternation or begin-group operator. */ -#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) - -/* If this bit is set, then . matches newline. - If not set, then it doesn't. */ -#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) - -/* If this bit is set, then . doesn't match NUL. - If not set, then it does. */ -#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) - -/* If this bit is set, nonmatching lists [^...] do not match newline. - If not set, they do. */ -#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) - -/* If this bit is set, either \{...\} or {...} defines an - interval, depending on RE_NO_BK_BRACES. - If not set, \{, \}, {, and } are literals. */ -#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) - -/* If this bit is set, +, ? and | aren't recognized as operators. - If not set, they are. */ -#define RE_LIMITED_OPS (RE_INTERVALS << 1) - -/* If this bit is set, newline is an alternation operator. - If not set, newline is literal. */ -#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) - -/* If this bit is set, then `{...}' defines an interval, and \{ and \} - are literals. - If not set, then `\{...\}' defines an interval. */ -#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) - -/* If this bit is set, (...) defines a group, and \( and \) are literals. - If not set, \(...\) defines a group, and ( and ) are literals. */ -#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) - -/* If this bit is set, then \ matches . - If not set, then \ is a back-reference. */ -#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) - -/* If this bit is set, then | is an alternation operator, and \| is literal. - If not set, then \| is an alternation operator, and | is literal. */ -#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) - -/* If this bit is set, then an ending range point collating higher - than the starting range point, as in [z-a], is invalid. - If not set, then when ending range point collates higher than the - starting range point, the range is ignored. */ -#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) - -/* If this bit is set, then an unmatched ) is ordinary. - If not set, then an unmatched ) is invalid. */ -#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) - -/* If this bit is set, succeed as soon as we match the whole pattern, - without further backtracking. */ -#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) - -/* If this bit is set, do not process the GNU regex operators. - If not set, then the GNU regex operators are recognized. */ -#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) - -/* If this bit is set, turn on internal regex debugging. - If not set, and debugging was on, turn it off. - This only works if regex.c is compiled -DDEBUG. - We define this bit always, so that all that's needed to turn on - debugging is to recompile regex.c; the calling code can always have - this bit set, and it won't affect anything in the normal case. */ -#define RE_DEBUG (RE_NO_GNU_OPS << 1) - -/* If this bit is set, a syntactically invalid interval is treated as - a string of ordinary characters. For example, the ERE 'a{1' is - treated as 'a\{1'. */ -#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) - -/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only - for ^, because it is difficult to scan the regex backwards to find - whether ^ should be special. */ -#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) - -/* If this bit is set, then \{ cannot be first in an bre or - immediately after an alternation or begin-group operator. */ -#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) - -/* If this bit is set, then no_sub will be set to 1 during - re_compile_pattern. */ -#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) - -/* This global variable defines the particular regexp syntax to use (for - some interfaces). When a regexp is compiled, the syntax used is - stored in the pattern buffer, so changing this does not affect - already-compiled regexps. */ -extern reg_syntax_t re_syntax_options; - -/* Define combinations of the above bits for the standard possibilities. - (The [[[ comments delimit what gets put into the Texinfo file, so - don't delete them!) */ -/* [[[begin syntaxes]]] */ -#define RE_SYNTAX_EMACS 0 - -#define RE_SYNTAX_AWK \ - (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ - | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ - | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) - -#define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) - -#define RE_SYNTAX_POSIX_AWK \ - (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) - -#define RE_SYNTAX_GREP \ - (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ - | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ - | RE_NEWLINE_ALT) - -#define RE_SYNTAX_EGREP \ - (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ - | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ - | RE_NO_BK_VBAR) - -#define RE_SYNTAX_POSIX_EGREP \ - (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ - | RE_INVALID_INTERVAL_ORD) - -/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ -#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC - -#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC - -/* Syntax bits common to both basic and extended POSIX regex syntax. */ -#define _RE_SYNTAX_POSIX_COMMON \ - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -#define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) - -/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this - isn't minimal, since other operators, such as \`, aren't disabled. */ -#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) - -#define RE_SYNTAX_POSIX_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ - | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) - -/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is - removed and RE_NO_BK_REFS is added. */ -#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) -/* [[[end syntaxes]]] */ - -/* Maximum number of duplicates an interval can allow. Some systems - (erroneously) define this in other header files, but we want our - value, so remove any previous define. */ -#ifdef RE_DUP_MAX -# undef RE_DUP_MAX -#endif -/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ -#define RE_DUP_MAX (0x7fff) - - -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ - -/* If this bit is set, then use extended regular expression syntax. - If not set, then use basic regular expression syntax. */ -#define REG_EXTENDED 1 - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define REG_ICASE (REG_EXTENDED << 1) - -/* If this bit is set, then anchors do not match at newline - characters in the string. - If not set, then anchors do match at newlines. */ -#define REG_NEWLINE (REG_ICASE << 1) - -/* If this bit is set, then report only success or fail in regexec. - If not set, then returns differ between not matching and errors. */ -#define REG_NOSUB (REG_NEWLINE << 1) - - -/* POSIX `eflags' bits (i.e., information for regexec). */ - -/* If this bit is set, then the beginning-of-line operator doesn't match - the beginning of the string (presumably because it's not the - beginning of a line). - If not set, then the beginning-of-line operator does match the - beginning of the string. */ -#define REG_NOTBOL 1 - -/* Like REG_NOTBOL, except for the end-of-line. */ -#define REG_NOTEOL (1 << 1) - -/* Use PMATCH[0] to delimit the start and end of the search in the - buffer. */ -#define REG_STARTEND (1 << 2) - - -/* If any error codes are removed, changed, or added, update the - `re_error_msg' table in regex.c. */ -typedef enum -{ -#ifdef _XOPEN_SOURCE - REG_ENOSYS = -1, /* This will never happen for this implementation. */ -#endif - - REG_NOERROR = 0, /* Success. */ - REG_NOMATCH, /* Didn't find a match (for regexec). */ - - /* POSIX regcomp return error codes. (In the order listed in the - standard.) */ - REG_BADPAT, /* Invalid pattern. */ - REG_ECOLLATE, /* Inalid collating element. */ - REG_ECTYPE, /* Invalid character class name. */ - REG_EESCAPE, /* Trailing backslash. */ - REG_ESUBREG, /* Invalid back reference. */ - REG_EBRACK, /* Unmatched left bracket. */ - REG_EPAREN, /* Parenthesis imbalance. */ - REG_EBRACE, /* Unmatched \{. */ - REG_BADBR, /* Invalid contents of \{\}. */ - REG_ERANGE, /* Invalid range end. */ - REG_ESPACE, /* Ran out of memory. */ - REG_BADRPT, /* No preceding re for repetition op. */ - - /* Error codes we've added. */ - REG_EEND, /* Premature end. */ - REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ - REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ -} reg_errcode_t; - -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ - -#ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE unsigned char * -#endif - -struct re_pattern_buffer -{ - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are sometimes used as - array indexes. */ - unsigned char *buffer; - - /* Number of bytes to which `buffer' points. */ - unsigned long int allocated; - - /* Number of bytes actually used in `buffer'. */ - unsigned long int used; - - /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t syntax; - - /* Pointer to a fastmap, if any, otherwise zero. re_search uses the - fastmap, if there is one, to skip over impossible starting points - for matches. */ - char *fastmap; - - /* Either a translate table to apply to all characters before - comparing them, or zero for no translation. The translation is - applied to a pattern when it is compiled and to a string when it - is matched. */ - RE_TRANSLATE_TYPE translate; - - /* Number of subexpressions found by the compiler. */ - size_t re_nsub; - - /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see whether or - not we should use the fastmap, so we don't set this absolutely - perfectly; see `re_compile_fastmap' (the `duplicate' case). */ - unsigned can_be_null : 1; - - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. - If REGS_REALLOCATE, reallocate space if necessary. - If REGS_FIXED, use what's there. */ -#define REGS_UNALLOCATED 0 -#define REGS_REALLOCATE 1 -#define REGS_FIXED 2 - unsigned regs_allocated : 2; - - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ - unsigned fastmap_accurate : 1; - - /* If set, `re_match_2' does not return information about - subexpressions. */ - unsigned no_sub : 1; - - /* If set, a beginning-of-line anchor doesn't match at the beginning - of the string. */ - unsigned not_bol : 1; - - /* Similarly for an end-of-line anchor. */ - unsigned not_eol : 1; - - /* If true, an anchor at a newline matches. */ - unsigned newline_anchor : 1; -}; - -typedef struct re_pattern_buffer regex_t; - -/* Type for byte offsets within the string. POSIX mandates this. */ -typedef int regoff_t; - - -/* This is the structure we store register match data in. See - regex.texinfo for a full description of what registers match. */ -struct re_registers -{ - unsigned num_regs; - regoff_t *start; - regoff_t *end; -}; - - -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#ifndef RE_NREGS -# define RE_NREGS 30 -#endif - - -/* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a - structure of arrays. */ -typedef struct -{ - regoff_t rm_so; /* Byte offset from string's start to substring's start. */ - regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -} regmatch_t; - -/* Declarations for routines. */ - -/* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); - -/* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ -extern const char *re_compile_pattern (const char *__pattern, size_t __length, - struct re_pattern_buffer *__buffer); - - -/* Compile a fastmap for the compiled pattern in BUFFER; used to - accelerate searches. Return 0 if successful and -2 if was an - internal error. */ -extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); - - -/* Search in the string STRING (with length LENGTH) for the pattern - compiled into BUFFER. Start searching at position START, for RANGE - characters. Return the starting position of the match, -1 for no - match, or -2 for an internal error. Also return register - information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern int re_search (struct re_pattern_buffer *__buffer, const char *__string, - int __length, int __start, int __range, - struct re_registers *__regs); - - -/* Like `re_search', but search in the concatenation of STRING1 and - STRING2. Also, stop searching at index START + STOP. */ -extern int re_search_2 (struct re_pattern_buffer *__buffer, - const char *__string1, int __length1, - const char *__string2, int __length2, int __start, - int __range, struct re_registers *__regs, int __stop); - - -/* Like `re_search', but return how many characters in STRING the regexp - in BUFFER matched, starting at position START. */ -extern int re_match (struct re_pattern_buffer *__buffer, const char *__string, - int __length, int __start, struct re_registers *__regs); - - -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ -extern int re_match_2 (struct re_pattern_buffer *__buffer, - const char *__string1, int __length1, - const char *__string2, int __length2, int __start, - struct re_registers *__regs, int __stop); - - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using BUFFER and REGS will use this memory - for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least `NUM_REGS * sizeof - (regoff_t)' bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ -extern void re_set_registers (struct re_pattern_buffer *__buffer, - struct re_registers *__regs, - unsigned int __num_regs, - regoff_t *__starts, regoff_t *__ends); - -#if defined _REGEX_RE_COMP || defined _LIBC -# ifndef _CRAY -/* 4.2 bsd compatibility. */ -extern char *re_comp (const char *); -extern int re_exec (const char *); -# endif -#endif - -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". */ -#ifndef __restrict -# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) -# if defined restrict || 199901L <= __STDC_VERSION__ -# define __restrict restrict -# else -# define __restrict -# endif -# endif -#endif -/* gcc 3.1 and up support the [restrict] syntax. */ -#ifndef __restrict_arr -# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \ - && !defined __GNUG__ -# define __restrict_arr __restrict -# else -# define __restrict_arr -# endif -#endif - -/* POSIX compatibility. */ -extern int regcomp (regex_t *__restrict __preg, - const char *__restrict __pattern, - int __cflags); - -extern int regexec (const regex_t *__restrict __preg, - const char *__restrict __string, size_t __nmatch, - regmatch_t __pmatch[__restrict_arr], - int __eflags); - -extern size_t regerror (int __errcode, const regex_t *__restrict __preg, - char *__restrict __errbuf, size_t __errbuf_size); - -extern void regfree (regex_t *__preg); - - -#ifdef __cplusplus -} -#endif /* C++ */ - -#endif /* regex.h */ diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/graph.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/graph.c deleted file mode 100644 index 209581865e4..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/graph.c +++ /dev/null @@ -1,1574 +0,0 @@ -/*! - * \file - * - * \brief Various routines with dealing with sparse graphs - * - * \author George Karypis - * \version\verbatim $Id: graph.c 13328 2012-12-31 14:57:40Z karypis $ \endverbatim - */ - -#include - -#define OMPMINOPS 50000 - -/*************************************************************************/ -/*! Allocate memory for a graph and initializes it - \returns the allocated graph. The various fields are set to NULL. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_Create() -{ - gk_graph_t *graph; - - graph = (gk_graph_t *)gk_malloc(sizeof(gk_graph_t), "gk_graph_Create: graph"); - - gk_graph_Init(graph); - - return graph; -} - - -/*************************************************************************/ -/*! Initializes the graph. - \param graph is the graph to be initialized. -*/ -/*************************************************************************/ -void gk_graph_Init(gk_graph_t *graph) -{ - memset(graph, 0, sizeof(gk_graph_t)); - graph->nvtxs = -1; -} - - -/*************************************************************************/ -/*! Frees all the memory allocated for a graph. - \param graph is the graph to be freed. -*/ -/*************************************************************************/ -void gk_graph_Free(gk_graph_t **graph) -{ - if (*graph == NULL) - return; - gk_graph_FreeContents(*graph); - gk_free((void **)graph, LTERM); -} - - -/*************************************************************************/ -/*! Frees only the memory allocated for the graph's different fields and - sets them to NULL. - \param graph is the graph whose contents will be freed. -*/ -/*************************************************************************/ -void gk_graph_FreeContents(gk_graph_t *graph) -{ - gk_free((void *)&graph->xadj, &graph->adjncy, - &graph->iadjwgt, &graph->fadjwgt, - &graph->ivwgts, &graph->fvwgts, - &graph->ivsizes, &graph->fvsizes, - &graph->vlabels, - LTERM); -} - - -/**************************************************************************/ -/*! Reads a sparse graph from the supplied file - \param filename is the file that stores the data. - \param format is the graph format. The supported values are: - GK_GRAPH_FMT_METIS. - \param isfewgts is 1 if the edge-weights should be read as floats - \param isfvwgts is 1 if the vertex-weights should be read as floats - \param isfvsizes is 1 if the vertex-sizes should be read as floats - \returns the graph that was read. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_Read(char *filename, int format, int isfewgts, - int isfvwgts, int isfvsizes) -{ - ssize_t i, k, l; - size_t nfields, nvtxs, nedges, fmt, ncon, lnlen; - int32_t ival; - float fval; - int readsizes=0, readwgts=0, readvals=0, numbering=0; - char *line=NULL, *head, *tail, fmtstr[256]; - FILE *fpin=NULL; - gk_graph_t *graph=NULL; - - - if (!gk_fexists(filename)) - gk_errexit(SIGERR, "File %s does not exist!\n", filename); - - if (format == GK_GRAPH_FMT_METIS) { - fpin = gk_fopen(filename, "r", "gk_graph_Read: fpin"); - do { - if (gk_getline(&line, &lnlen, fpin) <= 0) - gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename); - } while (line[0] == '%'); - - fmt = ncon = 0; - nfields = sscanf(line, "%zu %zu %zu %zu", &nvtxs, &nedges, &fmt, &ncon); - if (nfields < 2) - gk_errexit(SIGERR, "Header line must contain at least 2 integers (#vtxs and #edges).\n"); - - nedges *= 2; - - if (fmt > 111) - gk_errexit(SIGERR, "Cannot read this type of file format [fmt=%zu]!\n", fmt); - - sprintf(fmtstr, "%03zu", fmt%1000); - readsizes = (fmtstr[0] == '1'); - readwgts = (fmtstr[1] == '1'); - readvals = (fmtstr[2] == '1'); - numbering = 1; - ncon = (ncon == 0 ? 1 : ncon); - } - else { - gk_errexit(SIGERR, "Unrecognized format: %d\n", format); - } - - graph = gk_graph_Create(); - - graph->nvtxs = nvtxs; - - graph->xadj = gk_zmalloc(nvtxs+1, "gk_graph_Read: xadj"); - graph->adjncy = gk_i32malloc(nedges, "gk_graph_Read: adjncy"); - if (readvals) { - if (isfewgts) - graph->fadjwgt = gk_fmalloc(nedges, "gk_graph_Read: fadjwgt"); - else - graph->iadjwgt = gk_i32malloc(nedges, "gk_graph_Read: iadjwgt"); - } - - if (readsizes) { - if (isfvsizes) - graph->fvsizes = gk_fmalloc(nvtxs, "gk_graph_Read: fvsizes"); - else - graph->ivsizes = gk_i32malloc(nvtxs, "gk_graph_Read: ivsizes"); - } - - if (readwgts) { - if (isfvwgts) - graph->fvwgts = gk_fmalloc(nvtxs*ncon, "gk_graph_Read: fvwgts"); - else - graph->ivwgts = gk_i32malloc(nvtxs*ncon, "gk_graph_Read: ivwgts"); - } - - - /*---------------------------------------------------------------------- - * Read the sparse graph file - *---------------------------------------------------------------------*/ - numbering = (numbering ? - 1 : 0); - for (graph->xadj[0]=0, k=0, i=0; ifvsizes[i] = (float)strtod(head, &tail); -#else - graph->fvsizes[i] = strtof(head, &tail); -#endif - if (tail == head) - gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1); - if (graph->fvsizes[i] < 0) - gk_errexit(SIGERR, "The size for vertex %zd must be >= 0\n", i+1); - } - else { - graph->ivsizes[i] = strtol(head, &tail, 0); - if (tail == head) - gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1); - if (graph->ivsizes[i] < 0) - gk_errexit(SIGERR, "The size for vertex %zd must be >= 0\n", i+1); - } - head = tail; - } - - /* Read vertex weights */ - if (readwgts) { - for (l=0; lfvwgts[i*ncon+l] = (float)strtod(head, &tail); -#else - graph->fvwgts[i*ncon+l] = strtof(head, &tail); -#endif - if (tail == head) - gk_errexit(SIGERR, "The line for vertex %zd does not have enough weights " - "for the %d constraints.\n", i+1, ncon); - if (graph->fvwgts[i*ncon+l] < 0) - gk_errexit(SIGERR, "The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l); - } - else { - graph->ivwgts[i*ncon+l] = strtol(head, &tail, 0); - if (tail == head) - gk_errexit(SIGERR, "The line for vertex %zd does not have enough weights " - "for the %d constraints.\n", i+1, ncon); - if (graph->ivwgts[i*ncon+l] < 0) - gk_errexit(SIGERR, "The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l); - } - head = tail; - } - } - - - /* Read the rest of the row */ - while (1) { - ival = (int)strtol(head, &tail, 0); - if (tail == head) - break; - head = tail; - - if ((graph->adjncy[k] = ival + numbering) < 0) - gk_errexit(SIGERR, "Error: Invalid column number %d at row %zd.\n", ival, i); - - if (readvals) { - if (isfewgts) { -#ifdef __MSC__ - fval = (float)strtod(head, &tail); -#else - fval = strtof(head, &tail); -#endif - if (tail == head) - gk_errexit(SIGERR, "Value could not be found for edge! Vertex:%zd, NNZ:%zd\n", i, k); - - graph->fadjwgt[k] = fval; - } - else { - ival = strtol(head, &tail, 0); - if (tail == head) - gk_errexit(SIGERR, "Value could not be found for edge! Vertex:%zd, NNZ:%zd\n", i, k); - - graph->iadjwgt[k] = ival; - } - head = tail; - } - k++; - } - graph->xadj[i+1] = k; - } - - if (k != nedges) - gk_errexit(SIGERR, "gk_graph_Read: Something wrong with the number of edges in " - "the input file. nedges=%zd, Actualnedges=%zd.\n", nedges, k); - - gk_fclose(fpin); - - gk_free((void **)&line, LTERM); - - return graph; -} - - -/**************************************************************************/ -/*! Writes a graph into a file. - \param graph is the graph to be written, - \param filename is the name of the output file. - \param format is one of GK_GRAPH_FMT_METIS specifying - the format of the output file. -*/ -/**************************************************************************/ -void gk_graph_Write(gk_graph_t *graph, char *filename, int format) -{ - ssize_t i, j; - int hasvwgts, hasvsizes, hasewgts; - FILE *fpout; - - if (format != GK_GRAPH_FMT_METIS) - gk_errexit(SIGERR, "Unknown file format. %d\n", format); - - if (filename) - fpout = gk_fopen(filename, "w", "gk_graph_Write: fpout"); - else - fpout = stdout; - - - hasewgts = (graph->iadjwgt || graph->fadjwgt); - hasvwgts = (graph->ivwgts || graph->fvwgts); - hasvsizes = (graph->ivsizes || graph->fvsizes); - - /* write the header line */ - fprintf(fpout, "%d %zd", graph->nvtxs, graph->xadj[graph->nvtxs]/2); - if (hasvwgts || hasvsizes || hasewgts) - fprintf(fpout, " %d%d%d", hasvsizes, hasvwgts, hasewgts); - fprintf(fpout, "\n"); - - - for (i=0; invtxs; i++) { - if (hasvsizes) { - if (graph->ivsizes) - fprintf(fpout, " %d", graph->ivsizes[i]); - else - fprintf(fpout, " %f", graph->fvsizes[i]); - } - - if (hasvwgts) { - if (graph->ivwgts) - fprintf(fpout, " %d", graph->ivwgts[i]); - else - fprintf(fpout, " %f", graph->fvwgts[i]); - } - - for (j=graph->xadj[i]; jxadj[i+1]; j++) { - fprintf(fpout, " %d", graph->adjncy[j]+1); - if (hasewgts) { - if (graph->iadjwgt) - fprintf(fpout, " %d", graph->iadjwgt[j]); - else - fprintf(fpout, " %f", graph->fadjwgt[j]); - } - } - fprintf(fpout, "\n"); - } - if (filename) - gk_fclose(fpout); -} - - -/*************************************************************************/ -/*! Returns a copy of a graph. - \param graph is the graph to be duplicated. - \returns the newly created copy of the graph. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_Dup(gk_graph_t *graph) -{ - gk_graph_t *ngraph; - - ngraph = gk_graph_Create(); - - ngraph->nvtxs = graph->nvtxs; - - /* copy the adjacency structure */ - if (graph->xadj) - ngraph->xadj = gk_zcopy(graph->nvtxs+1, graph->xadj, - gk_zmalloc(graph->nvtxs+1, "gk_graph_Dup: xadj")); - if (graph->ivwgts) - ngraph->ivwgts = gk_i32copy(graph->nvtxs, graph->ivwgts, - gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivwgts")); - if (graph->ivsizes) - ngraph->ivsizes = gk_i32copy(graph->nvtxs, graph->ivsizes, - gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivsizes")); - if (graph->vlabels) - ngraph->vlabels = gk_i32copy(graph->nvtxs, graph->vlabels, - gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivlabels")); - if (graph->fvwgts) - ngraph->fvwgts = gk_fcopy(graph->nvtxs, graph->fvwgts, - gk_fmalloc(graph->nvtxs, "gk_graph_Dup: fvwgts")); - if (graph->fvsizes) - ngraph->fvsizes = gk_fcopy(graph->nvtxs, graph->fvsizes, - gk_fmalloc(graph->nvtxs, "gk_graph_Dup: fvsizes")); - - - if (graph->adjncy) - ngraph->adjncy = gk_i32copy(graph->xadj[graph->nvtxs], graph->adjncy, - gk_i32malloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: adjncy")); - if (graph->iadjwgt) - ngraph->iadjwgt = gk_i32copy(graph->xadj[graph->nvtxs], graph->iadjwgt, - gk_i32malloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: iadjwgt")); - if (graph->fadjwgt) - ngraph->fadjwgt = gk_fcopy(graph->xadj[graph->nvtxs], graph->fadjwgt, - gk_fmalloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: fadjwgt")); - - return ngraph; -} - - -/*************************************************************************/ -/*! Returns a subgraph containing a set of consecutive vertices. - \param graph is the original graph. - \param vstart is the starting vertex. - \param nvtxs is the number of vertices from vstart to extract. - \returns the newly created subgraph. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_ExtractSubgraph(gk_graph_t *graph, int vstart, int nvtxs) -{ - ssize_t i; - gk_graph_t *ngraph; - - if (vstart+nvtxs > graph->nvtxs) - return NULL; - - ngraph = gk_graph_Create(); - - ngraph->nvtxs = nvtxs; - - /* copy the adjancy structure */ - if (graph->xadj) - ngraph->xadj = gk_zcopy(nvtxs+1, graph->xadj+vstart, - gk_zmalloc(nvtxs+1, "gk_graph_ExtractSubgraph: xadj")); - for (i=nvtxs; i>=0; i--) - ngraph->xadj[i] -= ngraph->xadj[0]; - ASSERT(ngraph->xadj[0] == 0); - - if (graph->ivwgts) - ngraph->ivwgts = gk_i32copy(nvtxs, graph->ivwgts+vstart, - gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: ivwgts")); - if (graph->ivsizes) - ngraph->ivsizes = gk_i32copy(nvtxs, graph->ivsizes+vstart, - gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: ivsizes")); - if (graph->vlabels) - ngraph->vlabels = gk_i32copy(nvtxs, graph->vlabels+vstart, - gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: vlabels")); - - if (graph->fvwgts) - ngraph->fvwgts = gk_fcopy(nvtxs, graph->fvwgts+vstart, - gk_fmalloc(nvtxs, "gk_graph_ExtractSubgraph: fvwgts")); - if (graph->fvsizes) - ngraph->fvsizes = gk_fcopy(nvtxs, graph->fvsizes+vstart, - gk_fmalloc(nvtxs, "gk_graph_ExtractSubgraph: fvsizes")); - - - ASSERT(ngraph->xadj[nvtxs] == graph->xadj[vstart+nvtxs]-graph->xadj[vstart]); - if (graph->adjncy) - ngraph->adjncy = gk_i32copy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], - graph->adjncy+graph->xadj[vstart], - gk_i32malloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], - "gk_graph_ExtractSubgraph: adjncy")); - if (graph->iadjwgt) - ngraph->iadjwgt = gk_i32copy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], - graph->iadjwgt+graph->xadj[vstart], - gk_i32malloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], - "gk_graph_ExtractSubgraph: iadjwgt")); - if (graph->fadjwgt) - ngraph->fadjwgt = gk_fcopy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], - graph->fadjwgt+graph->xadj[vstart], - gk_fmalloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], - "gk_graph_ExtractSubgraph: fadjwgt")); - - return ngraph; -} - - -/*************************************************************************/ -/*! Returns a graph that has been reordered according to the permutation. - \param[IN] graph is the graph to be re-ordered. - \param[IN] perm is the new ordering of the graph's vertices - \param[IN] iperm is the original ordering of the re-ordered graph's vertices - \returns the newly created copy of the graph. - - \note Either perm or iperm can be NULL but not both. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_Reorder(gk_graph_t *graph, int32_t *perm, int32_t *iperm) -{ - ssize_t j, jj, *xadj; - int i, k, u, v, nvtxs; - int freeperm=0, freeiperm=0; - int32_t *adjncy; - gk_graph_t *ngraph; - - if (perm == NULL && iperm == NULL) - return NULL; - - ngraph = gk_graph_Create(); - - ngraph->nvtxs = nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* allocate memory for the different structures that are present in graph */ - if (graph->xadj) - ngraph->xadj = gk_zmalloc(nvtxs+1, "gk_graph_Reorder: xadj"); - - if (graph->ivwgts) - ngraph->ivwgts = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivwgts"); - - if (graph->ivsizes) - ngraph->ivsizes = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivsizes"); - - if (graph->vlabels) - ngraph->vlabels = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivlabels"); - - if (graph->fvwgts) - ngraph->fvwgts = gk_fmalloc(nvtxs, "gk_graph_Reorder: fvwgts"); - - if (graph->fvsizes) - ngraph->fvsizes = gk_fmalloc(nvtxs, "gk_graph_Reorder: fvsizes"); - - - if (graph->adjncy) - ngraph->adjncy = gk_i32malloc(graph->xadj[nvtxs], "gk_graph_Reorder: adjncy"); - - if (graph->iadjwgt) - ngraph->iadjwgt = gk_i32malloc(graph->xadj[nvtxs], "gk_graph_Reorder: iadjwgt"); - - if (graph->fadjwgt) - ngraph->fadjwgt = gk_fmalloc(graph->xadj[nvtxs], "gk_graph_Reorder: fadjwgt"); - - - /* create perm/iperm if not provided */ - if (perm == NULL) { - freeperm = 1; - perm = gk_i32malloc(nvtxs, "gk_graph_Reorder: perm"); - for (i=0; ixadj[0] = jj = 0; - for (v=0; vadjncy[jj] = perm[adjncy[j]]; - if (graph->iadjwgt) - ngraph->iadjwgt[jj] = graph->iadjwgt[j]; - if (graph->fadjwgt) - ngraph->fadjwgt[jj] = graph->fadjwgt[j]; - } - if (graph->ivwgts) - ngraph->ivwgts[v] = graph->ivwgts[u]; - if (graph->fvwgts) - ngraph->fvwgts[v] = graph->fvwgts[u]; - if (graph->ivsizes) - ngraph->ivsizes[v] = graph->ivsizes[u]; - if (graph->fvsizes) - ngraph->fvsizes[v] = graph->fvsizes[u]; - if (graph->vlabels) - ngraph->vlabels[v] = graph->vlabels[u]; - - ngraph->xadj[v+1] = jj; - } - - - /* free memory */ - if (freeperm) - gk_free((void **)&perm, LTERM); - if (freeiperm) - gk_free((void **)&iperm, LTERM); - - return ngraph; -} - - -/*************************************************************************/ -/*! This function finds the connected components in a graph. - - \param graph is the graph structure - \param cptr is the ptr structure of the CSR representation of the - components. The length of this vector must be graph->nvtxs+1. - \param cind is the indices structure of the CSR representation of - the components. The length of this vector must be graph->nvtxs. - - \returns the number of components that it found. - - \note The cptr and cind parameters can be NULL, in which case only the - number of connected components is returned. -*/ -/*************************************************************************/ -int gk_graph_FindComponents(gk_graph_t *graph, int32_t *cptr, int32_t *cind) -{ - ssize_t i, ii, j, jj, k, nvtxs, first, last, ntodo, ncmps; - ssize_t *xadj; - int32_t *adjncy, *pos, *todo; - int32_t mustfree_ccsr=0, mustfree_where=0; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* Deal with NULL supplied cptr/cind vectors */ - if (cptr == NULL) { - cptr = gk_i32malloc(nvtxs+1, "gk_graph_FindComponents: cptr"); - cind = gk_i32malloc(nvtxs, "gk_graph_FindComponents: cind"); - mustfree_ccsr = 1; - } - - /* The list of vertices that have not been touched yet. - The valid entries are from [0..ntodo). */ - todo = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: todo")); - - /* For a vertex that has not been visited, pos[i] is the position in the - todo list that this vertex is stored. - If a vertex has been visited, pos[i] = -1. */ - pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: pos")); - - - /* Find the connected componends */ - ncmps = -1; - ntodo = nvtxs; /* All vertices have not been visited */ - first = last = 0; /* Point to the first and last vertices that have been touched - but not explored. - These vertices are stored in cind[first]...cind[last-1]. */ - while (ntodo > 0) { - if (first == last) { /* Find another starting vertex */ - cptr[++ncmps] = first; /* Mark the end of the current CC */ - - ASSERT(pos[todo[0]] != -1); - i = todo[0]; - - cind[last++] = i; - pos[i] = -1; - } - - i = cind[first++]; /* Get the first visited but unexplored vertex */ - - /* Remove i from the todo list and put the last item in the todo - list at the position that i was so that the todo list will be - consequtive. The pos[] array is updated accordingly to keep track - the location of the vertices in the todo[] list. */ - k = pos[i]; - j = todo[k] = todo[--ntodo]; - pos[j] = k; - - for (j=xadj[i]; jnvtxs <= 0) - return; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* This array will function like pos + touched of the CC method */ - pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_ComputeBFSOrdering: pos")); - - /* This array ([C]losed[O]pen[T]odo => cot) serves three purposes. - Positions from [0...first) is the current iperm[] vector of the explored vertices; - Positions from [first...last) is the OPEN list (i.e., visited vertices); - Positions from [last...nvtxs) is the todo list. */ - cot = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_ComputeBFSOrdering: cot")); - - - /* put v at the front of the todo list */ - pos[0] = cot[0] = v; - pos[v] = cot[v] = 0; - - /* Find the connected componends induced by the partition */ - first = last = 0; - while (first < nvtxs) { - if (first == last) { /* Find another starting vertex */ - k = cot[last]; - ASSERT(pos[k] != -1); - pos[k] = -1; /* mark node as being visited */ - last++; - } - - i = cot[first++]; /* the ++ advances the explored vertices */ - for (j=xadj[i]; jnvtxs <= 0) - return; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* the degree of the vertices in the closed list */ - degrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: degrees"); - - /* the minimum vertex ID of an open vertex to the closed list */ - minIDs = gk_i32smalloc(nvtxs, nvtxs+1, "gk_graph_ComputeBestFOrdering: minIDs"); - - /* the open list */ - open = gk_i32malloc(nvtxs, "gk_graph_ComputeBestFOrdering: open"); - - /* if perm[i] >= 0, then perm[i] is the order of vertex i; - otherwise perm[i] == -1. - */ - perm = gk_i32smalloc(nvtxs, -1, "gk_graph_ComputeBestFOrdering: perm"); - - /* create the queue and put everything in it */ - queue = gk_i32pqCreate(nvtxs); - for (i=0; invtxs <= 0) - return; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* the degree of the vertices in the closed list */ - degrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: degrees"); - - /* the weighted degree of the vertices in the closed list for type==3 */ - wdegrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: wdegrees"); - - /* the sum of differences for type==4 */ - sod = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: sod"); - - /* the encountering level of a vertex type==5 */ - level = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: level"); - - /* The open+todo list of vertices. - The vertices from [0..nopen] are the open vertices. - The vertices from [nopen..ntodo) are the todo vertices. - */ - ot = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: ot")); - - /* For a vertex that has not been explored, pos[i] is the position in the ot list. */ - pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: pos")); - - /* if perm[i] >= 0, then perm[i] is the order of vertex i; otherwise perm[i] == -1. */ - perm = gk_i32smalloc(nvtxs, -1, "gk_graph_ComputeBestFOrdering: perm"); - - /* create the queue and put the starting vertex in it */ - queue = gk_i32pqCreate(nvtxs); - gk_i32pqInsert(queue, v, 1); - - /* put v at the front of the open list */ - pos[0] = ot[0] = v; - pos[v] = ot[v] = 0; - nopen = 1; - ntodo = nvtxs; - - /* start processing the nodes */ - for (i=0; i= nopen) - gk_errexit(SIGERR, "The position of v is not in open list. pos[%d]=%d is >=%d.\n", v, pos[v], nopen); - - /* remove v from the open list and re-arrange the todo part of the list */ - ot[pos[v]] = ot[nopen-1]; - pos[ot[nopen-1]] = pos[v]; - if (ntodo > nopen) { - ot[nopen-1] = ot[ntodo-1]; - pos[ot[ntodo-1]] = nopen-1; - } - nopen--; - ntodo--; - - for (j=xadj[v]; jnvtxs <= 0) - return; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - inqueue = gk_i32smalloc(nvtxs, 0, "gk_graph_SingleSourceShortestPaths: inqueue"); - - /* determine if you will be computing using int32_t or float and proceed from there */ - if (graph->iadjwgt != NULL) { - gk_i32pq_t *queue; - int32_t *adjwgt; - int32_t *sps; - - adjwgt = graph->iadjwgt; - - queue = gk_i32pqCreate(nvtxs); - gk_i32pqInsert(queue, v, 0); - inqueue[v] = 1; - - sps = gk_i32smalloc(nvtxs, -1, "gk_graph_SingleSourceShortestPaths: sps"); - sps[v] = 0; - - /* start processing the nodes */ - while ((v = gk_i32pqGetTop(queue)) != -1) { - inqueue[v] = 2; - - /* relax the adjacent edges */ - for (i=xadj[v]; ifadjwgt; - - queue = gk_fpqCreate(nvtxs); - gk_fpqInsert(queue, v, 0); - inqueue[v] = 1; - - sps = gk_fsmalloc(nvtxs, -1, "gk_graph_SingleSourceShortestPaths: sps"); - sps[v] = 0; - - /* start processing the nodes */ - while ((v = gk_fpqGetTop(queue)) != -1) { - inqueue[v] = 2; - - /* relax the adjacent edges */ - for (i=xadj[v]; irowptr) - gk_errexit(SIGERR, "Row-based view of the graphrix does not exists.\n"); - - n = graph->nrows; - ptr = graph->rowptr; - ind = graph->rowind; - val = graph->rowval; - break; - - case GK_CSR_COL: - if (!graph->colptr) - gk_errexit(SIGERR, "Column-based view of the graphrix does not exists.\n"); - - n = graph->ncols; - ptr = graph->colptr; - ind = graph->colind; - val = graph->colval; - break; - - default: - gk_errexit(SIGERR, "Invalid index type of %d.\n", what); - return; - } - - #pragma omp parallel if (n > 100) - { - ssize_t i, j, k; - gk_ikv_t *cand; - float *tval; - - #pragma omp single - for (i=0; i ptr[i] && ind[j] < ind[j-1]) - k = 1; /* an inversion */ - cand[j-ptr[i]].val = j-ptr[i]; - cand[j-ptr[i]].key = ind[j]; - tval[j-ptr[i]] = val[j]; - } - if (k) { - gk_ikvsorti(ptr[i+1]-ptr[i], cand); - for (j=ptr[i]; jnrows = nrows; - ngraph->ncols = graph->ncols; - - for (nnz=0, i=0; irowptr[rind[i]+1]-graph->rowptr[rind[i]]; - - ngraph->rowptr = gk_zmalloc(ngraph->nrows+1, "gk_graph_ExtractPartition: rowptr"); - ngraph->rowind = gk_imalloc(nnz, "gk_graph_ExtractPartition: rowind"); - ngraph->rowval = gk_fmalloc(nnz, "gk_graph_ExtractPartition: rowval"); - - ngraph->rowptr[0] = 0; - for (nnz=0, j=0, ii=0; iirowptr[i+1]-graph->rowptr[i], graph->rowind+graph->rowptr[i], ngraph->rowind+nnz); - gk_fcopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowval+graph->rowptr[i], ngraph->rowval+nnz); - nnz += graph->rowptr[i+1]-graph->rowptr[i]; - ngraph->rowptr[++j] = nnz; - } - ASSERT(j == ngraph->nrows); - - return ngraph; -} - - -/*************************************************************************/ -/*! Returns a subgraphrix corresponding to a specified partitioning of rows. - \param graph is the original graphrix. - \param part is the partitioning vector of the rows. - \param pid is the partition ID that will be extracted. - \returns the row structure of the newly created subgraphrix. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_ExtractPartition(gk_graph_t *graph, int *part, int pid) -{ - ssize_t i, j, nnz; - gk_graph_t *ngraph; - - ngraph = gk_graph_Create(); - - ngraph->nrows = 0; - ngraph->ncols = graph->ncols; - - for (nnz=0, i=0; inrows; i++) { - if (part[i] == pid) { - ngraph->nrows++; - nnz += graph->rowptr[i+1]-graph->rowptr[i]; - } - } - - ngraph->rowptr = gk_zmalloc(ngraph->nrows+1, "gk_graph_ExtractPartition: rowptr"); - ngraph->rowind = gk_imalloc(nnz, "gk_graph_ExtractPartition: rowind"); - ngraph->rowval = gk_fmalloc(nnz, "gk_graph_ExtractPartition: rowval"); - - ngraph->rowptr[0] = 0; - for (nnz=0, j=0, i=0; inrows; i++) { - if (part[i] == pid) { - gk_icopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowind+graph->rowptr[i], ngraph->rowind+nnz); - gk_fcopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowval+graph->rowptr[i], ngraph->rowval+nnz); - nnz += graph->rowptr[i+1]-graph->rowptr[i]; - ngraph->rowptr[++j] = nnz; - } - } - ASSERT(j == ngraph->nrows); - - return ngraph; -} - - -/*************************************************************************/ -/*! Splits the graphrix into multiple sub-graphrices based on the provided - color array. - \param graph is the original graphrix. - \param color is an array of size equal to the number of non-zeros - in the graphrix (row-wise structure). The graphrix is split into - as many parts as the number of colors. For meaningfull results, - the colors should be numbered consecutively starting from 0. - \returns an array of graphrices for each supplied color number. -*/ -/**************************************************************************/ -gk_graph_t **gk_graph_Split(gk_graph_t *graph, int *color) -{ - ssize_t i, j; - int nrows, ncolors; - ssize_t *rowptr; - int *rowind; - float *rowval; - gk_graph_t **sgraphs; - - nrows = graph->nrows; - rowptr = graph->rowptr; - rowind = graph->rowind; - rowval = graph->rowval; - - ncolors = gk_imax(rowptr[nrows], color)+1; - - sgraphs = (gk_graph_t **)gk_malloc(sizeof(gk_graph_t *)*ncolors, "gk_graph_Split: sgraphs"); - for (i=0; inrows = graph->nrows; - sgraphs[i]->ncols = graph->ncols; - sgraphs[i]->rowptr = gk_zsmalloc(nrows+1, 0, "gk_graph_Split: sgraphs[i]->rowptr"); - } - - for (i=0; irowptr[i]++; - } - for (i=0; irowptr); - - for (i=0; irowind = gk_imalloc(sgraphs[i]->rowptr[nrows], "gk_graph_Split: sgraphs[i]->rowind"); - sgraphs[i]->rowval = gk_fmalloc(sgraphs[i]->rowptr[nrows], "gk_graph_Split: sgraphs[i]->rowval"); - } - - for (i=0; irowind[sgraphs[color[j]]->rowptr[i]] = rowind[j]; - sgraphs[color[j]]->rowval[sgraphs[color[j]]->rowptr[i]] = rowval[j]; - sgraphs[color[j]]->rowptr[i]++; - } - } - - for (i=0; irowptr); - - return sgraphs; -} - - -/*************************************************************************/ -/*! Prunes certain rows/columns of the graphrix. The prunning takes place - by analyzing the row structure of the graphrix. The prunning takes place - by removing rows/columns but it does not affect the numbering of the - remaining rows/columns. - - \param graph the graphrix to be prunned, - \param what indicates if the rows (GK_CSR_ROW) or the columns (GK_CSR_COL) - of the graphrix will be prunned, - \param minf is the minimum number of rows (columns) that a column (row) must - be present in order to be kept, - \param maxf is the maximum number of rows (columns) that a column (row) must - be present at in order to be kept. - \returns the prunned graphrix consisting only of its row-based structure. - The input graphrix is not modified. -*/ -/**************************************************************************/ -gk_graph_t *gk_graph_Prune(gk_graph_t *graph, int what, int minf, int maxf) -{ - ssize_t i, j, nnz; - int nrows, ncols; - ssize_t *rowptr, *nrowptr; - int *rowind, *nrowind, *collen; - float *rowval, *nrowval; - gk_graph_t *ngraph; - - ngraph = gk_graph_Create(); - - nrows = ngraph->nrows = graph->nrows; - ncols = ngraph->ncols = graph->ncols; - - rowptr = graph->rowptr; - rowind = graph->rowind; - rowval = graph->rowval; - - nrowptr = ngraph->rowptr = gk_zmalloc(nrows+1, "gk_graph_Prune: nrowptr"); - nrowind = ngraph->rowind = gk_imalloc(rowptr[nrows], "gk_graph_Prune: nrowind"); - nrowval = ngraph->rowval = gk_fmalloc(rowptr[nrows], "gk_graph_Prune: nrowval"); - - - switch (what) { - case GK_CSR_COL: - collen = gk_ismalloc(ncols, 0, "gk_graph_Prune: collen"); - - for (i=0; i= minf && collen[i] <= maxf ? 1 : 0); - - nrowptr[0] = 0; - for (nnz=0, i=0; i= minf && rowptr[i+1]-rowptr[i] <= maxf) { - for (j=rowptr[i]; jrowval) { - n = graph->nrows; - ptr = graph->rowptr; - val = graph->rowval; - - #pragma omp parallel if (ptr[n] > OMPMINOPS) - { - #pragma omp for private(j,sum) schedule(static) - for (i=0; i 0 */ - } - if (sum > 0) { - if (norm == 2) - sum=1.0/sqrt(sum); - else if (norm == 1) - sum=1.0/sum; - for (j=ptr[i]; jcolval) { - n = graph->ncols; - ptr = graph->colptr; - val = graph->colval; - - #pragma omp parallel if (ptr[n] > OMPMINOPS) - { - #pragma omp for private(j,sum) schedule(static) - for (i=0; i 0) { - if (norm == 2) - sum=1.0/sqrt(sum); - else if (norm == 1) - sum=1.0/sum; - for (j=ptr[i]; j - -/****************************************************************************** -* This function creates the hash-table -*******************************************************************************/ -gk_HTable_t *HTable_Create(int nelements) -{ - gk_HTable_t *htable; - - htable = gk_malloc(sizeof(gk_HTable_t), "HTable_Create: htable"); - htable->harray = gk_ikvmalloc(nelements, "HTable_Create: harray"); - htable->nelements = nelements; - - HTable_Reset(htable); - - return htable; -} - - -/****************************************************************************** -* This function resets the data-structures associated with the hash-table -*******************************************************************************/ -void HTable_Reset(gk_HTable_t *htable) -{ - int i; - - for (i=0; inelements; i++) - htable->harray[i].key = HTABLE_EMPTY; - htable->htsize = 0; - -} - -/****************************************************************************** -* This function resizes the hash-table -*******************************************************************************/ -void HTable_Resize(gk_HTable_t *htable, int nelements) -{ - int i, old_nelements; - gk_ikv_t *old_harray; - - old_nelements = htable->nelements; - old_harray = htable->harray; - - /* prepare larger hash */ - htable->nelements = nelements; - htable->htsize = 0; - htable->harray = gk_ikvmalloc(nelements, "HTable_Resize: harray"); - for (i=0; iharray[i].key = HTABLE_EMPTY; - - /* reassign the values */ - for (i=0; ihtsize > htable->nelements/2) - HTable_Resize(htable, 2*htable->nelements); - - first = HTable_HFunction(htable->nelements, key); - - for (i=first; inelements; i++) { - if (htable->harray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) { - htable->harray[i].key = key; - htable->harray[i].val = val; - htable->htsize++; - return; - } - } - - for (i=0; iharray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) { - htable->harray[i].key = key; - htable->harray[i].val = val; - htable->htsize++; - return; - } - } - -} - - -/****************************************************************************** -* This function deletes key from the htable -*******************************************************************************/ -void HTable_Delete(gk_HTable_t *htable, int key) -{ - int i, first; - - first = HTable_HFunction(htable->nelements, key); - - for (i=first; inelements; i++) { - if (htable->harray[i].key == key) { - htable->harray[i].key = HTABLE_DELETED; - htable->htsize--; - return; - } - } - - for (i=0; iharray[i].key == key) { - htable->harray[i].key = HTABLE_DELETED; - htable->htsize--; - return; - } - } - -} - - -/****************************************************************************** -* This function returns the data associated with the key in the hastable -*******************************************************************************/ -int HTable_Search(gk_HTable_t *htable, int key) -{ - int i, first; - - first = HTable_HFunction(htable->nelements, key); - - for (i=first; inelements; i++) { - if (htable->harray[i].key == key) - return htable->harray[i].val; - else if (htable->harray[i].key == HTABLE_EMPTY) - return -1; - } - - for (i=0; iharray[i].key == key) - return htable->harray[i].val; - else if (htable->harray[i].key == HTABLE_EMPTY) - return -1; - } - - return -1; -} - - -/****************************************************************************** -* This function returns the next key/val -*******************************************************************************/ -int HTable_GetNext(gk_HTable_t *htable, int key, int *r_val, int type) -{ - int i; - static int first, last; - - if (type == HTABLE_FIRST) - first = last = HTable_HFunction(htable->nelements, key); - - if (first > last) { - for (i=first; inelements; i++) { - if (htable->harray[i].key == key) { - *r_val = htable->harray[i].val; - first = i+1; - return 1; - } - else if (htable->harray[i].key == HTABLE_EMPTY) - return -1; - } - first = 0; - } - - for (i=first; iharray[i].key == key) { - *r_val = htable->harray[i].val; - first = i+1; - return 1; - } - else if (htable->harray[i].key == HTABLE_EMPTY) - return -1; - } - - return -1; -} - - -/****************************************************************************** -* This function returns the data associated with the key in the hastable -*******************************************************************************/ -int HTable_SearchAndDelete(gk_HTable_t *htable, int key) -{ - int i, first; - - first = HTable_HFunction(htable->nelements, key); - - for (i=first; inelements; i++) { - if (htable->harray[i].key == key) { - htable->harray[i].key = HTABLE_DELETED; - htable->htsize--; - return htable->harray[i].val; - } - else if (htable->harray[i].key == HTABLE_EMPTY) - gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n"); - } - - for (i=0; iharray[i].key == key) { - htable->harray[i].key = HTABLE_DELETED; - htable->htsize--; - return htable->harray[i].val; - } - else if (htable->harray[i].key == HTABLE_EMPTY) - gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n"); - } - - return -1; - -} - - - -/****************************************************************************** -* This function destroys the data structures associated with the hash-table -*******************************************************************************/ -void HTable_Destroy(gk_HTable_t *htable) -{ - gk_free((void **)&htable->harray, &htable, LTERM); -} - - -/****************************************************************************** -* This is the hash-function. Based on multiplication -*******************************************************************************/ -int HTable_HFunction(int nelements, int key) -{ - return (int)(key%nelements); -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/io.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/io.c deleted file mode 100644 index caaedcb59c0..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/io.c +++ /dev/null @@ -1,384 +0,0 @@ -/*! -\file io.c -\brief Various file I/O functions. - -This file contains various functions that perform I/O. - -\date Started 4/10/95 -\author George -\version\verbatim $Id: io.c 12591 2012-09-01 19:03:15Z karypis $ \endverbatim -*/ - -#ifdef HAVE_GETLINE -/* Get getline to be defined. */ -#define _GNU_SOURCE -#include -#undef _GNU_SOURCE -#endif - -#include - -/************************************************************************* -* This function opens a file -**************************************************************************/ -FILE *gk_fopen(char *fname, char *mode, const char *msg) -{ - FILE *fp; - char errmsg[8192]; - - fp = fopen(fname, mode); - if (fp != NULL) - return fp; - - sprintf(errmsg,"file: %s, mode: %s, [%s]", fname, mode, msg); - perror(errmsg); - errexit("Failed on gk_fopen()\n"); - - return NULL; -} - - -/************************************************************************* -* This function closes a file -**************************************************************************/ -void gk_fclose(FILE *fp) -{ - fclose(fp); -} - - -/*************************************************************************/ -/*! This function is the GKlib implementation of glibc's getline() - function. - \returns -1 if the EOF has been reached, otherwise it returns the - number of bytes read. -*/ -/*************************************************************************/ -gk_idx_t gk_getline(char **lineptr, size_t *n, FILE *stream) -{ -#ifdef HAVE_GETLINE - return getline(lineptr, n, stream); -#else - size_t i; - int ch; - - if (feof(stream)) - return -1; - - /* Initial memory allocation if *lineptr is NULL */ - if (*lineptr == NULL || *n == 0) { - *n = 1024; - *lineptr = gk_malloc((*n)*sizeof(char), "gk_getline: lineptr"); - } - - /* get into the main loop */ - i = 0; - while ((ch = getc(stream)) != EOF) { - (*lineptr)[i++] = (char)ch; - - /* reallocate memory if reached at the end of the buffer. The +1 is for '\0' */ - if (i+1 == *n) { - *n = 2*(*n); - *lineptr = gk_realloc(*lineptr, (*n)*sizeof(char), "gk_getline: lineptr"); - } - - if (ch == '\n') - break; - } - (*lineptr)[i] = '\0'; - - return (i == 0 ? -1 : i); -#endif -} - - -/*************************************************************************/ -/*! This function reads the contents of a text file and returns it in the - form of an array of strings. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -char **gk_readfile(char *fname, gk_idx_t *r_nlines) -{ - size_t lnlen, nlines; - char *line=NULL, **lines=NULL; - FILE *fpin; - - gk_getfilestats(fname, &nlines, NULL, NULL, NULL); - if (nlines > 0) { - lines = (char **)gk_malloc(nlines*sizeof(char *), "gk_readfile: lines"); - - fpin = gk_fopen(fname, "r", "gk_readfile"); - nlines = 0; - while (gk_getline(&line, &lnlen, fpin) != -1) { - gk_strtprune(line, "\n\r"); - lines[nlines++] = gk_strdup(line); - } - gk_fclose(fpin); - } - - gk_free((void **)&line, LTERM); - - if (r_nlines != NULL) - *r_nlines = nlines; - - return lines; -} - - -/*************************************************************************/ -/*! This function reads the contents of a file and returns it in the - form of an array of int32_t. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -int32_t *gk_i32readfile(char *fname, gk_idx_t *r_nlines) -{ - size_t lnlen, nlines; - char *line=NULL; - int32_t *array=NULL; - FILE *fpin; - - gk_getfilestats(fname, &nlines, NULL, NULL, NULL); - if (nlines > 0) { - array = gk_i32malloc(nlines, "gk_i32readfile: array"); - - fpin = gk_fopen(fname, "r", "gk_readfile"); - nlines = 0; - - while (gk_getline(&line, &lnlen, fpin) != -1) { - sscanf(line, "%"SCNd32, &array[nlines++]); - } - - gk_fclose(fpin); - } - - gk_free((void **)&line, LTERM); - - if (r_nlines != NULL) - *r_nlines = nlines; - - return array; -} - - -/*************************************************************************/ -/*! This function reads the contents of a file and returns it in the - form of an array of int64_t. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -int64_t *gk_i64readfile(char *fname, gk_idx_t *r_nlines) -{ - size_t lnlen, nlines; - char *line=NULL; - int64_t *array=NULL; - FILE *fpin; - - gk_getfilestats(fname, &nlines, NULL, NULL, NULL); - if (nlines > 0) { - array = gk_i64malloc(nlines, "gk_i64readfile: array"); - - fpin = gk_fopen(fname, "r", "gk_readfile"); - nlines = 0; - - while (gk_getline(&line, &lnlen, fpin) != -1) { - sscanf(line, "%"SCNd64, &array[nlines++]); - } - - gk_fclose(fpin); - } - - gk_free((void **)&line, LTERM); - - if (r_nlines != NULL) - *r_nlines = nlines; - - return array; -} - -/*************************************************************************/ -/*! This function reads the contents of a binary file and returns it in the - form of an array of int32_t. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -int32_t *gk_i32readfilebin(char *fname, ssize_t *r_nelmnts) -{ - ssize_t fsize, nelmnts; - int32_t *array=NULL; - FILE *fpin; - - *r_nelmnts = -1; - - fsize = (ssize_t) gk_getfsize(fname); - if (fsize%sizeof(int32_t) != 0) { - gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(int32_t).\n"); - return NULL; - } - - nelmnts = fsize/sizeof(int32_t); - array = gk_i32malloc(nelmnts, "gk_i32readfilebin: array"); - - fpin = gk_fopen(fname, "rb", "gk_i32readfilebin"); - - if (fread(array, sizeof(int32_t), nelmnts, fpin) != nelmnts) { - gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); - gk_free((void **)&array, LTERM); - return NULL; - } - gk_fclose(fpin); - - *r_nelmnts = nelmnts; - - return array; -} - -/*************************************************************************/ -/*! This function reads the contents of a binary file and returns it in the - form of an array of int64_t. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -int64_t *gk_i64readfilebin(char *fname, ssize_t *r_nelmnts) -{ - ssize_t fsize, nelmnts; - int64_t *array=NULL; - FILE *fpin; - - *r_nelmnts = -1; - - fsize = (ssize_t) gk_getfsize(fname); - if (fsize%sizeof(int64_t) != 0) { - gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(int64_t).\n"); - return NULL; - } - - nelmnts = fsize/sizeof(int64_t); - array = gk_i64malloc(nelmnts, "gk_i64readfilebin: array"); - - fpin = gk_fopen(fname, "rb", "gk_i64readfilebin"); - - if (fread(array, sizeof(int64_t), nelmnts, fpin) != nelmnts) { - gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); - gk_free((void **)&array, LTERM); - return NULL; - } - gk_fclose(fpin); - - *r_nelmnts = nelmnts; - - return array; -} - -/*************************************************************************/ -/*! This function reads the contents of a binary file and returns it in the - form of an array of float. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -float *gk_freadfilebin(char *fname, ssize_t *r_nelmnts) -{ - ssize_t fsize, nelmnts; - float *array=NULL; - FILE *fpin; - - *r_nelmnts = -1; - - fsize = (ssize_t) gk_getfsize(fname); - if (fsize%sizeof(float) != 0) { - gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(float).\n"); - return NULL; - } - - nelmnts = fsize/sizeof(float); - array = gk_fmalloc(nelmnts, "gk_freadfilebin: array"); - - fpin = gk_fopen(fname, "rb", "gk_freadfilebin"); - - if (fread(array, sizeof(float), nelmnts, fpin) != nelmnts) { - gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); - gk_free((void **)&array, LTERM); - return NULL; - } - gk_fclose(fpin); - - *r_nelmnts = nelmnts; - - return array; -} - - -/*************************************************************************/ -/*! This function writes the contents of an array into a binary file. - \param fname is the name of the file - \param n the number of elements in the array. - \param a the array to be written out. -*/ -/*************************************************************************/ -size_t gk_fwritefilebin(char *fname, size_t n, float *a) -{ - size_t fsize; - FILE *fp; - - fp = gk_fopen(fname, "wb", "gk_fwritefilebin"); - - fsize = fwrite(a, sizeof(float), n, fp); - - gk_fclose(fp); - - return fsize; -} - - -/*************************************************************************/ -/*! This function reads the contents of a binary file and returns it in the - form of an array of double. - \param fname is the name of the file - \param r_nlines is the number of lines in the file. If it is NULL, - this information is not returned. -*/ -/*************************************************************************/ -double *gk_dreadfilebin(char *fname, ssize_t *r_nelmnts) -{ - ssize_t fsize, nelmnts; - double *array=NULL; - FILE *fpin; - - *r_nelmnts = -1; - - fsize = (ssize_t) gk_getfsize(fname); - if (fsize%sizeof(double) != 0) { - gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(double).\n"); - return NULL; - } - - nelmnts = fsize/sizeof(double); - array = gk_dmalloc(nelmnts, "gk_dreadfilebin: array"); - - fpin = gk_fopen(fname, "rb", "gk_dreadfilebin"); - - if (fread(array, sizeof(double), nelmnts, fpin) != nelmnts) { - gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); - gk_free((void **)&array, LTERM); - return NULL; - } - gk_fclose(fpin); - - *r_nelmnts = nelmnts; - - return array; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/itemsets.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/itemsets.c deleted file mode 100644 index 65b5af40d0f..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/itemsets.c +++ /dev/null @@ -1,210 +0,0 @@ -/*! - * \file - * \brief Frequent/Closed itemset discovery routines - * - * This file contains the code for finding frequent/closed itemests. These routines - * are implemented using a call-back mechanism to deal with the discovered itemsets. - * - * \date 6/13/2008 - * \author George Karypis - * \version\verbatim $Id: itemsets.c 11075 2011-11-11 22:31:52Z karypis $ \endverbatim - */ - -#include - -/*-------------------------------------------------------------*/ -/*! Data structures for use within this module */ -/*-------------------------------------------------------------*/ -typedef struct { - int minfreq; /* the minimum frequency of a pattern */ - int maxfreq; /* the maximum frequency of a pattern */ - int minlen; /* the minimum length of the requested pattern */ - int maxlen; /* the maximum length of the requested pattern */ - int tnitems; /* the initial range of the item space */ - - /* the call-back function */ - void (*callback)(void *stateptr, int nitems, int *itemids, int ntrans, int *transids); - void *stateptr; /* the user-supplied pointer to pass to the callback */ - - /* workspace variables */ - int *rmarker; - gk_ikv_t *cand; -} isparams_t; - - -/*-------------------------------------------------------------*/ -/*! Prototypes for this module */ -/*-------------------------------------------------------------*/ -void itemsets_find_frequent_itemsets(isparams_t *params, gk_csr_t *mat, - int preflen, int *prefix); -gk_csr_t *itemsets_project_matrix(isparams_t *param, gk_csr_t *mat, int cid); - - - -/*************************************************************************/ -/*! The entry point of the frequent itemset discovery code */ -/*************************************************************************/ -void gk_find_frequent_itemsets(int ntrans, ssize_t *tranptr, int *tranind, - int minfreq, int maxfreq, int minlen, int maxlen, - void (*process_itemset)(void *stateptr, int nitems, int *itemids, - int ntrans, int *transids), - void *stateptr) -{ - ssize_t i; - gk_csr_t *mat, *pmat; - isparams_t params; - int *pattern; - - /* Create the matrix */ - mat = gk_csr_Create(); - mat->nrows = ntrans; - mat->ncols = tranind[gk_iargmax(tranptr[ntrans], tranind)]+1; - mat->rowptr = gk_zcopy(ntrans+1, tranptr, gk_zmalloc(ntrans+1, "gk_find_frequent_itemsets: mat.rowptr")); - mat->rowind = gk_icopy(tranptr[ntrans], tranind, gk_imalloc(tranptr[ntrans], "gk_find_frequent_itemsets: mat.rowind")); - mat->colids = gk_iincset(mat->ncols, 0, gk_imalloc(mat->ncols, "gk_find_frequent_itemsets: mat.colids")); - - /* Setup the parameters */ - params.minfreq = minfreq; - params.maxfreq = (maxfreq == -1 ? mat->nrows : maxfreq); - params.minlen = minlen; - params.maxlen = (maxlen == -1 ? mat->ncols : maxlen); - params.tnitems = mat->ncols; - params.callback = process_itemset; - params.stateptr = stateptr; - params.rmarker = gk_ismalloc(mat->nrows, 0, "gk_find_frequent_itemsets: rmarker"); - params.cand = gk_ikvmalloc(mat->ncols, "gk_find_frequent_itemsets: cand"); - - /* Perform the initial projection */ - gk_csr_CreateIndex(mat, GK_CSR_COL); - pmat = itemsets_project_matrix(¶ms, mat, -1); - gk_csr_Free(&mat); - - pattern = gk_imalloc(pmat->ncols, "gk_find_frequent_itemsets: pattern"); - itemsets_find_frequent_itemsets(¶ms, pmat, 0, pattern); - - gk_csr_Free(&pmat); - gk_free((void **)&pattern, ¶ms.rmarker, ¶ms.cand, LTERM); - -} - - - -/*************************************************************************/ -/*! The recursive routine for DFS-based frequent pattern discovery */ -/*************************************************************************/ -void itemsets_find_frequent_itemsets(isparams_t *params, gk_csr_t *mat, - int preflen, int *prefix) -{ - ssize_t i; - gk_csr_t *cmat; - - /* Project each frequent column */ - for (i=0; incols; i++) { - prefix[preflen] = mat->colids[i]; - - if (preflen+1 >= params->minlen) - (*params->callback)(params->stateptr, preflen+1, prefix, - mat->colptr[i+1]-mat->colptr[i], mat->colind+mat->colptr[i]); - - if (preflen+1 < params->maxlen) { - cmat = itemsets_project_matrix(params, mat, i); - itemsets_find_frequent_itemsets(params, cmat, preflen+1, prefix); - gk_csr_Free(&cmat); - } - } - -} - - -/******************************************************************************/ -/*! This function projects a matrix w.r.t. to a particular column. - It performs the following steps: - - Determines the length of each column that is remaining - - Sorts the columns in increasing length - - Creates a column-based version of the matrix with the proper - column ordering and renamed rowids. - */ -/*******************************************************************************/ -gk_csr_t *itemsets_project_matrix(isparams_t *params, gk_csr_t *mat, int cid) -{ - ssize_t i, j, k, ii, pnnz; - int nrows, ncols, pnrows, pncols; - ssize_t *colptr, *pcolptr; - int *colind, *colids, *pcolind, *pcolids, *rmarker; - gk_csr_t *pmat; - gk_ikv_t *cand; - - nrows = mat->nrows; - ncols = mat->ncols; - colptr = mat->colptr; - colind = mat->colind; - colids = mat->colids; - - rmarker = params->rmarker; - cand = params->cand; - - - /* Allocate space for the projected matrix based on what you know thus far */ - pmat = gk_csr_Create(); - pmat->nrows = pnrows = (cid == -1 ? nrows : colptr[cid+1]-colptr[cid]); - - - /* Mark the rows that will be kept and determine the prowids */ - if (cid == -1) { /* Initial projection */ - gk_iset(nrows, 1, rmarker); - } - else { /* The other projections */ - for (i=colptr[cid]; i= params->minfreq && k <= params->maxfreq) { - cand[pncols].val = i; - cand[pncols++].key = k; - pnnz += k; - } - } - - /* Sort the columns in increasing order */ - gk_ikvsorti(pncols, cand); - - - /* Allocate space for the remaining fields of the projected matrix */ - pmat->ncols = pncols; - pmat->colids = pcolids = gk_imalloc(pncols, "itemsets_project_matrix: pcolids"); - pmat->colptr = pcolptr = gk_zmalloc(pncols+1, "itemsets_project_matrix: pcolptr"); - pmat->colind = pcolind = gk_imalloc(pnnz, "itemsets_project_matrix: pcolind"); - - - /* Populate the projected matrix */ - pcolptr[0] = 0; - for (pnnz=0, ii=0; ii - - -/*************************************************************************/ -/*! This function creates an mcore - */ -/*************************************************************************/ -gk_mcore_t *gk_mcoreCreate(size_t coresize) -{ - gk_mcore_t *mcore; - - mcore = (gk_mcore_t *)gk_malloc(sizeof(gk_mcore_t), "gk_mcoreCreate: mcore"); - memset(mcore, 0, sizeof(gk_mcore_t)); - - mcore->coresize = coresize; - mcore->corecpos = 0; - - mcore->core = (coresize == 0 ? NULL : gk_malloc(mcore->coresize, "gk_mcoreCreate: core")); - - /* allocate the memory for keeping track of malloc ops */ - mcore->nmops = 2048; - mcore->cmop = 0; - mcore->mops = (gk_mop_t *)gk_malloc(mcore->nmops*sizeof(gk_mop_t), "gk_mcoreCreate: mcore->mops"); - - return mcore; -} - - -/*************************************************************************/ -/*! This function creates an mcore. This version is used for gkmcore. - */ -/*************************************************************************/ -gk_mcore_t *gk_gkmcoreCreate() -{ - gk_mcore_t *mcore; - - if ((mcore = (gk_mcore_t *)malloc(sizeof(gk_mcore_t))) == NULL) - return NULL; - memset(mcore, 0, sizeof(gk_mcore_t)); - - /* allocate the memory for keeping track of malloc ops */ - mcore->nmops = 2048; - mcore->cmop = 0; - if ((mcore->mops = (gk_mop_t *)malloc(mcore->nmops*sizeof(gk_mop_t))) == NULL) { - free(mcore); - return NULL; - } - - return mcore; -} - - -/*************************************************************************/ -/*! This function destroys an mcore. - */ -/*************************************************************************/ -void gk_mcoreDestroy(gk_mcore_t **r_mcore, int showstats) -{ - gk_mcore_t *mcore = *r_mcore; - - if (mcore == NULL) - return; - - if (showstats) - printf("\n gk_mcore statistics\n" - " coresize: %12zu nmops: %12zu cmop: %6zu\n" - " num_callocs: %12zu num_hallocs: %12zu\n" - " size_callocs: %12zu size_hallocs: %12zu\n" - " cur_callocs: %12zu cur_hallocs: %12zu\n" - " max_callocs: %12zu max_hallocs: %12zu\n", - mcore->coresize, mcore->nmops, mcore->cmop, - mcore->num_callocs, mcore->num_hallocs, - mcore->size_callocs, mcore->size_hallocs, - mcore->cur_callocs, mcore->cur_hallocs, - mcore->max_callocs, mcore->max_hallocs); - - if (mcore->cur_callocs != 0 || mcore->cur_hallocs != 0 || mcore->cmop != 0) { - printf("***Warning: mcore memory was not fully freed when destroyed.\n" - " cur_callocs: %6zu cur_hallocs: %6zu cmop: %6zu\n", - mcore->cur_callocs, mcore->cur_hallocs, mcore->cmop); - } - - gk_free((void **)&mcore->core, &mcore->mops, &mcore, LTERM); - - *r_mcore = NULL; -} - - -/*************************************************************************/ -/*! This function destroys an mcore. This version is for gkmcore. - */ -/*************************************************************************/ -void gk_gkmcoreDestroy(gk_mcore_t **r_mcore, int showstats) -{ - gk_mcore_t *mcore = *r_mcore; - - if (mcore == NULL) - return; - - if (showstats) - printf("\n gk_mcore statistics\n" - " nmops: %12zu cmop: %6zu\n" - " num_hallocs: %12zu\n" - " size_hallocs: %12zu\n" - " cur_hallocs: %12zu\n" - " max_hallocs: %12zu\n", - mcore->nmops, mcore->cmop, - mcore->num_hallocs, - mcore->size_hallocs, - mcore->cur_hallocs, - mcore->max_hallocs); - - if (mcore->cur_hallocs != 0 || mcore->cmop != 0) { - printf("***Warning: mcore memory was not fully freed when destroyed.\n" - " cur_hallocs: %6zu cmop: %6zu\n", - mcore->cur_hallocs, mcore->cmop); - } - - free(mcore->mops); - free(mcore); - - *r_mcore = NULL; -} - - -/*************************************************************************/ -/*! This function allocate space from the core/heap - */ -/*************************************************************************/ -void *gk_mcoreMalloc(gk_mcore_t *mcore, size_t nbytes) -{ - void *ptr; - - /* pad to make pointers 8-byte aligned */ - nbytes += (nbytes%8 == 0 ? 0 : 8 - nbytes%8); - - if (mcore->corecpos + nbytes < mcore->coresize) { - /* service this request from the core */ - ptr = ((char *)mcore->core)+mcore->corecpos; - mcore->corecpos += nbytes; - - gk_mcoreAdd(mcore, GK_MOPT_CORE, nbytes, ptr); - } - else { - /* service this request from the heap */ - ptr = gk_malloc(nbytes, "gk_mcoremalloc: ptr"); - - gk_mcoreAdd(mcore, GK_MOPT_HEAP, nbytes, ptr); - } - - /* - printf("MCMALLOC: %zu %d %8zu\n", mcore->cmop-1, - mcore->mops[mcore->cmop-1].type, mcore->mops[mcore->cmop-1].nbytes); - */ - - return ptr; -} - - -/*************************************************************************/ -/*! This function sets a marker in the stack of malloc ops to be used - subsequently for freeing purposes - */ -/*************************************************************************/ -void gk_mcorePush(gk_mcore_t *mcore) -{ - gk_mcoreAdd(mcore, GK_MOPT_MARK, 0, NULL); - /* printf("MCPPUSH: %zu\n", mcore->cmop-1); */ -} - - -/*************************************************************************/ -/*! This function sets a marker in the stack of malloc ops to be used - subsequently for freeing purposes. This is the gkmcore version. - */ -/*************************************************************************/ -void gk_gkmcorePush(gk_mcore_t *mcore) -{ - gk_gkmcoreAdd(mcore, GK_MOPT_MARK, 0, NULL); - /* printf("MCPPUSH: %zu\n", mcore->cmop-1); */ -} - - -/*************************************************************************/ -/*! This function frees all mops since the last push - */ -/*************************************************************************/ -void gk_mcorePop(gk_mcore_t *mcore) -{ - while (mcore->cmop > 0) { - mcore->cmop--; - switch (mcore->mops[mcore->cmop].type) { - case GK_MOPT_MARK: /* push marker */ - goto DONE; - break; - - case GK_MOPT_CORE: /* core free */ - if (mcore->corecpos < mcore->mops[mcore->cmop].nbytes) - errexit("Internal Error: wspace's core is about to be over-freed [%zu, %zu, %zd]\n", - mcore->coresize, mcore->corecpos, mcore->mops[mcore->cmop].nbytes); - - mcore->corecpos -= mcore->mops[mcore->cmop].nbytes; - mcore->cur_callocs -= mcore->mops[mcore->cmop].nbytes; - break; - - case GK_MOPT_HEAP: /* heap free */ - gk_free((void **)&mcore->mops[mcore->cmop].ptr, LTERM); - mcore->cur_hallocs -= mcore->mops[mcore->cmop].nbytes; - break; - - default: - gk_errexit(SIGMEM, "Unknown mop type of %d\n", mcore->mops[mcore->cmop].type); - } - } - -DONE: - ; - /*printf("MCPPOP: %zu\n", mcore->cmop); */ -} - - -/*************************************************************************/ -/*! This function frees all mops since the last push. This version is - for poping the gkmcore and it uses free instead of gk_free. - */ -/*************************************************************************/ -void gk_gkmcorePop(gk_mcore_t *mcore) -{ - while (mcore->cmop > 0) { - mcore->cmop--; - switch (mcore->mops[mcore->cmop].type) { - case GK_MOPT_MARK: /* push marker */ - goto DONE; - break; - - case GK_MOPT_HEAP: /* heap free */ - free(mcore->mops[mcore->cmop].ptr); - mcore->cur_hallocs -= mcore->mops[mcore->cmop].nbytes; - break; - - default: - gk_errexit(SIGMEM, "Unknown mop type of %d\n", mcore->mops[mcore->cmop].type); - } - } - -DONE: - ; -} - - -/*************************************************************************/ -/*! Adds a memory allocation at the end of the list. - */ -/*************************************************************************/ -void gk_mcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr) -{ - if (mcore->cmop == mcore->nmops) { - mcore->nmops *= 2; - mcore->mops = realloc(mcore->mops, mcore->nmops*sizeof(gk_mop_t)); - if (mcore->mops == NULL) - gk_errexit(SIGMEM, "***Memory allocation for gkmcore failed.\n"); - } - - mcore->mops[mcore->cmop].type = type; - mcore->mops[mcore->cmop].nbytes = nbytes; - mcore->mops[mcore->cmop].ptr = ptr; - mcore->cmop++; - - switch (type) { - case GK_MOPT_MARK: - break; - - case GK_MOPT_CORE: - mcore->num_callocs++; - mcore->size_callocs += nbytes; - mcore->cur_callocs += nbytes; - if (mcore->max_callocs < mcore->cur_callocs) - mcore->max_callocs = mcore->cur_callocs; - break; - - case GK_MOPT_HEAP: - mcore->num_hallocs++; - mcore->size_hallocs += nbytes; - mcore->cur_hallocs += nbytes; - if (mcore->max_hallocs < mcore->cur_hallocs) - mcore->max_hallocs = mcore->cur_hallocs; - break; - default: - gk_errexit(SIGMEM, "Incorrect mcore type operation.\n"); - } -} - - -/*************************************************************************/ -/*! Adds a memory allocation at the end of the list. This is the gkmcore - version. - */ -/*************************************************************************/ -void gk_gkmcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr) -{ - if (mcore->cmop == mcore->nmops) { - mcore->nmops *= 2; - mcore->mops = realloc(mcore->mops, mcore->nmops*sizeof(gk_mop_t)); - if (mcore->mops == NULL) - gk_errexit(SIGMEM, "***Memory allocation for gkmcore failed.\n"); - } - - mcore->mops[mcore->cmop].type = type; - mcore->mops[mcore->cmop].nbytes = nbytes; - mcore->mops[mcore->cmop].ptr = ptr; - mcore->cmop++; - - switch (type) { - case GK_MOPT_MARK: - break; - - case GK_MOPT_HEAP: - mcore->num_hallocs++; - mcore->size_hallocs += nbytes; - mcore->cur_hallocs += nbytes; - if (mcore->max_hallocs < mcore->cur_hallocs) - mcore->max_hallocs = mcore->cur_hallocs; - break; - default: - gk_errexit(SIGMEM, "Incorrect mcore type operation.\n"); - } -} - - -/*************************************************************************/ -/*! This function deletes the mop associated with the supplied pointer. - The mop has to be a heap allocation, otherwise it fails violently. - */ -/*************************************************************************/ -void gk_mcoreDel(gk_mcore_t *mcore, void *ptr) -{ - int i; - - for (i=mcore->cmop-1; i>=0; i--) { - if (mcore->mops[i].type == GK_MOPT_MARK) - gk_errexit(SIGMEM, "Could not find pointer %p in mcore\n", ptr); - - if (mcore->mops[i].ptr == ptr) { - if (mcore->mops[i].type != GK_MOPT_HEAP) - gk_errexit(SIGMEM, "Trying to delete a non-HEAP mop.\n"); - - mcore->cur_hallocs -= mcore->mops[i].nbytes; - mcore->mops[i] = mcore->mops[--mcore->cmop]; - return; - } - } - - gk_errexit(SIGMEM, "mcoreDel should never have been here!\n"); -} - - -/*************************************************************************/ -/*! This function deletes the mop associated with the supplied pointer. - The mop has to be a heap allocation, otherwise it fails violently. - This is the gkmcore version. - */ -/*************************************************************************/ -void gk_gkmcoreDel(gk_mcore_t *mcore, void *ptr) -{ - int i; - - for (i=mcore->cmop-1; i>=0; i--) { - if (mcore->mops[i].type == GK_MOPT_MARK) - gk_errexit(SIGMEM, "Could not find pointer %p in mcore\n", ptr); - - if (mcore->mops[i].ptr == ptr) { - if (mcore->mops[i].type != GK_MOPT_HEAP) - gk_errexit(SIGMEM, "Trying to delete a non-HEAP mop.\n"); - - mcore->cur_hallocs -= mcore->mops[i].nbytes; - mcore->mops[i] = mcore->mops[--mcore->cmop]; - return; - } - } - - gk_errexit(SIGMEM, "gkmcoreDel should never have been here!\n"); -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/memory.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/memory.c deleted file mode 100644 index cdd00fa79ab..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/memory.c +++ /dev/null @@ -1,252 +0,0 @@ -/*! -\file memory.c -\brief This file contains various allocation routines - -The allocation routines included are for 1D and 2D arrays of the -most datatypes that GKlib support. Many of these routines are -defined with the help of the macros in gk_memory.h. These macros -can be used to define other memory allocation routines. - -\date Started 4/3/2007 -\author George -\version\verbatim $Id: memory.c 10783 2011-09-21 23:19:56Z karypis $ \endverbatim -*/ - - -#include - -/* This is for the global mcore that tracks all heap allocations */ -static __thread gk_mcore_t *gkmcore = NULL; - - -/*************************************************************************/ -/*! Define the set of memory allocation routines for each data type */ -/**************************************************************************/ -GK_MKALLOC(gk_c, char) -GK_MKALLOC(gk_i, int) -GK_MKALLOC(gk_i32, int32_t) -GK_MKALLOC(gk_i64, int64_t) -GK_MKALLOC(gk_z, ssize_t) -GK_MKALLOC(gk_f, float) -GK_MKALLOC(gk_d, double) -GK_MKALLOC(gk_idx, gk_idx_t) - -GK_MKALLOC(gk_ckv, gk_ckv_t) -GK_MKALLOC(gk_ikv, gk_ikv_t) -GK_MKALLOC(gk_i32kv, gk_i32kv_t) -GK_MKALLOC(gk_i64kv, gk_i64kv_t) -GK_MKALLOC(gk_zkv, gk_zkv_t) -GK_MKALLOC(gk_fkv, gk_fkv_t) -GK_MKALLOC(gk_dkv, gk_dkv_t) -GK_MKALLOC(gk_skv, gk_skv_t) -GK_MKALLOC(gk_idxkv, gk_idxkv_t) - - - - - - -/*************************************************************************/ -/*! This function allocates a two-dimensional matrix. - */ -/*************************************************************************/ -void gk_AllocMatrix(void ***r_matrix, size_t elmlen, size_t ndim1, size_t ndim2) -{ - gk_idx_t i, j; - void **matrix; - - *r_matrix = NULL; - - if ((matrix = (void **)gk_malloc(ndim1*sizeof(void *), "gk_AllocMatrix: matrix")) == NULL) - return; - - for (i=0; icmop == 0) { - gk_gkmcoreDestroy(&gkmcore, showstats); - gkmcore = NULL; - } - } -} - - -/*************************************************************************/ -/*! This function is my wrapper around malloc that provides the following - enhancements over malloc: - * It always allocates one byte of memory, even if 0 bytes are requested. - This is to ensure that checks of returned values do not lead to NULL - due to 0 bytes requested. - * It zeros-out the memory that is allocated. This is for a quick init - of the underlying datastructures. -*/ -/**************************************************************************/ -void *gk_malloc(size_t nbytes, char *msg) -{ - void *ptr=NULL; - - if (nbytes == 0) - nbytes++; /* Force mallocs to actually allocate some memory */ - - ptr = (void *)malloc(nbytes); - - if (ptr == NULL) { - fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); - fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); - gk_errexit(SIGMEM, "***Memory allocation failed for %s. Requested size: %zu bytes", - msg, nbytes); - return NULL; - } - - /* add this memory allocation */ - if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr); - - /* zero-out the allocated space */ -#ifndef NDEBUG - memset(ptr, 0, nbytes); -#endif - - return ptr; -} - - -/************************************************************************* -* This function is my wrapper around realloc -**************************************************************************/ -void *gk_realloc(void *oldptr, size_t nbytes, char *msg) -{ - void *ptr=NULL; - - if (nbytes == 0) - nbytes++; /* Force mallocs to actually allocate some memory */ - - /* remove this memory de-allocation */ - if (gkmcore != NULL && oldptr != NULL) gk_gkmcoreDel(gkmcore, oldptr); - - ptr = (void *)realloc(oldptr, nbytes); - - if (ptr == NULL) { - fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); - fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); - gk_errexit(SIGMEM, "***Memory realloc failed for %s. " "Requested size: %zu bytes", - msg, nbytes); - return NULL; - } - - /* add this memory allocation */ - if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr); - - return ptr; -} - - -/************************************************************************* -* This function is my wrapper around free, allows multiple pointers -**************************************************************************/ -void gk_free(void **ptr1,...) -{ - va_list plist; - void **ptr; - - if (*ptr1 != NULL) { - free(*ptr1); - - /* remove this memory de-allocation */ - if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr1); - } - *ptr1 = NULL; - - va_start(plist, ptr1); - while ((ptr = va_arg(plist, void **)) != LTERM) { - if (*ptr != NULL) { - free(*ptr); - - /* remove this memory de-allocation */ - if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr); - } - *ptr = NULL; - } - va_end(plist); -} - - -/************************************************************************* -* This function returns the current ammount of dynamically allocated -* memory that is used by the system -**************************************************************************/ -size_t gk_GetCurMemoryUsed() -{ - if (gkmcore == NULL) - return 0; - else - return gkmcore->cur_hallocs; -} - - -/************************************************************************* -* This function returns the maximum ammount of dynamically allocated -* memory that was used by the system -**************************************************************************/ -size_t gk_GetMaxMemoryUsed() -{ - if (gkmcore == NULL) - return 0; - else - return gkmcore->max_hallocs; -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_inttypes.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_inttypes.h deleted file mode 100644 index e26204b7f3d..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_inttypes.h +++ /dev/null @@ -1,301 +0,0 @@ -// ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. 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. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_INTTYPES_H_ // [ -#define _MSC_INTTYPES_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include "ms_stdint.h" - -// 7.8 Format conversion of integer types - -typedef struct { - intmax_t quot; - intmax_t rem; -} imaxdiv_t; - -// 7.8.1 Macros for format specifiers - -// The fprintf macros for signed integers are: -#define PRId8 "d" -#define PRIi8 "i" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIdLEAST16 "hd" -#define PRIiLEAST16 "hi" -#define PRIdFAST16 "hd" -#define PRIiFAST16 "hi" - -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIdLEAST32 "I32d" -#define PRIiLEAST32 "I32i" -#define PRIdFAST32 "I32d" -#define PRIiFAST32 "I32i" - -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIdLEAST64 "I64d" -#define PRIiLEAST64 "I64i" -#define PRIdFAST64 "I64d" -#define PRIiFAST64 "I64i" - -#define PRIdMAX "I64d" -#define PRIiMAX "I64i" - -#define PRIdPTR "Id" -#define PRIiPTR "Ii" - -// The fprintf macros for unsigned integers are: -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRIoLEAST16 "ho" -#define PRIuLEAST16 "hu" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" -#define PRIoFAST16 "ho" -#define PRIuFAST16 "hu" -#define PRIxFAST16 "hx" -#define PRIXFAST16 "hX" - -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRIoLEAST32 "I32o" -#define PRIuLEAST32 "I32u" -#define PRIxLEAST32 "I32x" -#define PRIXLEAST32 "I32X" -#define PRIoFAST32 "I32o" -#define PRIuFAST32 "I32u" -#define PRIxFAST32 "I32x" -#define PRIXFAST32 "I32X" - -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" -#define PRIoLEAST64 "I64o" -#define PRIuLEAST64 "I64u" -#define PRIxLEAST64 "I64x" -#define PRIXLEAST64 "I64X" -#define PRIoFAST64 "I64o" -#define PRIuFAST64 "I64u" -#define PRIxFAST64 "I64x" -#define PRIXFAST64 "I64X" - -#define PRIoMAX "I64o" -#define PRIuMAX "I64u" -#define PRIxMAX "I64x" -#define PRIXMAX "I64X" - -#define PRIoPTR "Io" -#define PRIuPTR "Iu" -#define PRIxPTR "Ix" -#define PRIXPTR "IX" - -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] - -// 7.8.2 Functions for greatest-width integer types - -// 7.8.2.1 The imaxabs function -#define imaxabs _abs64 - -// 7.8.2.2 The imaxdiv function - -// This is modified version of div() function from Microsoft's div.c found -// in %MSVC.NET%\crt\src\div.c -#ifdef STATIC_IMAXDIV // [ -static -#else // STATIC_IMAXDIV ][ -_inline -#endif // STATIC_IMAXDIV ] -imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t result; - - result.quot = numer / denom; - result.rem = numer % denom; - - if (numer < 0 && result.rem > 0) { - // did division wrong; must fix up - ++result.quot; - result.rem -= denom; - } - - return result; -} - -// 7.8.2.3 The strtoimax and strtoumax functions -#define strtoimax _strtoi64 -#define strtoumax _strtoui64 - -// 7.8.2.4 The wcstoimax and wcstoumax functions -#define wcstoimax _wcstoi64 -#define wcstoumax _wcstoui64 - - -#endif // _MSC_INTTYPES_H_ ] diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_stat.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_stat.h deleted file mode 100644 index a1ef6faf79d..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_stat.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MS_STAT_H_ -#define _MS_STAT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include -/* Test macros for file types. */ - -#define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) - -#define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR) -#define S_ISCHR(mode) __S_ISTYPE((mode), S_IFCHR) -#define S_ISBLK(mode) __S_ISTYPE((mode), S_IFBLK) -#define S_ISREG(mode) __S_ISTYPE((mode), S_IFREG) - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_stdint.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_stdint.h deleted file mode 100644 index 7e200dc6fc6..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/ms_stdint.h +++ /dev/null @@ -1,222 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. 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. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#if (_MSC_VER < 1300) && defined(__cplusplus) - extern "C++" { -#endif -# include -#if (_MSC_VER < 1300) && defined(__cplusplus) - } -#endif - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef int intptr_t; - typedef unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/omp.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/omp.c deleted file mode 100644 index bdd543acf40..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/omp.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * omp.c - * - * This file contains "fake" implementations of OpenMP's runtime libraries - * - */ - -#include - -#ifdef GK_NOOPENMP /* remove those for now */ -#if !defined(_OPENMP) -void omp_set_num_threads(int num_threads) { return; } -int omp_get_num_threads(void) { return 1; } -int omp_get_max_threads(void) { return 1; } -int omp_get_thread_num(void) { return 0; } -int omp_get_num_procs(void) { return 1; } -int omp_in_parallel(void) { return 0; } -void omp_set_dynamic(int num_threads) { return; } -int omp_get_dynamic(void) { return 0; } -void omp_set_nested(int nested) { return; } -int omp_get_nested(void) { return 0; } -#endif -#endif - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/pdb.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/pdb.c deleted file mode 100644 index b4d222653e7..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/pdb.c +++ /dev/null @@ -1,460 +0,0 @@ -/************************************************************************/ -/*! \file pdb.c - -\brief Functions for parsing pdb files. - -Pdb reader (parser). Loads arrays of pointers for easy backbone access. - -\date Started 10/20/06 -\author Kevin -\version $Id: pdb.c 10711 2011-08-31 22:23:04Z karypis $ -*/ -/************************************************************************/ -#include - -/************************************************************************/ -/*! \brief Converts three-letter amino acid codes to one-leter codes. - -This function takes a three letter \c * and converts it to a single \c - -\param res is the three-letter code to be converted. -\returns A \c representing the amino acid. -*/ -/************************************************************************/ -char gk_threetoone(char *res) { /* {{{ */ - /* make sure the matching works */ - res[0] = toupper(res[0]); - res[1] = toupper(res[1]); - res[2] = toupper(res[2]); - if(strcmp(res,"ALA") == 0) { - return 'A'; - } - else if(strcmp(res,"CYS") == 0) { - return 'C'; - } - else if(strcmp(res,"ASP") == 0) { - return 'D'; - } - else if(strcmp(res,"GLU") == 0) { - return 'E'; - } - else if(strcmp(res,"PHE") == 0) { - return 'F'; - } - else if(strcmp(res,"GLY") == 0) { - return 'G'; - } - else if(strcmp(res,"HIS") == 0) { - return 'H'; - } - else if(strcmp(res,"ILE") == 0) { - return 'I'; - } - else if(strcmp(res,"LYS") == 0) { - return 'K'; - } - else if(strcmp(res,"LEU") == 0) { - return 'L'; - } - else if(strcmp(res,"MET") == 0) { - return 'M'; - } - else if(strcmp(res,"ASN") == 0) { - return 'N'; - } - else if(strcmp(res,"PRO") == 0) { - return 'P'; - } - else if(strcmp(res,"GLN") == 0) { - return 'Q'; - } - else if(strcmp(res,"ARG") == 0) { - return 'R'; - } - else if(strcmp(res,"SER") == 0) { - return 'S'; - } - else if(strcmp(res,"THR") == 0) { - return 'T'; - } - else if(strcmp(res,"SCY") == 0) { - return 'U'; - } - else if(strcmp(res,"VAL") == 0) { - return 'V'; - } - else if(strcmp(res,"TRP") == 0) { - return 'W'; - } - else if(strcmp(res,"TYR") == 0) { - return 'Y'; - } - else { - return 'X'; - } -} /* }}} */ - -/************************************************************************/ -/*! \brief Frees the memory of a pdbf structure. - -This function takes a pdbf pointer and frees all the memory below it. - -\param p is the pdbf structure to be freed. -*/ -/************************************************************************/ -void gk_freepdbf(pdbf *p) { /* {{{ */ - int i; - if(p != NULL) { - gk_free((void **)&p->resSeq, LTERM); - for(i=0; inatoms; i++) { - gk_free((void **)&p->atoms[i].name, &p->atoms[i].resname, LTERM); - } - for(i=0; inresidues; i++) { - gk_free((void *)&p->threeresSeq[i], LTERM); - } - /* this may look like it's wrong, but it's just a 1-d array of pointers, and - the pointers themselves are freed above */ - gk_free((void **)&p->bbs, &p->cas, &p->atoms, &p->cm, &p->threeresSeq, LTERM); - } - gk_free((void **)&p, LTERM); -} /* }}} */ - -/************************************************************************/ -/*! \brief Reads a pdb file into a pdbf structure - -This function allocates a pdbf structure and reads the file fname into -that structure. - -\param fname is the file name to be read -\returns A filled pdbf structure. -*/ -/************************************************************************/ -pdbf *gk_readpdbfile(char *fname) { /* {{{ */ - int i=0, res=0; - char linetype[6]; - int aserial; - char aname[5] = " \0"; - char altLoc = ' '; - char rname[4] = " \0"; - char chainid = ' '; - char oldchainid = ' '; - int rserial; - int oldRserial = -37; - char icode = ' '; - char element = ' '; - double x; - double y; - double z; - double avgx; - double avgy; - double avgz; - double opcy; - double tmpt; - char line[MAXLINELEN]; - int corruption=0; - int nresatoms; - - int atoms=0, residues=0, cas=0, bbs=0, firstres=1; - pdbf *toFill = gk_malloc(sizeof(pdbf),"fillme"); - FILE *FPIN; - - FPIN = gk_fopen(fname,"r",fname); - while(fgets(line, 256, FPIN)) { - sscanf(line,"%s ",linetype); - /* It seems the only reliable parts are through temperature, so we only use these parts */ - /* if(strstr(linetype, "ATOM") != NULL || strstr(linetype, "HETATM") != NULL) { */ - if(strstr(linetype, "ATOM") != NULL) { - sscanf(line, "%6s%5d%*1c%4c%1c%3c%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf %c\n", - linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,&element); - sscanf(linetype, " %s ",linetype); - sscanf(aname, " %s ",aname); - sscanf(rname, " %s ",rname); - if(altLoc != ' ') { - corruption = corruption|CRP_ALTLOCS; - } - - if(firstres == 1) { - oldRserial = rserial; - oldchainid = chainid; - residues++; - firstres = 0; - } - if(oldRserial != rserial) { - residues++; - oldRserial = rserial; - } - if(oldchainid != chainid) { - corruption = corruption|CRP_MULTICHAIN; - } - oldchainid = chainid; - atoms++; - if(strcmp(aname,"CA") == 0) { - cas++; - } - if(strcmp(aname,"N") == 0 || strcmp(aname,"CA") == 0 || - strcmp(aname,"C") == 0 || strcmp(aname,"O") == 0) { - bbs++; - } - } - else if(strstr(linetype, "ENDMDL") != NULL || strstr(linetype, "END") != NULL || strstr(linetype, "TER") != NULL) { - break; - } - } - fclose(FPIN); - - /* printf("File has coordinates for %d atoms in %d residues\n",atoms,residues); */ - toFill->natoms = atoms; - toFill->ncas = cas; - toFill->nbbs = bbs; - toFill->nresidues = residues; - toFill->resSeq = (char *) gk_malloc (residues*sizeof(char),"residue seq"); - toFill->threeresSeq = (char **)gk_malloc (residues*sizeof(char *),"residue seq"); - toFill->atoms = (atom *) gk_malloc (atoms*sizeof(atom), "atoms"); - toFill->bbs = (atom **)gk_malloc ( bbs*sizeof(atom *),"bbs"); - toFill->cas = (atom **)gk_malloc ( cas*sizeof(atom *),"cas"); - toFill->cm = (center_of_mass *)gk_malloc(residues*sizeof(center_of_mass),"center of mass"); - res=0; firstres=1; cas=0; bbs=0; i=0; - avgx = 0.0; avgy = 0.0; avgz = 0.0; - nresatoms = 0; - - FPIN = gk_fopen(fname,"r",fname); - while(fgets(line, 256, FPIN)) { - sscanf(line,"%s ",linetype); - /* It seems the only reliable parts are through temperature, so we only use these parts */ - /* if(strstr(linetype, "ATOM") != NULL || strstr(linetype, "HETATM") != NULL) { */ - if(strstr(linetype, "ATOM") != NULL ) { - - /* to ensure our memory doesn't get corrupted by the biologists, we only read this far */ - sscanf(line, "%6s%5d%*1c%4c%1c%3c%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf %c\n", - linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,&element); - sscanf(aname, "%s",aname); - sscanf(rname, "%s",rname); - - if(firstres == 1) { - toFill->resSeq[res] = gk_threetoone(rname); - toFill->threeresSeq[res] = gk_strdup(rname); - oldRserial = rserial; - res++; - firstres = 0; - } - if(oldRserial != rserial) { - /* we're changing residues. store the center of mass from the last one & reset */ - toFill->cm[res-1].x = avgx/nresatoms; - toFill->cm[res-1].y = avgy/nresatoms; - toFill->cm[res-1].z = avgz/nresatoms; - avgx = 0.0; avgy = 0.0; avgz = 0.0; - nresatoms = 0; - toFill->cm[res-1].name = toFill->resSeq[res-1]; - - toFill->threeresSeq[res] = gk_strdup(rname); - toFill->resSeq[res] = gk_threetoone(rname); - res++; - oldRserial = rserial; - } - avgx += x; - avgy += y; - avgz += z; - nresatoms++; - - toFill->atoms[i].x = x; - toFill->atoms[i].y = y; - toFill->atoms[i].z = z; - toFill->atoms[i].opcy = opcy; - toFill->atoms[i].tmpt = tmpt; - toFill->atoms[i].element = element; - toFill->atoms[i].serial = aserial; - toFill->atoms[i].chainid = chainid; - toFill->atoms[i].altLoc = altLoc; - toFill->atoms[i].rserial = rserial; - toFill->atoms[i].icode = icode; - toFill->atoms[i].name = gk_strdup(aname); - toFill->atoms[i].resname = gk_strdup(rname); - /* Set up pointers for the backbone and c-alpha shortcuts */ - if(strcmp(aname,"CA") == 0) { - toFill->cas[cas] = &(toFill->atoms[i]); - cas++; - } - if(strcmp(aname,"N") == 0 || strcmp(aname,"CA") == 0 || strcmp(aname,"C") == 0 || strcmp(aname,"O") == 0) { - toFill->bbs[bbs] = &(toFill->atoms[i]); - bbs++; - } - i++; - } - else if(strstr(linetype, "ENDMDL") != NULL || strstr(linetype, "END") != NULL || strstr(linetype, "TER") != NULL) { - break; - } - } - /* get that last average */ - toFill->cm[res-1].x = avgx/nresatoms; - toFill->cm[res-1].y = avgy/nresatoms; - toFill->cm[res-1].z = avgz/nresatoms; - /* Begin test code */ - if(cas != residues) { - printf("Number of residues and CA coordinates differs by %d (!)\n",residues-cas); - if(cas < residues) { - corruption = corruption|CRP_MISSINGCA; - } - else if(cas > residues) { - corruption = corruption|CRP_MULTICA; - } - } - if(bbs < residues*4) { - corruption = corruption|CRP_MISSINGBB; - } - else if(bbs > residues*4) { - corruption = corruption|CRP_MULTIBB; - } - fclose(FPIN); - toFill->corruption = corruption; - /* if(corruption == 0) - printf("File was clean!\n"); */ - return(toFill); -} /* }}} */ - -/************************************************************************/ -/*! \brief Writes the sequence of residues from a pdb file. - -This function takes a pdbf structure and a filename, and writes out -the amino acid sequence according to the atomic coordinates. The output -is in fasta format. - - -\param p is the pdbf structure with the sequence of interest -\param fname is the file name to be written -*/ -/************************************************************************/ -void gk_writefastafrompdb(pdbf *pb, char *fname) { - int i; - FILE *FPOUT; - - FPOUT = gk_fopen(fname,"w",fname); - fprintf(FPOUT,"> %s\n",fname); - - for(i=0; inresidues; i++) - fprintf(FPOUT,"%c",pb->resSeq[i]); - - fprintf(FPOUT,"\n"); - fclose(FPOUT); -} - -/************************************************************************/ -/*! \brief Writes all centers of mass in pdb-format to file fname. - -This function takes a pdbf structure and writes out the calculated -mass center information to file fname as though each one was a c-alpha. - -\param p is the pdbf structure to write out -\param fname is the file name to be written -*/ -/************************************************************************/ -void gk_writecentersofmass(pdbf *p, char *fname) { - int i; - FILE *FPIN; - FPIN = gk_fopen(fname,"w",fname); - for(i=0; inresidues; i++) { - fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", - "ATOM ",i,"CA",' ',p->threeresSeq[i],' ',i,' ',p->cm[i].x,p->cm[i].y,p->cm[i].z,1.0,-37.0); - } - fclose(FPIN); -} - -/************************************************************************/ -/*! \brief Writes all atoms in p in pdb-format to file fname. - -This function takes a pdbf structure and writes out all the atom -information to file fname. - -\param p is the pdbf structure to write out -\param fname is the file name to be written -*/ -/************************************************************************/ -void gk_writefullatom(pdbf *p, char *fname) { - int i; - FILE *FPIN; - FPIN = gk_fopen(fname,"w",fname); - for(i=0; inatoms; i++) { - fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", - "ATOM ",p->atoms[i].serial,p->atoms[i].name,p->atoms[i].altLoc,p->atoms[i].resname,p->atoms[i].chainid,p->atoms[i].rserial,p->atoms[i].icode,p->atoms[i].x,p->atoms[i].y,p->atoms[i].z,p->atoms[i].opcy,p->atoms[i].tmpt); - } - fclose(FPIN); -} - -/************************************************************************/ -/*! \brief Writes out all the backbone atoms of a structure in pdb format - -This function takes a pdbf structure p and writes only the backbone atoms -to a filename fname. - -\param p is the pdb structure to write out. -\param fname is the file name to be written. -*/ -/************************************************************************/ -void gk_writebackbone(pdbf *p, char *fname) { - int i; - FILE *FPIN; - FPIN = gk_fopen(fname,"w",fname); - for(i=0; inbbs; i++) { - fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", - "ATOM ",p->bbs[i]->serial,p->bbs[i]->name,p->bbs[i]->altLoc,p->bbs[i]->resname,p->bbs[i]->chainid,p->bbs[i]->rserial,p->bbs[i]->icode,p->bbs[i]->x,p->bbs[i]->y,p->bbs[i]->z,p->bbs[i]->opcy,p->bbs[i]->tmpt); - } - fclose(FPIN); -} - -/************************************************************************/ -/*! \brief Writes out all the alpha carbon atoms of a structure - -This function takes a pdbf structure p and writes only the alpha carbon -atoms to a filename fname. - -\param p is the pdb structure to write out. -\param fname is the file name to be written. -*/ -/************************************************************************/ -void gk_writealphacarbons(pdbf *p, char *fname) { - int i; - FILE *FPIN; - FPIN = gk_fopen(fname,"w",fname); - for(i=0; incas; i++) { - fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", - "ATOM ",p->cas[i]->serial,p->cas[i]->name,p->cas[i]->altLoc,p->cas[i]->resname,p->cas[i]->chainid,p->cas[i]->rserial,p->cas[i]->icode,p->cas[i]->x,p->cas[i]->y,p->cas[i]->z,p->cas[i]->opcy,p->cas[i]->tmpt); - } - fclose(FPIN); -} - -/************************************************************************/ -/*! \brief Decodes the corruption bitswitch and prints any problems - -Due to the totally unreliable nature of the pdb format, reading a pdb -file stores a corruption bitswitch, and this function decodes that switch -and prints the result on stdout. - -\param p is the pdb structure to write out. -\param fname is the file name to be written. -*/ -/************************************************************************/ -void gk_showcorruption(pdbf *p) { - int corruption = p->corruption; - if(corruption&CRP_ALTLOCS) - printf("Multiple coordinate sets for at least one atom\n"); - if(corruption&CRP_MISSINGCA) - printf("Missing coordiantes for at least one CA atom\n"); - if(corruption&CRP_MISSINGBB) - printf("Missing coordiantes for at least one backbone atom (N,CA,C,O)\n"); - if(corruption&CRP_MULTICHAIN) - printf("File contains coordinates for multiple chains\n"); - if(corruption&CRP_MULTICA) - printf("Multiple CA atoms found for the same residue (could be alternate locators)\n"); - if(corruption&CRP_MULTICA) - printf("Multiple copies of backbone atoms found for the same residue (could be alternate locators)\n"); -} - /* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%4s%2s%2s\n", - linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,segId,element,charge); - printf(".%s.%s.%s.\n",segId,element,charge); - printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%4s%2s%2s\n", - linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",segId,element,charge); */ - - /* and we could probably get away with this using astral files, */ - /* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%6s\n", - linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,element); - printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%6s\n", - linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",element); */ diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/pqueue.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/pqueue.c deleted file mode 100644 index 94ee7513a8c..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/pqueue.c +++ /dev/null @@ -1,32 +0,0 @@ -/*! -\file pqueue.c -\brief This file implements various max-priority queues. - -The priority queues are generated using the GK_MKPQUEUE macro. - -\date Started 3/27/2007 -\author George -\version\verbatim $Id: pqueue.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - -#include - - -/*************************************************************************/ -/*! Create the various max priority queues */ -/*************************************************************************/ -#define key_gt(a, b) ((a) > (b)) -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wempty-body" -#endif -GK_MKPQUEUE(gk_ipq, gk_ipq_t, gk_ikv_t, int, gk_idx_t, gk_ikvmalloc, INT_MAX, key_gt) -GK_MKPQUEUE(gk_i32pq, gk_i32pq_t, gk_i32kv_t, int32_t, gk_idx_t, gk_i32kvmalloc, INT32_MAX, key_gt) -GK_MKPQUEUE(gk_i64pq, gk_i64pq_t, gk_i64kv_t, int64_t, gk_idx_t, gk_i64kvmalloc, INT64_MAX, key_gt) -GK_MKPQUEUE(gk_fpq, gk_fpq_t, gk_fkv_t, float, gk_idx_t, gk_fkvmalloc, FLT_MAX, key_gt) -GK_MKPQUEUE(gk_dpq, gk_dpq_t, gk_dkv_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX, key_gt) -GK_MKPQUEUE(gk_idxpq, gk_idxpq_t, gk_idxkv_t, gk_idx_t, gk_idx_t, gk_idxkvmalloc, GK_IDX_MAX, key_gt) -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif -#undef key_gt diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/random.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/random.c deleted file mode 100644 index d18e7188b16..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/random.c +++ /dev/null @@ -1,134 +0,0 @@ -/*! -\file -\brief Various routines for providing portable 32 and 64 bit random number - generators. - -\date Started 5/17/2007 -\author George -\version\verbatim $Id: random.c 11793 2012-04-04 21:03:02Z karypis $ \endverbatim -*/ - -#include - - -/*************************************************************************/ -/*! Create the various random number functions */ -/*************************************************************************/ -GK_MKRANDOM(gk_c, size_t, char) -GK_MKRANDOM(gk_i, size_t, int) -GK_MKRANDOM(gk_f, size_t, float) -GK_MKRANDOM(gk_d, size_t, double) -GK_MKRANDOM(gk_idx, size_t, gk_idx_t) -GK_MKRANDOM(gk_z, size_t, ssize_t) - - - -/*************************************************************************/ -/*! GKlib's built in random number generator for portability across - different architectures */ -/*************************************************************************/ -#ifdef USE_GKRAND -/* - A C-program for MT19937-64 (2004/9/29 version). - Coded by Takuji Nishimura and Makoto Matsumoto. - - This is a 64-bit version of Mersenne Twister pseudorandom number - generator. - - Before using, initialize the state by using init_genrand64(seed) - or init_by_array64(init_key, key_length). - - Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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. -*/ - -#define NN 312 -#define MM 156 -#define MATRIX_A 0xB5026F5AA96619E9ULL -#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ -#define LM 0x7FFFFFFFULL /* Least significant 31 bits */ - - -/* The array for the state vector */ -static uint64_t mt[NN]; -/* mti==NN+1 means mt[NN] is not initialized */ -static int mti=NN+1; -#endif /* USE_GKRAND */ - -/* initializes mt[NN] with a seed */ -void gk_randinit(uint64_t seed) -{ -#ifdef USE_GKRAND - mt[0] = seed; - for (mti=1; mti> 62)) + mti); -#else - srand((unsigned int) seed); -#endif -} - - -/* generates a random number on [0, 2^64-1]-interval */ -uint64_t gk_randint64(void) -{ -#ifdef USE_GKRAND - int i; - unsigned long long x; - static uint64_t mag01[2]={0ULL, MATRIX_A}; - - if (mti >= NN) { /* generate NN words at one time */ - /* if init_genrand64() has not been called, */ - /* a default initial seed is used */ - if (mti == NN+1) - gk_randinit(5489ULL); - - for (i=0; i>1) ^ mag01[(int)(x&1ULL)]; - } - for (; i>1) ^ mag01[(int)(x&1ULL)]; - } - x = (mt[NN-1]&UM)|(mt[0]&LM); - mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; - - mti = 0; - } - - x = mt[mti++]; - - x ^= (x >> 29) & 0x5555555555555555ULL; - x ^= (x << 17) & 0x71D67FFFEDA60000ULL; - x ^= (x << 37) & 0xFFF7EEE000000000ULL; - x ^= (x >> 43); - - return x & 0x7FFFFFFFFFFFFFFF; -#else - return (uint64_t)(((uint64_t) rand()) << 32 | ((uint64_t) rand())); -#endif -} - -/* generates a random number on [0, 2^32-1]-interval */ -uint32_t gk_randint32(void) -{ -#ifdef USE_GKRAND - return (uint32_t)(gk_randint64() & 0x7FFFFFFF); -#else - return (uint32_t)rand(); -#endif -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/rw.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/rw.c deleted file mode 100644 index 7cd4391a04a..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/rw.c +++ /dev/null @@ -1,103 +0,0 @@ -/*! - * \file - * - * \brief Various routines that perform random-walk based operations - on graphs stored as gk_csr_t matrices. - * - * \author George Karypis - * \version\verbatim $Id: rw.c 11078 2011-11-12 00:20:44Z karypis $ \endverbatim - */ - -#include - - -/*************************************************************************/ -/*! Computes the (personalized) page-rank of the vertices in a graph. - - \param mat is the matrix storing the graph. - \param lamda is the restart probability. - \param eps is the error tolerance for convergance. - \param max_niter is the maximum number of allowed iterations. - \param pr on entry stores the restart distribution of the vertices. - This allows for the computation of personalized page-rank scores - by appropriately setting that parameter. - On return, pr stores the computed page ranks. - - \returns the number of iterations that were performed. -*/ -/**************************************************************************/ -int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr) -{ - ssize_t i, j, k, iter, nrows; - double *rscale, *prold, *prnew, *prtmp; - double fromsinks, error; - ssize_t *rowptr; - int *rowind; - float *rowval; - - nrows = mat->nrows; - rowptr = mat->rowptr; - rowind = mat->rowind; - rowval = mat->rowval; - - prold = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prnew"); - prnew = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prold"); - rscale = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: rscale"); - - /* compute the scaling factors to get adjacency weights into transition - probabilities */ - for (i=0; i 0) - rscale[i] = 1.0/rscale[i]; - } - - /* the restart distribution is the initial pr scores */ - for (i=0; i error ? fabs(prnew[i]-prold[i]) : error); - - //printf("nrm1: %le maxfabserr: %le\n", gk_dsum(nrows, prnew, 1), error); - - if (error < eps) - break; - } - - /* store the computed pr scores into pr for output */ - for (i=0; i - - - - -/*********************************************************/ -/* ! \brief Initializes the gk_seq_t variable - - - - -\param A pointer to gk_seq_t itself -\returns null -*/ -/***********************************************************************/ - -void gk_seq_init(gk_seq_t *seq) -{ - - seq->len = 0; - seq->sequence = NULL; - - seq->pssm = NULL; - seq->psfm = NULL; - - seq->name = NULL; - -} - -/***********************************************************************/ -/*! \brief This function creates the localizations for the various sequences - -\param string i.e amino acids, nucleotides, sequences -\returns gk_i2cc2i_t variable -*/ -/*********************************************************************/ - -gk_i2cc2i_t *gk_i2cc2i_create_common(char *alphabet) -{ - - - int nsymbols; - gk_idx_t i; - gk_i2cc2i_t *t; - - nsymbols = strlen(alphabet); - t = gk_malloc(sizeof(gk_i2cc2i_t),"gk_i2c_create_common"); - t->n = nsymbols; - t->i2c = gk_cmalloc(256, "gk_i2c_create_common"); - t->c2i = gk_imalloc(256, "gk_i2c_create_common"); - - - gk_cset(256, -1, t->i2c); - gk_iset(256, -1, t->c2i); - - for(i=0;ii2c[i] = alphabet[i]; - t->c2i[(int)alphabet[i]] = i; - } - - return t; - -} - - -/*********************************************************************/ -/*! \brief This function reads a pssm in the format of gkmod pssm - -\param file_name is the name of the pssm file -\returns gk_seq_t -*/ -/********************************************************************/ -gk_seq_t *gk_seq_ReadGKMODPSSM(char *filename) -{ - gk_seq_t *seq; - gk_idx_t i, j, ii; - size_t ntokens, nbytes, len; - FILE *fpin; - - - gk_Tokens_t tokens; - static char *AAORDER = "ARNDCQEGHILKMFPSTWYVBZX*"; - static int PSSMWIDTH = 20; - char *header, line[MAXLINELEN]; - gk_i2cc2i_t *converter; - - header = gk_cmalloc(PSSMWIDTH, "gk_seq_ReadGKMODPSSM: header"); - - converter = gk_i2cc2i_create_common(AAORDER); - - gk_getfilestats(filename, &len, &ntokens, NULL, &nbytes); - len --; - - seq = gk_malloc(sizeof(gk_seq_t),"gk_seq_ReadGKMODPSSM"); - gk_seq_init(seq); - - seq->len = len; - seq->sequence = gk_imalloc(len, "gk_seq_ReadGKMODPSSM"); - seq->pssm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM"); - seq->psfm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM"); - - seq->nsymbols = PSSMWIDTH; - seq->name = gk_getbasename(filename); - - fpin = gk_fopen(filename,"r","gk_seq_ReadGKMODPSSM"); - - - /* Read the header line */ - if (fgets(line, MAXLINELEN-1, fpin) == NULL) - errexit("Unexpected end of file: %s\n", filename); - gk_strtoupper(line); - gk_strtokenize(line, " \t\n", &tokens); - - for (i=0; isequence[i] = converter->c2i[(int)tokens.list[1][0]]; - - for (j=0; jpssm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+j]); - seq->psfm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+PSSMWIDTH+j]); - } - - - - gk_freetokenslist(&tokens); - i++; - } - - seq->len = i; /* Reset the length if certain characters were skipped */ - - gk_free((void **)&header, LTERM); - gk_fclose(fpin); - - return seq; -} - - -/**************************************************************************/ -/*! \brief This function frees the memory allocated to the seq structure. - -\param gk_seq_t -\returns nothing -*/ -/**************************************************************************/ -void gk_seq_free(gk_seq_t *seq) -{ - gk_iFreeMatrix(&seq->pssm, seq->len, seq->nsymbols); - gk_iFreeMatrix(&seq->psfm, seq->len, seq->nsymbols); - gk_free((void **)&seq->name, &seq->sequence, LTERM); - //gk_free((void **)&seq, LTERM); - gk_free((void **) &seq, LTERM); - -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/sort.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/sort.c deleted file mode 100644 index bde30f5a59f..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/sort.c +++ /dev/null @@ -1,327 +0,0 @@ -/*! -\file sort.c -\brief This file contains GKlib's various sorting routines - -These routines are implemented using the GKSORT macro that is defined -in gk_qsort.h and is based on GNU's GLIBC qsort() implementation. - -Additional sorting routines can be created using the same way that -these routines where defined. - -\date Started 4/4/07 -\author George -\version\verbatim $Id: sort.c 10796 2011-09-23 21:33:09Z karypis $ \endverbatim -*/ - -#include - - - -/*************************************************************************/ -/*! Sorts an array of chars in increasing order */ -/*************************************************************************/ -void gk_csorti(size_t n, char *base) -{ -#define char_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(char, base, n, char_lt); -#undef char_lt -} - - -/*************************************************************************/ -/*! Sorts an array of chars in decreasing order */ -/*************************************************************************/ -void gk_csortd(size_t n, char *base) -{ -#define char_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(char, base, n, char_gt); -#undef char_gt -} - - -/*************************************************************************/ -/*! Sorts an array of integers in increasing order */ -/*************************************************************************/ -void gk_isorti(size_t n, int *base) -{ -#define int_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(int, base, n, int_lt); -#undef int_lt -} - - -/*************************************************************************/ -/*! Sorts an array of integers in decreasing order */ -/*************************************************************************/ -void gk_isortd(size_t n, int *base) -{ -#define int_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(int, base, n, int_gt); -#undef int_gt -} - - -/*************************************************************************/ -/*! Sorts an array of floats in increasing order */ -/*************************************************************************/ -void gk_fsorti(size_t n, float *base) -{ -#define float_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(float, base, n, float_lt); -#undef float_lt -} - - -/*************************************************************************/ -/*! Sorts an array of floats in decreasing order */ -/*************************************************************************/ -void gk_fsortd(size_t n, float *base) -{ -#define float_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(float, base, n, float_gt); -#undef float_gt -} - - -/*************************************************************************/ -/*! Sorts an array of doubles in increasing order */ -/*************************************************************************/ -void gk_dsorti(size_t n, double *base) -{ -#define double_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(double, base, n, double_lt); -#undef double_lt -} - - -/*************************************************************************/ -/*! Sorts an array of doubles in decreasing order */ -/*************************************************************************/ -void gk_dsortd(size_t n, double *base) -{ -#define double_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(double, base, n, double_gt); -#undef double_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_idx_t in increasing order */ -/*************************************************************************/ -void gk_idxsorti(size_t n, gk_idx_t *base) -{ -#define idx_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(gk_idx_t, base, n, idx_lt); -#undef idx_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_idx_t in decreasing order */ -/*************************************************************************/ -void gk_idxsortd(size_t n, gk_idx_t *base) -{ -#define idx_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(gk_idx_t, base, n, idx_gt); -#undef idx_gt -} - - - - -/*************************************************************************/ -/*! Sorts an array of gk_ckv_t in increasing order */ -/*************************************************************************/ -void gk_ckvsorti(size_t n, gk_ckv_t *base) -{ -#define ckey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_ckv_t, base, n, ckey_lt); -#undef ckey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_ckv_t in decreasing order */ -/*************************************************************************/ -void gk_ckvsortd(size_t n, gk_ckv_t *base) -{ -#define ckey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_ckv_t, base, n, ckey_gt); -#undef ckey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_ikv_t in increasing order */ -/*************************************************************************/ -void gk_ikvsorti(size_t n, gk_ikv_t *base) -{ -#define ikey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_ikv_t, base, n, ikey_lt); -#undef ikey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_ikv_t in decreasing order */ -/*************************************************************************/ -void gk_ikvsortd(size_t n, gk_ikv_t *base) -{ -#define ikey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_ikv_t, base, n, ikey_gt); -#undef ikey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_i32kv_t in increasing order */ -/*************************************************************************/ -void gk_i32kvsorti(size_t n, gk_i32kv_t *base) -{ -#define ikey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_i32kv_t, base, n, ikey_lt); -#undef ikey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_i32kv_t in decreasing order */ -/*************************************************************************/ -void gk_i32kvsortd(size_t n, gk_i32kv_t *base) -{ -#define ikey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_i32kv_t, base, n, ikey_gt); -#undef ikey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_i64kv_t in increasing order */ -/*************************************************************************/ -void gk_i64kvsorti(size_t n, gk_i64kv_t *base) -{ -#define ikey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_i64kv_t, base, n, ikey_lt); -#undef ikey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_i64kv_t in decreasing order */ -/*************************************************************************/ -void gk_i64kvsortd(size_t n, gk_i64kv_t *base) -{ -#define ikey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_i64kv_t, base, n, ikey_gt); -#undef ikey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_zkv_t in increasing order */ -/*************************************************************************/ -void gk_zkvsorti(size_t n, gk_zkv_t *base) -{ -#define zkey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_zkv_t, base, n, zkey_lt); -#undef zkey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_zkv_t in decreasing order */ -/*************************************************************************/ -void gk_zkvsortd(size_t n, gk_zkv_t *base) -{ -#define zkey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_zkv_t, base, n, zkey_gt); -#undef zkey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_fkv_t in increasing order */ -/*************************************************************************/ -void gk_fkvsorti(size_t n, gk_fkv_t *base) -{ -#define fkey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_fkv_t, base, n, fkey_lt); -#undef fkey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_fkv_t in decreasing order */ -/*************************************************************************/ -void gk_fkvsortd(size_t n, gk_fkv_t *base) -{ -#define fkey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_fkv_t, base, n, fkey_gt); -#undef fkey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_dkv_t in increasing order */ -/*************************************************************************/ -void gk_dkvsorti(size_t n, gk_dkv_t *base) -{ -#define dkey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_dkv_t, base, n, dkey_lt); -#undef dkey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_fkv_t in decreasing order */ -/*************************************************************************/ -void gk_dkvsortd(size_t n, gk_dkv_t *base) -{ -#define dkey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_dkv_t, base, n, dkey_gt); -#undef dkey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_skv_t in increasing order */ -/*************************************************************************/ -void gk_skvsorti(size_t n, gk_skv_t *base) -{ -#define skey_lt(a, b) (strcmp((a)->key, (b)->key) < 0) - GK_MKQSORT(gk_skv_t, base, n, skey_lt); -#undef skey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_skv_t in decreasing order */ -/*************************************************************************/ -void gk_skvsortd(size_t n, gk_skv_t *base) -{ -#define skey_gt(a, b) (strcmp((a)->key, (b)->key) > 0) - GK_MKQSORT(gk_skv_t, base, n, skey_gt); -#undef skey_gt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_idxkv_t in increasing order */ -/*************************************************************************/ -void gk_idxkvsorti(size_t n, gk_idxkv_t *base) -{ -#define idxkey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(gk_idxkv_t, base, n, idxkey_lt); -#undef idxkey_lt -} - - -/*************************************************************************/ -/*! Sorts an array of gk_idxkv_t in decreasing order */ -/*************************************************************************/ -void gk_idxkvsortd(size_t n, gk_idxkv_t *base) -{ -#define idxkey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(gk_idxkv_t, base, n, idxkey_gt); -#undef idxkey_gt -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/string.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/string.c deleted file mode 100644 index 7947c3baba7..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/string.c +++ /dev/null @@ -1,529 +0,0 @@ -/************************************************************************/ -/*! \file - -\brief Functions for manipulating strings. - -Various functions for manipulating strings. Some of these functions -provide new functionality, whereas others are drop-in replacements -of standard functions (but with enhanced functionality). - -\date Started 11/1/99 -\author George -\version $Id: string.c 10711 2011-08-31 22:23:04Z karypis $ -*/ -/************************************************************************/ - -#include - - - -/************************************************************************/ -/*! \brief Replaces certain characters in a string. - -This function takes a string and replaces all the characters in the -\c fromlist with the corresponding characters from the \c tolist. -That is, each occurence of fromlist[i] is replaced by -tolist[i]. -If the \c tolist is shorter than \c fromlist, then the corresponding -characters are deleted. The modifications on \c str are done in place. -It tries to provide a functionality similar to Perl's \b tr// function. - -\param str is the string whose characters will be replaced. -\param fromlist is the set of characters to be replaced. -\param tolist is the set of replacement characters . -\returns A pointer to \c str itself. -*/ -/************************************************************************/ -char *gk_strchr_replace(char *str, char *fromlist, char *tolist) -{ - gk_idx_t i, j, k; - size_t len, fromlen, tolen; - - len = strlen(str); - fromlen = strlen(fromlist); - tolen = strlen(tolist); - - for (i=j=0; i s// regular-expression -based substitution function. - -\param str - is the input string on which the operation will be performed. -\param pattern - is the regular expression for the pattern to be matched for substitution. -\param replacement - is the replacement string, in which the possible captured pattern substrings - are referred to as $1, $2, ..., $9. The entire matched pattern is refered - to as $0. -\param options - is a string specified options for the substitution operation. Currently the - "i" (case insensitive) and "g" (global substitution) are - supported. -\param new_str - is a reference to a pointer that will store a pointer to the newly created - string that results from the substitutions. This string is allocated via - gk_malloc() and needs to be freed using gk_free(). The string is returned - even if no substitutions were performed. -\returns - If successful, it returns 1 + the number of substitutions that were performed. - Thus, if no substitutions were performed, the returned value will be 1. - Otherwise it returns 0. In case of error, a meaningful error message is - returned in newstr, which also needs to be freed afterwards. -*/ -/************************************************************************/ -int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options, - char **new_str) -{ - gk_idx_t i; - int j, rc, flags, global, nmatches; - size_t len, rlen, nlen, offset, noffset; - regex_t re; - regmatch_t matches[10]; - - - /* Parse the options */ - flags = REG_EXTENDED; - if (strchr(options, 'i') != NULL) - flags = flags | REG_ICASE; - global = (strchr(options, 'g') != NULL ? 1 : 0); - - - /* Compile the regex */ - if ((rc = regcomp(&re, pattern, flags)) != 0) { - len = regerror(rc, &re, NULL, 0); - *new_str = gk_cmalloc(len, "gk_strstr_replace: new_str"); - regerror(rc, &re, *new_str, len); - return 0; - } - - /* Prepare the output string */ - len = strlen(str); - nlen = 2*len; - noffset = 0; - *new_str = gk_cmalloc(nlen+1, "gk_strstr_replace: new_str"); - - - /* Get into the matching-replacing loop */ - rlen = strlen(replacement); - offset = 0; - nmatches = 0; - do { - rc = regexec(&re, str+offset, 10, matches, 0); - - if (rc == REG_ESPACE) { - gk_free((void **)new_str, LTERM); - *new_str = gk_strdup("regexec ran out of memory."); - regfree(&re); - return 0; - } - else if (rc == REG_NOMATCH) { - if (nlen-noffset < len-offset) { - nlen += (len-offset) - (nlen-noffset); - *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); - } - strcpy(*new_str+noffset, str+offset); - noffset += (len-offset); - break; - } - else { /* A match was found! */ - nmatches++; - - /* Copy the left unmatched portion of the string */ - if (matches[0].rm_so > 0) { - if (nlen-noffset < matches[0].rm_so) { - nlen += matches[0].rm_so - (nlen-noffset); - *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); - } - strncpy(*new_str+noffset, str+offset, matches[0].rm_so); - noffset += matches[0].rm_so; - } - - /* Go and append the replacement string */ - for (i=0; i 9) { - gk_free((void **)new_str, LTERM); - *new_str = gk_strdup("Error in captured subexpression specification."); - regfree(&re); - return 0; - } - - if (nlen-noffset < matches[j].rm_eo-matches[j].rm_so) { - nlen += nlen + (matches[j].rm_eo-matches[j].rm_so); - *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); - } - - strncpy(*new_str+noffset, str+offset+matches[j].rm_so, matches[j].rm_eo); - noffset += matches[j].rm_eo-matches[j].rm_so; - } - else { - gk_free((void **)new_str, LTERM); - *new_str = gk_strdup("Error in replacement string. Missing subexpression number folloing '$'."); - regfree(&re); - return 0; - } - break; - - default: - if (nlen-noffset < 1) { - nlen += nlen + 1; - *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); - } - (*new_str)[noffset++] = replacement[i]; - } - } - - /* Update the offset of str for the next match */ - offset += matches[0].rm_eo; - - if (!global) { - /* Copy the right portion of the string if no 'g' option */ - if (nlen-noffset < len-offset) { - nlen += (len-offset) - (nlen-noffset); - *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); - } - strcpy(*new_str+noffset, str+offset); - noffset += (len-offset); - } - } - } while (global); - - (*new_str)[noffset] = '\0'; - - regfree(&re); - return nmatches + 1; - -} - - - -/************************************************************************/ -/*! \brief Prunes characters from the end of the string. - -This function removes any trailing characters that are included in the -\c rmlist. The trimming stops at the last character (i.e., first character -from the end) that is not in \c rmlist. -This function can be used to removed trailing spaces, newlines, etc. -This is a distructive operation as it modifies the string. - -\param str is the string that will be trimmed. -\param rmlist contains the set of characters that will be removed. -\returns A pointer to \c str itself. -\sa gk_strhprune() -*/ -/*************************************************************************/ -char *gk_strtprune(char *str, char *rmlist) -{ - gk_idx_t i, j; - size_t len; - - len = strlen(rmlist); - - for (i=strlen(str)-1; i>=0; i--) { - for (j=0; j0) { /* If something needs to be removed */ - for (j=0; str[i]; i++, j++) - str[j] = str[i]; - str[j] = '\0'; - } - - return str; -} - - -/************************************************************************/ -/*! \brief Converts a string to upper case. - -This function converts a string to upper case. This operation modifies the -string itself. - -\param str is the string whose case will be changed. -\returns A pointer to \c str itself. -\sa gk_strtolower() -*/ -/*************************************************************************/ -char *gk_strtoupper(char *str) -{ - int i; - - for (i=0; str[i]!='\0'; str[i]=toupper(str[i]), i++); - return str; -} - - -/************************************************************************/ -/*! \brief Converts a string to lower case. - -This function converts a string to lower case. This operation modifies the -string itself. - -\param str is the string whose case will be changed. -\returns A pointer to \c str itself. -\sa gk_strtoupper() -*/ -/*************************************************************************/ -char *gk_strtolower(char *str) -{ - int i; - - for (i=0; str[i]!='\0'; str[i]=tolower(str[i]), i++); - return str; -} - - -/************************************************************************/ -/*! \brief Duplicates a string - -This function is a replacement for C's standard strdup() function. -The key differences between the two are that gk_strdup(): - - uses the dynamic memory allocation routines of \e GKlib. - - it correctly handles NULL input strings. - -The string that is returned must be freed by gk_free(). - -\param orgstr is the string that will be duplicated. -\returns A pointer to the newly created string. -\sa gk_free() -*/ -/*************************************************************************/ -char *gk_strdup(char *orgstr) -{ - int len; - char *str=NULL; - - if (orgstr != NULL) { - len = strlen(orgstr)+1; - str = gk_malloc(len*sizeof(char), "gk_strdup: str"); - strcpy(str, orgstr); - } - - return str; -} - - -/************************************************************************/ -/*! \brief Case insensitive string comparison. - -This function compares two strings for equality by ignoring the case of the -strings. - -\warning This function is \b not equivalent to a case-insensitive - strcmp() function, as it does not return ordering - information. - -\todo Remove the above warning. - -\param s1 is the first string to be compared. -\param s2 is the second string to be compared. -\retval 1 if the strings are identical, -\retval 0 otherwise. -*/ -/*************************************************************************/ -int gk_strcasecmp(char *s1, char *s2) -{ - int i=0; - - if (strlen(s1) != strlen(s2)) - return 0; - - while (s1[i] != '\0') { - if (tolower(s1[i]) != tolower(s2[i])) - return 0; - i++; - } - - return 1; -} - - -/************************************************************************/ -/*! \brief Compare two strings in revere order - -This function is similar to strcmp but it performs the comparison as -if the two strings were reversed. - -\param s1 is the first string to be compared. -\param s2 is the second string to be compared. -\retval -1, 0, 1, if the s1 < s2, s1 == s2, or s1 > s2. -*/ -/*************************************************************************/ -int gk_strrcmp(char *s1, char *s2) -{ - int i1 = strlen(s1)-1; - int i2 = strlen(s2)-1; - - while ((i1 >= 0) && (i2 >= 0)) { - if (s1[i1] != s2[i2]) - return (s1[i1] - s2[i2]); - i1--; - i2--; - } - - /* i1 == -1 and/or i2 == -1 */ - - if (i1 < i2) - return -1; - if (i1 > i2) - return 1; - return 0; -} - - - -/************************************************************************/ -/*! \brief Converts a time_t time into a string - -This function takes a time_t-specified time and returns a string-formated -representation of the corresponding time. The format of the string is -mm/dd/yyyy hh:mm:ss, in which the hours are in military time. - -\param time is the time to be converted. -\return It returns a pointer to a statically allocated string that is - over-written in successive calls of this function. If the - conversion failed, it returns NULL. - -*/ -/*************************************************************************/ -char *gk_time2str(time_t time) -{ - static char datestr[128]; - struct tm *tm; - - tm = localtime(&time); - - if (strftime(datestr, 128, "%m/%d/%Y %H:%M:%S", tm) == 0) - return NULL; - else - return datestr; -} - - - -#if !defined(WIN32) && !defined(__MINGW32__) -/************************************************************************/ -/*! \brief Converts a date/time string into its equivalent time_t value - -This function takes date and/or time specification and converts it in -the equivalent time_t representation. The conversion is done using the -strptime() function. The format that gk_str2time() understands is -mm/dd/yyyy hh:mm:ss, in which the hours are in military time. - -\param str is the date/time string to be converted. -\return If the conversion was successful it returns the time, otherwise - it returns -1. -*/ -/*************************************************************************/ -time_t gk_str2time(char *str) -{ - struct tm time; - time_t rtime; - - memset(&time, '\0', sizeof(time)); - - if (!strptime(str, "%m/%d/%Y %H:%M:%S", &time)) - return -1; - - rtime = mktime(&time); - return (rtime < 0 ? 0 : rtime); -} -#endif - - -/************************************************************************* -* This function returns the ID of a particular string based on the -* supplied StringMap array -**************************************************************************/ -int gk_GetStringID(gk_StringMap_t *strmap, char *key) -{ - int i; - - for (i=0; strmap[i].name; i++) { - if (gk_strcasecmp(key, strmap[i].name)) - return strmap[i].id; - } - - return -1; -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/timers.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/timers.c deleted file mode 100644 index bb8f29620a3..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/timers.c +++ /dev/null @@ -1,52 +0,0 @@ -/*! -\file timers.c -\brief Various timing functions - -\date Started 4/12/2007 -\author George -\version\verbatim $Id: timers.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - - -#include - - - - -/************************************************************************* -* This function returns the CPU seconds -**************************************************************************/ -double gk_WClockSeconds(void) -{ -#ifdef __GNUC__ - struct timeval ctime; - - gettimeofday(&ctime, NULL); - - return (double)ctime.tv_sec + (double).000001*ctime.tv_usec; -#else - return (double)time(NULL); -#endif -} - - -/************************************************************************* -* This function returns the CPU seconds -**************************************************************************/ -double gk_CPUSeconds(void) -{ -//#ifdef __OPENMP__ -#ifdef __OPENMPXXXX__ - return omp_get_wtime(); -#else - #if defined(WIN32) || defined(__MINGW32__) - return((double) clock()/CLOCKS_PER_SEC); - #else - struct rusage r; - - getrusage(RUSAGE_SELF, &r); - return ((r.ru_utime.tv_sec + r.ru_stime.tv_sec) + 1.0e-6*(r.ru_utime.tv_usec + r.ru_stime.tv_usec)); - #endif -#endif -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/tokenizer.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/tokenizer.c deleted file mode 100644 index 5efd262db91..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/tokenizer.c +++ /dev/null @@ -1,77 +0,0 @@ -/*! -\file tokenizer.c -\brief String tokenization routines - -This file contains various routines for splitting an input string into -tokens and returning them in form of a list. The goal is to mimic perl's -split function. - -\date Started 11/23/04 -\author George -\version\verbatim $Id: tokenizer.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - - -#include - - -/************************************************************************ -* This function tokenizes a string based on the user-supplied delimiters -* list. The resulting tokens are returned into an array of strings. -*************************************************************************/ -void gk_strtokenize(char *str, char *delim, gk_Tokens_t *tokens) -{ - int i, ntoks, slen; - - tokens->strbuf = gk_strdup(str); - - slen = strlen(str); - str = tokens->strbuf; - - /* Scan once to determine the number of tokens */ - for (ntoks=0, i=0; intoks = ntoks; - tokens->list = (char **)gk_malloc(ntoks*sizeof(char *), "strtokenize: tokens->list"); - - - /* Scan a second time to mark and link the tokens */ - for (ntoks=0, i=0; ilist[ntoks++] = str+i; - - /* Consume all the consecutive characters from the token */ - while (ilist, &tokens->strbuf, LTERM); -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/util.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/util.c deleted file mode 100644 index e75d68b51bb..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/GKlib/util.c +++ /dev/null @@ -1,108 +0,0 @@ -/*! -\file util.c -\brief Various utility routines - -\date Started 4/12/2007 -\author George -\version\verbatim $Id: util.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim -*/ - - -#include - - - -/************************************************************************* -* This file randomly permutes the contents of an array. -* flag == 0, don't initialize perm -* flag == 1, set p[i] = i -**************************************************************************/ -void gk_RandomPermute(size_t n, int *p, int flag) -{ - gk_idx_t i, u, v; - int tmp; - - if (flag == 1) { - for (i=0; i 1; i++, a = a>>1); - return i-1; -} - - -/************************************************************************* -* This function checks if the argument is a power of 2 -**************************************************************************/ -int gk_ispow2(int a) -{ - return (a == (1< - -typedef __int32 int32_t; -typedef __int64 int64_t; -#define PRId32 "I32d" -#define PRId64 "I64d" -#define SCNd32 "ld" -#define SCNd64 "I64d" -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#else -#include -#endif -#endif - - -/*------------------------------------------------------------------------ -* Setup the basic datatypes -*-------------------------------------------------------------------------*/ -#if IDXTYPEWIDTH == 32 - typedef int32_t idx_t; - - #define IDX_MAX INT32_MAX - #define IDX_MIN INT32_MIN - - #define SCIDX SCNd32 - #define PRIDX PRId32 - - #define strtoidx strtol - #define iabs abs -#elif IDXTYPEWIDTH == 64 - typedef int64_t idx_t; - - #define IDX_MAX INT64_MAX - #define IDX_MIN INT64_MIN - - #define SCIDX SCNd64 - #define PRIDX PRId64 - -#ifdef COMPILER_MSC - #define strtoidx _strtoi64 -#else - #define strtoidx strtoll -#endif - #define iabs labs -#else - #error "Incorrect user-supplied value fo IDXTYPEWIDTH" -#endif - - -#if REALTYPEWIDTH == 32 - typedef float real_t; - - #define SCREAL "f" - #define PRREAL "f" - #define REAL_MAX FLT_MAX - #define REAL_MIN FLT_MIN - #define REAL_EPSILON FLT_EPSILON - - #define rabs fabsf - #define REALEQ(x,y) ((rabs((x)-(y)) <= FLT_EPSILON)) - -#ifdef COMPILER_MSC - #define strtoreal (float)strtod -#else - #define strtoreal strtof -#endif -#elif REALTYPEWIDTH == 64 - typedef double real_t; - - #define SCREAL "lf" - #define PRREAL "lf" - #define REAL_MAX DBL_MAX - #define REAL_MIN DBL_MIN - #define REAL_EPSILON DBL_EPSILON - - #define rabs fabs - #define REALEQ(x,y) ((rabs((x)-(y)) <= DBL_EPSILON)) - - #define strtoreal strtod -#else - #error "Incorrect user-supplied value for REALTYPEWIDTH" -#endif - - -/*------------------------------------------------------------------------ -* Constant definitions -*-------------------------------------------------------------------------*/ -/* Metis's version number */ -#define METIS_VER_MAJOR 5 -#define METIS_VER_MINOR 1 -#define METIS_VER_SUBMINOR 0 - -/* The maximum length of the options[] array */ -#define METIS_NOPTIONS 40 - - - -/*------------------------------------------------------------------------ -* Function prototypes -*-------------------------------------------------------------------------*/ - -#ifdef _WINDLL -#define METIS_API(type) __declspec(dllexport) type __cdecl -#elif defined(__cdecl) -#define METIS_API(type) type __cdecl -#else -#define METIS_API(type) type -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - -METIS_API(int) METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, - idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, - idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, - idx_t *edgecut, idx_t *part); - -METIS_API(int) METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, - idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, - idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, - idx_t *edgecut, idx_t *part); - -METIS_API(int) METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy); - -METIS_API(int) METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy); - -METIS_API(int) METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts, - idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart); - -METIS_API(int) METIS_PartMeshDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts, - real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, - idx_t *npart); - -METIS_API(int) METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, - idx_t *options, idx_t *perm, idx_t *iperm); - -METIS_API(int) METIS_Free(void *ptr); - -METIS_API(int) METIS_SetDefaultOptions(idx_t *options); - - -/* These functions are used by ParMETIS */ - -METIS_API(int) METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, - idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm, - idx_t *sizes); - -METIS_API(int) METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *options, idx_t *sepsize, idx_t *part); - -METIS_API(int) METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy, - idx_t *where, idx_t *hmarker, real_t ubfactor); - - -#ifdef __cplusplus -} -#endif - - - -/*------------------------------------------------------------------------ -* Enum type definitions -*-------------------------------------------------------------------------*/ -/*! Return codes */ -typedef enum { - METIS_OK = 1, /*!< Returned normally */ - METIS_ERROR_INPUT = -2, /*!< Returned due to erroneous inputs and/or options */ - METIS_ERROR_MEMORY = -3, /*!< Returned due to insufficient memory */ - METIS_ERROR = -4 /*!< Some other errors */ -} rstatus_et; - - -/*! Operation type codes */ -typedef enum { - METIS_OP_PMETIS, - METIS_OP_KMETIS, - METIS_OP_OMETIS -} moptype_et; - - -/*! Options codes (i.e., options[]) */ -typedef enum { - METIS_OPTION_PTYPE, - METIS_OPTION_OBJTYPE, - METIS_OPTION_CTYPE, - METIS_OPTION_IPTYPE, - METIS_OPTION_RTYPE, - METIS_OPTION_DBGLVL, - METIS_OPTION_NITER, - METIS_OPTION_NCUTS, - METIS_OPTION_SEED, - METIS_OPTION_NO2HOP, - METIS_OPTION_MINCONN, - METIS_OPTION_CONTIG, - METIS_OPTION_COMPRESS, - METIS_OPTION_CCORDER, - METIS_OPTION_PFACTOR, - METIS_OPTION_NSEPS, - METIS_OPTION_UFACTOR, - METIS_OPTION_NUMBERING, - - /* Used for command-line parameter purposes */ - METIS_OPTION_HELP, - METIS_OPTION_TPWGTS, - METIS_OPTION_NCOMMON, - METIS_OPTION_NOOUTPUT, - METIS_OPTION_BALANCE, - METIS_OPTION_GTYPE, - METIS_OPTION_UBVEC -} moptions_et; - - -/*! Partitioning Schemes */ -typedef enum { - METIS_PTYPE_RB, - METIS_PTYPE_KWAY -} mptype_et; - -/*! Graph types for meshes */ -typedef enum { - METIS_GTYPE_DUAL, - METIS_GTYPE_NODAL -} mgtype_et; - -/*! Coarsening Schemes */ -typedef enum { - METIS_CTYPE_RM, - METIS_CTYPE_SHEM -} mctype_et; - -/*! Initial partitioning schemes */ -typedef enum { - METIS_IPTYPE_GROW, - METIS_IPTYPE_RANDOM, - METIS_IPTYPE_EDGE, - METIS_IPTYPE_NODE, - METIS_IPTYPE_METISRB -} miptype_et; - - -/*! Refinement schemes */ -typedef enum { - METIS_RTYPE_FM, - METIS_RTYPE_GREEDY, - METIS_RTYPE_SEP2SIDED, - METIS_RTYPE_SEP1SIDED -} mrtype_et; - - -/*! Debug Levels */ -typedef enum { - METIS_DBG_INFO = 1, /*!< Shows various diagnostic messages */ - METIS_DBG_TIME = 2, /*!< Perform timing analysis */ - METIS_DBG_COARSEN = 4, /*!< Show the coarsening progress */ - METIS_DBG_REFINE = 8, /*!< Show the refinement progress */ - METIS_DBG_IPART = 16, /*!< Show info on initial partitioning */ - METIS_DBG_MOVEINFO = 32, /*!< Show info on vertex moves during refinement */ - METIS_DBG_SEPINFO = 64, /*!< Show info on vertex moves during sep refinement */ - METIS_DBG_CONNINFO = 128, /*!< Show info on minimization of subdomain connectivity */ - METIS_DBG_CONTIGINFO = 256, /*!< Show info on elimination of connected components */ - METIS_DBG_MEMORY = 2048, /*!< Show info related to wspace allocation */ -} mdbglvl_et; - - -/* Types of objectives */ -typedef enum { - METIS_OBJTYPE_CUT, - METIS_OBJTYPE_VOL, - METIS_OBJTYPE_NODE -} mobjtype_et; - - - -#endif /* _METIS_H_ */ diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/auxapi.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/auxapi.c deleted file mode 100644 index 8976b4ba49e..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/auxapi.c +++ /dev/null @@ -1,43 +0,0 @@ -/** -\file -\brief This file contains various helper API routines for using METIS. - -\date Started 5/12/2011 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version\verbatim $Id: auxapi.c 10409 2011-06-25 16:58:34Z karypis $ \endverbatim -*/ - - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function free memory that was allocated by METIS and retuned - to the application. - - \param ptr points to the memory that was previously allocated by - METIS. -*/ -/*************************************************************************/ -int METIS_Free(void *ptr) -{ - if (ptr != NULL) free(ptr); - return METIS_OK; -} - - -/*************************************************************************/ -/*! This function sets the default values for the options. - - \param options points to an array of size at least METIS_NOPTIONS. -*/ -/*************************************************************************/ -int METIS_SetDefaultOptions(idx_t *options) -{ - iset(METIS_NOPTIONS, -1, options); - - return METIS_OK; -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/balance.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/balance.c deleted file mode 100644 index 3fb0e6e56a4..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/balance.c +++ /dev/null @@ -1,498 +0,0 @@ -/*! -\file -\brief Functions for the edge-based balancing - -\date Started 7/23/97 -\author George -\author Copyright 1997-2011, Regents of the University of Minnesota -\version\verbatim $Id: balance.c 10187 2011-06-13 13:46:57Z karypis $ \endverbatim -*/ - -#include "metislib.h" - -/************************************************************************* -* This function is the entry poidx_t of the bisection balancing algorithms. -**************************************************************************/ -void Balance2Way(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) -{ - if (ComputeLoadImbalanceDiff(graph, 2, ctrl->pijbm, ctrl->ubfactors) <= 0) - return; - - if (graph->ncon == 1) { - /* return right away if the balance is OK */ - if (iabs(ntpwgts[0]*graph->tvwgt[0]-graph->pwgts[0]) < 3*graph->tvwgt[0]/graph->nvtxs) - return; - - if (graph->nbnd > 0) - Bnd2WayBalance(ctrl, graph, ntpwgts); - else - General2WayBalance(ctrl, graph, ntpwgts); - } - else { - McGeneral2WayBalance(ctrl, graph, ntpwgts); - } -} - - -/************************************************************************* -* This function balances two partitions by moving boundary nodes -* from the domain that is overweight to the one that is underweight. -**************************************************************************/ -void Bnd2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) -{ - idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; - idx_t *moved, *perm; - rpq_t *queue; - idx_t higain, mincut, mindiff; - idx_t tpwgts[2]; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - where = graph->where; - id = graph->id; - ed = graph->ed; - pwgts = graph->pwgts; - bndptr = graph->bndptr; - bndind = graph->bndind; - - moved = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - - /* Determine from which domain you will be moving data */ - tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; - tpwgts[1] = graph->tvwgt[0] - tpwgts[0]; - mindiff = iabs(tpwgts[0]-pwgts[0]); - from = (pwgts[0] < tpwgts[0] ? 1 : 0); - to = (from+1)%2; - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions: [%6"PRIDX" %6"PRIDX"] T[%6"PRIDX" %6"PRIDX"], Nv-Nb[%6"PRIDX" %6"PRIDX"]. ICut: %6"PRIDX" [B]\n", - pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, - graph->mincut)); - - queue = rpqCreate(nvtxs); - - iset(nvtxs, -1, moved); - - ASSERT(ComputeCut(graph, where) == graph->mincut); - ASSERT(CheckBnd(graph)); - - /* Insert the boundary nodes of the proper partition whose size is OK in the priority queue */ - nbnd = graph->nbnd; - irandArrayPermute(nbnd, perm, nbnd/5, 1); - for (ii=0; ii 0 || id[bndind[i]] == 0); - ASSERT(bndptr[bndind[i]] != -1); - if (where[bndind[i]] == from && vwgt[bndind[i]] <= mindiff) - rpqInsert(queue, bndind[i], ed[bndind[i]]-id[bndind[i]]); - } - - mincut = graph->mincut; - for (nswaps=0; nswaps tpwgts[to]) - break; - - mincut -= (ed[higain]-id[higain]); - INC_DEC(pwgts[to], pwgts[from], vwgt[higain]); - - where[higain] = to; - moved[higain] = nswaps; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], mincut, pwgts[0], pwgts[1])); - - /************************************************************** - * Update the id[i]/ed[i] values of the affected nodes - ***************************************************************/ - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - - for (j=xadj[higain]; j 0) { /* It will now become a boundary vertex */ - BNDInsert(nbnd, bndind, bndptr, k); - if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff) - rpqInsert(queue, k, ed[k]-id[k]); - } - } - } - } - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("\tMinimum cut: %6"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, pwgts[0], pwgts[1], nbnd)); - - graph->mincut = mincut; - graph->nbnd = nbnd; - - rpqDestroy(queue); - - WCOREPOP; -} - - -/************************************************************************* -* This function balances two partitions by moving the highest gain -* (including negative gain) vertices to the other domain. -* It is used only when tha unbalance is due to non contigous -* subdomains. That is, the are no boundary vertices. -* It moves vertices from the domain that is overweight to the one that -* is underweight. -**************************************************************************/ -void General2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) -{ - idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; - idx_t *moved, *perm; - rpq_t *queue; - idx_t higain, mincut, mindiff; - idx_t tpwgts[2]; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - where = graph->where; - id = graph->id; - ed = graph->ed; - pwgts = graph->pwgts; - bndptr = graph->bndptr; - bndind = graph->bndind; - - moved = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - - /* Determine from which domain you will be moving data */ - tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; - tpwgts[1] = graph->tvwgt[0] - tpwgts[0]; - mindiff = iabs(tpwgts[0]-pwgts[0]); - from = (pwgts[0] < tpwgts[0] ? 1 : 0); - to = (from+1)%2; - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions: [%6"PRIDX" %6"PRIDX"] T[%6"PRIDX" %6"PRIDX"], Nv-Nb[%6"PRIDX" %6"PRIDX"]. ICut: %6"PRIDX" [B]\n", - pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); - - queue = rpqCreate(nvtxs); - - iset(nvtxs, -1, moved); - - ASSERT(ComputeCut(graph, where) == graph->mincut); - ASSERT(CheckBnd(graph)); - - /* Insert the nodes of the proper partition whose size is OK in the priority queue */ - irandArrayPermute(nvtxs, perm, nvtxs/5, 1); - for (ii=0; iimincut; - nbnd = graph->nbnd; - for (nswaps=0; nswaps tpwgts[to]) - break; - - mincut -= (ed[higain]-id[higain]); - INC_DEC(pwgts[to], pwgts[from], vwgt[higain]); - - where[higain] = to; - moved[higain] = nswaps; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], mincut, pwgts[0], pwgts[1])); - - /************************************************************** - * Update the id[i]/ed[i] values of the affected nodes - ***************************************************************/ - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - if (ed[higain] > 0 && bndptr[higain] == -1) - BNDInsert(nbnd, bndind, bndptr, higain); - - for (j=xadj[higain]; j 0 && bndptr[k] == -1) - BNDInsert(nbnd, bndind, bndptr, k); - } - } - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("\tMinimum cut: %6"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, pwgts[0], pwgts[1], nbnd)); - - graph->mincut = mincut; - graph->nbnd = nbnd; - - rpqDestroy(queue); - - WCOREPOP; -} - - -/************************************************************************* -* This function performs an edge-based FM refinement -**************************************************************************/ -void McGeneral2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) -{ - idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass, - me, limit, tmp, cnum; - idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts, *id, *ed, *bndptr, *bndind; - idx_t *moved, *swaps, *perm, *qnum, *qsizes; - idx_t higain, mincut, newcut, mincutorder; - real_t *invtvwgt, *minbalv, *newbalv, minbal, newbal; - rpq_t **queues; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - invtvwgt = graph->invtvwgt; - where = graph->where; - id = graph->id; - ed = graph->ed; - pwgts = graph->pwgts; - bndptr = graph->bndptr; - bndind = graph->bndind; - - moved = iwspacemalloc(ctrl, nvtxs); - swaps = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - qnum = iwspacemalloc(ctrl, nvtxs); - newbalv = rwspacemalloc(ctrl, ncon); - minbalv = rwspacemalloc(ctrl, ncon); - qsizes = iwspacemalloc(ctrl, 2*ncon); - - limit = gk_min(gk_max(0.01*nvtxs, 15), 100); - - /* Initialize the queues */ - queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *)); - for (i=0; i<2*ncon; i++) { - queues[i] = rpqCreate(nvtxs); - qsizes[i] = 0; - } - - for (i=0; i qsizes[2*j+from] && - vwgt[i*ncon+qnum[i]]*invtvwgt[qnum[i]] < 1.3*vwgt[i*ncon+j]*invtvwgt[j]) { - qsizes[2*qnum[i]+from]--; - qsizes[2*j+from]++; - qnum[i] = j; - } - } - } - } - } - - - minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, minbalv); - ASSERT(minbal > 0.0); - - newcut = mincut = graph->mincut; - mincutorder = -1; - - if (ctrl->dbglvl&METIS_DBG_REFINE) { - printf("Parts: ["); - for (l=0; lnvtxs, graph->nbnd, graph->mincut, minbal); - } - - iset(nvtxs, -1, moved); - - ASSERT(ComputeCut(graph, where) == graph->mincut); - ASSERT(CheckBnd(graph)); - - /* Insert all nodes in the priority queues */ - nbnd = graph->nbnd; - irandArrayPermute(nvtxs, perm, nvtxs/10, 1); - for (ii=0; iipijbm, ctrl->ubfactors, queues, &from, &cnum); - to = (from+1)%2; - - if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1) - break; - - newcut -= (ed[higain]-id[higain]); - - iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); - iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); - newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, newbalv); - - if (newbal < minbal || (newbal == minbal && - (newcut < mincut || - (newcut == mincut && BetterBalance2Way(ncon, minbalv, newbalv))))) { - mincut = newcut; - minbal = newbal; - mincutorder = nswaps; - rcopy(ncon, newbalv, minbalv); - } - else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */ - newcut += (ed[higain]-id[higain]); - iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); - iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); - break; - } - - where[higain] = to; - moved[higain] = nswaps; - swaps[nswaps] = higain; - - if (ctrl->dbglvl&METIS_DBG_MOVEINFO) { - printf("Moved %6"PRIDX" from %"PRIDX"(%"PRIDX"). Gain: %5"PRIDX", " - "Cut: %5"PRIDX", NPwgts: ", higain, from, cnum, ed[higain]-id[higain], newcut); - for (l=0; l 0 && bndptr[higain] == -1) - BNDInsert(nbnd, bndind, bndptr, higain); - - for (j=xadj[higain]; j 0 && bndptr[k] == -1) - BNDInsert(nbnd, bndind, bndptr, k); - } - } - - - - /**************************************************************** - * Roll back computations - *****************************************************************/ - for (nswaps--; nswaps>mincutorder; nswaps--) { - higain = swaps[nswaps]; - - to = where[higain] = (where[higain]+1)%2; - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - else if (ed[higain] > 0 && bndptr[higain] == -1) - BNDInsert(nbnd, bndind, bndptr, higain); - - iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); - iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1); - for (j=xadj[higain]; j 0) - BNDInsert(nbnd, bndind, bndptr, k); - } - } - - if (ctrl->dbglvl&METIS_DBG_REFINE) { - printf("\tMincut: %6"PRIDX" at %5"PRIDX", NBND: %6"PRIDX", NPwgts: [", - mincut, mincutorder, nbnd); - for (l=0; lpijbm)); - } - - graph->mincut = mincut; - graph->nbnd = nbnd; - - - for (i=0; i<2*ncon; i++) - rpqDestroy(queues[i]); - - WCOREPOP; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/bucketsort.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/bucketsort.c deleted file mode 100644 index e126d02a632..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/bucketsort.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * bucketsort.c - * - * This file contains code that implement a variety of counting sorting - * algorithms - * - * Started 7/25/97 - * George - * - */ - -#include "metislib.h" - - - -/************************************************************************* -* This function uses simple counting sort to return a permutation array -* corresponding to the sorted order. The keys are arsumed to start from -* 0 and they are positive. This sorting is used during matching. -**************************************************************************/ -void BucketSortKeysInc(ctrl_t *ctrl, idx_t n, idx_t max, idx_t *keys, - idx_t *tperm, idx_t *perm) -{ - idx_t i, ii; - idx_t *counts; - - WCOREPUSH; - - counts = iset(max+2, 0, iwspacemalloc(ctrl, max+2)); - - for (i=0; invtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - ASSERT(adjwgt != NULL); - - htable = ismalloc(nvtxs, 0, "htable"); - - minedge = maxedge = adjncy[0]; - minewgt = maxewgt = adjwgt[0]; - - for (i=0; i maxedge) ? k : maxedge; - minewgt = (adjwgt[j] < minewgt) ? adjwgt[j] : minewgt; - maxewgt = (adjwgt[j] > maxewgt) ? adjwgt[j] : maxewgt; - - if (i == k) { - if (verbose) - printf("Vertex %"PRIDX" contains a self-loop " - "(i.e., diagonal entry in the matrix)!\n", i+numflag); - err++; - } - else { - for (l=xadj[k]; l 0 && verbose) { - printf("A total of %"PRIDX" errors exist in the input file. " - "Correct them, and run again!\n", err); - } - - gk_free((void **)&htable, LTERM); - - return (err == 0 ? 1 : 0); -} - - -/*************************************************************************/ -/*! This function performs a quick check of the weights of the graph */ -/*************************************************************************/ -int CheckInputGraphWeights(idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *vsize, idx_t *adjwgt) -{ - idx_t i; - - if (ncon <= 0) { - printf("Input Error: ncon must be >= 1.\n"); - return 0; - } - - if (vwgt) { - for (i=ncon*nvtxs; i>=0; i--) { - if (vwgt[i] < 0) { - printf("Input Error: negative vertex weight(s).\n"); - return 0; - } - } - } - if (vsize) { - for (i=nvtxs; i>=0; i--) { - if (vsize[i] < 0) { - printf("Input Error: negative vertex sizes(s).\n"); - return 0; - } - } - } - if (adjwgt) { - for (i=xadj[nvtxs]-1; i>=0; i--) { - if (adjwgt[i] < 0) { - printf("Input Error: non-positive edge weight(s).\n"); - return 0; - } - } - } - - return 1; -} - - -/*************************************************************************/ -/*! This function creates a graph whose topology is consistent with - Metis' requirements that: - - There are no self-edges. - - It is undirected; i.e., (u,v) and (v,u) should be present and of the - same weight. - - The adjacency list should not contain multiple edges to the same - other vertex. - - Any of the above errors are fixed by performing the following operations: - - Self-edges are removed. - - The undirected graph is formed by the union of edges. - - One of the duplicate edges is selected. - - The routine does not change the provided vertex weights. -*/ -/*************************************************************************/ -graph_t *FixGraph(graph_t *graph) -{ - idx_t i, j, k, l, nvtxs, nedges; - idx_t *xadj, *adjncy, *adjwgt; - idx_t *nxadj, *nadjncy, *nadjwgt; - graph_t *ngraph; - uvw_t *edges; - - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - ASSERT(adjwgt != NULL); - - ngraph = CreateGraph(); - - ngraph->nvtxs = nvtxs; - - /* deal with vertex weights/sizes */ - ngraph->ncon = graph->ncon; - ngraph->vwgt = icopy(nvtxs*graph->ncon, graph->vwgt, - imalloc(nvtxs*graph->ncon, "FixGraph: vwgt")); - - ngraph->vsize = ismalloc(nvtxs, 1, "FixGraph: vsize"); - if (graph->vsize) - icopy(nvtxs, graph->vsize, ngraph->vsize); - - /* fix graph by sorting the "superset" of edges */ - edges = (uvw_t *)gk_malloc(sizeof(uvw_t)*2*xadj[nvtxs], "FixGraph: edges"); - - for (nedges=0, i=0; i adjncy[j]) { - edges[nedges].u = adjncy[j]; - edges[nedges].v = i; - edges[nedges].w = adjwgt[j]; - nedges++; - } - } - } - - uvwsorti(nedges, edges); - - - /* keep the unique subset */ - for (k=0, i=1; ixadj = ismalloc(nvtxs+1, 0, "FixGraph: nxadj"); - nadjncy = ngraph->adjncy = imalloc(2*nedges, "FixGraph: nadjncy"); - nadjwgt = ngraph->adjwgt = imalloc(2*nedges, "FixGraph: nadjwgt"); - - /* create the adjacency list of the fixed graph from the upper-triangular - part of the adjacency matrix */ - for (k=0; kdbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr)); - - /* determine if the weights on the edges are all the same */ - for (eqewgts=1, i=1; inedges; i++) { - if (graph->adjwgt[0] != graph->adjwgt[i]) { - eqewgts = 0; - break; - } - } - - /* set the maximum allowed coarsest vertex weight */ - for (i=0; incon; i++) - ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo; - - do { - IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); - - /* allocate memory for cmap, if it has not already been done due to - multiple cuts */ - if (graph->cmap == NULL) - graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap"); - - /* determine which matching scheme you will use */ - switch (ctrl->ctype) { - case METIS_CTYPE_RM: - Match_RM(ctrl, graph); - break; - case METIS_CTYPE_SHEM: - if (eqewgts || graph->nedges == 0) - Match_RM(ctrl, graph); - else - Match_SHEM(ctrl, graph); - break; - default: - gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype); - } - - graph = graph->coarser; - eqewgts = 0; - level++; - - ASSERT(CheckGraph(graph, 0, 1)); - - } while (graph->nvtxs > ctrl->CoarsenTo && - graph->nvtxs < COARSEN_FRACTION*graph->finer->nvtxs && - graph->nedges > graph->nvtxs/2); - - IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr)); - - return graph; -} - - -/*************************************************************************/ -/*! This function takes a graph and creates a sequence of nlevels coarser - graphs, where nlevels is an input parameter. - */ -/*************************************************************************/ -graph_t *CoarsenGraphNlevels(ctrl_t *ctrl, graph_t *graph, idx_t nlevels) -{ - idx_t i, eqewgts, level; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr)); - - /* determine if the weights on the edges are all the same */ - for (eqewgts=1, i=1; inedges; i++) { - if (graph->adjwgt[0] != graph->adjwgt[i]) { - eqewgts = 0; - break; - } - } - - /* set the maximum allowed coarsest vertex weight */ - for (i=0; incon; i++) - ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo; - - for (level=0; leveldbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); - - /* allocate memory for cmap, if it has not already been done due to - multiple cuts */ - if (graph->cmap == NULL) - graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap"); - - /* determine which matching scheme you will use */ - switch (ctrl->ctype) { - case METIS_CTYPE_RM: - Match_RM(ctrl, graph); - break; - case METIS_CTYPE_SHEM: - if (eqewgts || graph->nedges == 0) - Match_RM(ctrl, graph); - else - Match_SHEM(ctrl, graph); - break; - default: - gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype); - } - - graph = graph->coarser; - eqewgts = 0; - - ASSERT(CheckGraph(graph, 0, 1)); - - if (graph->nvtxs < ctrl->CoarsenTo || - graph->nvtxs > COARSEN_FRACTION*graph->finer->nvtxs || - graph->nedges < graph->nvtxs/2) - break; - } - - IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr)); - - return graph; -} - - -/*************************************************************************/ -/*! This function finds a matching by randomly selecting one of the - unmatched adjacent vertices. - */ -/**************************************************************************/ -idx_t Match_RM(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, last_unmatched; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt; - idx_t *match, *cmap, *perm; - size_t nunmatched=0; - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr)); - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - cmap = graph->cmap; - - maxvwgt = ctrl->maxvwgt; - - match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs)); - perm = iwspacemalloc(ctrl, nvtxs); - - irandArrayPermute(nvtxs, perm, nvtxs/8, 1); - - for (cnvtxs=0, last_unmatched=0, pi=0; pimaxvwgt requirements */ - if (xadj[i] == xadj[i+1]) { - last_unmatched = gk_max(pi, last_unmatched)+1; - for (; last_unmatchedno2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs) - cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched); - - - /* match the final unmatched vertices with themselves and reorder the vertices - of the coarse graph for memory-friendly contraction */ - for (cnvtxs=0, i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr)); - - CreateCoarseGraph(ctrl, graph, cnvtxs, match); - - WCOREPOP; - - return cnvtxs; -} - - -/**************************************************************************/ -/*! This function finds a matching using the HEM heuristic. The vertices - are visited based on increasing degree to ensure that all vertices are - given a chance to match with something. - */ -/**************************************************************************/ -idx_t Match_SHEM(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, maxwgt, - last_unmatched, avgdegree; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt; - idx_t *match, *cmap, *degrees, *perm, *tperm; - size_t nunmatched=0; - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr)); - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - cmap = graph->cmap; - - maxvwgt = ctrl->maxvwgt; - - match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs)); - perm = iwspacemalloc(ctrl, nvtxs); - tperm = iwspacemalloc(ctrl, nvtxs); - degrees = iwspacemalloc(ctrl, nvtxs); - - irandArrayPermute(nvtxs, tperm, nvtxs/8, 1); - - avgdegree = 0.7*(xadj[nvtxs]/nvtxs); - for (i=0; i avgdegree ? avgdegree : xadj[i+1]-xadj[i]); - BucketSortKeysInc(ctrl, nvtxs, avgdegree, degrees, tperm, perm); - - for (cnvtxs=0, last_unmatched=0, pi=0; pimaxvwgt requirements */ - if (xadj[i] == xadj[i+1]) { - last_unmatched = gk_max(pi, last_unmatched)+1; - for (; last_unmatchedinvtvwgt, vwgt+i*ncon, - vwgt+maxidx*ncon, vwgt+k*ncon)))) { - maxidx = k; - maxwgt = adjwgt[j]; - } - } - - /* If it did not match, record for a 2-hop matching. */ - if (maxidx == i && ivecaxpylez(ncon, 2, vwgt+i*ncon, vwgt+i*ncon, maxvwgt)) { - nunmatched++; - maxidx = UNMATCHED; - } - } - } - } - - if (maxidx != UNMATCHED) { - cmap[i] = cmap[maxidx] = cnvtxs++; - match[i] = maxidx; - match[maxidx] = i; - } - } - } - - //printf("nunmatched: %zu\n", nunmatched); - - /* see if a 2-hop matching is required/allowed */ - if (!ctrl->no2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs) - cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched); - - - /* match the final unmatched vertices with themselves and reorder the vertices - of the coarse graph for memory-friendly contraction */ - for (cnvtxs=0, i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr)); - - CreateCoarseGraph(ctrl, graph, cnvtxs, match); - - WCOREPOP; - - return cnvtxs; -} - - -/*************************************************************************/ -/*! This function matches the unmatched vertices using a 2-hop matching - that involves vertices that are two hops away from each other. */ -/**************************************************************************/ -idx_t Match_2Hop(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, - idx_t cnvtxs, size_t nunmatched) -{ - - cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 2); - cnvtxs = Match_2HopAll(ctrl, graph, perm, match, cnvtxs, &nunmatched, 64); - if (nunmatched > 1.5*UNMATCHEDFOR2HOP*graph->nvtxs) - cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 3); - if (nunmatched > 2.0*UNMATCHEDFOR2HOP*graph->nvtxs) - cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, graph->nvtxs); - - return cnvtxs; -} - - -/*************************************************************************/ -/*! This function matches the unmatched vertices whose degree is less than - maxdegree using a 2-hop matching that involves vertices that are two - hops away from each other. - The requirement of the 2-hop matching is a simple non-empty overlap - between the adjancency lists of the vertices. */ -/**************************************************************************/ -idx_t Match_2HopAny(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, - idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree) -{ - idx_t i, pi, ii, j, jj, k, nvtxs; - idx_t *xadj, *adjncy, *colptr, *rowind; - idx_t *cmap; - size_t nunmatched; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr)); - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - cmap = graph->cmap; - - nunmatched = *r_nunmatched; - - /*IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, printf("IN: nunmatched: %zu\t", * nunmatched)); */ - - /* create the inverted index */ - WCOREPUSH; - colptr = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs+1)); - for (i=0; ij; jj--) { - if (match[rowind[jj]] == UNMATCHED) { - cmap[rowind[j]] = cmap[rowind[jj]] = cnvtxs++; - match[rowind[j]] = rowind[jj]; - match[rowind[jj]] = rowind[j]; - nunmatched -= 2; - break; - } - } - } - } - } - WCOREPOP; - - /* IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, printf("OUT: nunmatched: %zu\n", nunmatched)); */ - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr)); - - *r_nunmatched = nunmatched; - return cnvtxs; -} - - -/*************************************************************************/ -/*! This function matches the unmatched vertices whose degree is less than - maxdegree using a 2-hop matching that involves vertices that are two - hops away from each other. - The requirement of the 2-hop matching is that of identical adjacency - lists. - */ -/**************************************************************************/ -idx_t Match_2HopAll(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, - idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree) -{ - idx_t i, pi, pk, ii, j, jj, k, nvtxs, mask, idegree; - idx_t *xadj, *adjncy; - idx_t *cmap, *mark; - ikv_t *keys; - size_t nunmatched, ncand; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr)); - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - cmap = graph->cmap; - - nunmatched = *r_nunmatched; - mask = IDX_MAX/maxdegree; - - /*IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, printf("IN: nunmatched: %zu\t", nunmatched)); */ - - WCOREPUSH; - - /* collapse vertices with identical adjancency lists */ - keys = ikvwspacemalloc(ctrl, nunmatched); - for (ncand=0, pi=0; pi 1 && idegree < maxdegree) { - for (k=0, j=xadj[i]; jdbglvl, METIS_DBG_COARSEN, printf("OUT: ncand: %zu, nunmatched: %zu\n", ncand, nunmatched)); */ - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr)); - - *r_nunmatched = nunmatched; - return cnvtxs; -} - - -/*************************************************************************/ -/*! This function prints various stats for each graph during coarsening - */ -/*************************************************************************/ -void PrintCGraphStats(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i; - - printf("%10"PRIDX" %10"PRIDX" %10"PRIDX" [%"PRIDX"] [", - graph->nvtxs, graph->nedges, isum(graph->nedges, graph->adjwgt, 1), ctrl->CoarsenTo); - - for (i=0; incon; i++) - printf(" %8"PRIDX":%8"PRIDX, ctrl->maxvwgt[i], graph->tvwgt[i]); - printf(" ]\n"); -} - - -/*************************************************************************/ -/*! This function creates the coarser graph. It uses a simple hash-table - for identifying the adjacent vertices that get collapsed to the same - node. The hash-table can have conflicts, which are handled via a - linear scan. - */ -/*************************************************************************/ -void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, - idx_t *match) -{ - idx_t j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, - v, u, mask, dovsize; - idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; - idx_t *cmap, *htable; - idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt; - graph_t *cgraph; - - dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0); - - /* Check if the mask-version of the code is a good choice */ - mask = HTLENGTH; - if (cnvtxs < 2*mask || graph->nedges/graph->nvtxs > mask/20) { - CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match); - return; - } - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - for (v=0; v (mask>>3)) { - CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match); - return; - } - } - - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr)); - - ncon = graph->ncon; - vwgt = graph->vwgt; - vsize = graph->vsize; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - cmap = graph->cmap; - - /* Initialize the coarser graph */ - cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize); - cxadj = cgraph->xadj; - cvwgt = cgraph->vwgt; - cvsize = cgraph->vsize; - cadjncy = cgraph->adjncy; - cadjwgt = cgraph->adjwgt; - - htable = iset(gk_min(cnvtxs+1, mask+1), -1, iwspacemalloc(ctrl, mask+1)); - - cxadj[0] = cnvtxs = cnedges = 0; - for (v=0; v= 0 && cadjncy[jj] != cnvtxs) { - for (jj=0; jj= 0 && jj < nedges && cadjncy[jj] == cnvtxs) { - cadjncy[jj] = cadjncy[--nedges]; - cadjwgt[jj] = cadjwgt[nedges]; - } - } - - /* Zero out the htable */ - for (j=0; jnedges = cnedges; - - for (j=0; jtvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon); - cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1); - } - - - ReAdjustMemory(ctrl, graph, cgraph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr)); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function creates the coarser graph. It uses a full-size array - (htable) for identifying the adjacent vertices that get collapsed to - the same node. - */ -/*************************************************************************/ -void CreateCoarseGraphNoMask(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, - idx_t *match) -{ - idx_t j, k, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, dovsize; - idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; - idx_t *cmap, *htable; - idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt; - graph_t *cgraph; - - WCOREPUSH; - - dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr)); - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - vsize = graph->vsize; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - cmap = graph->cmap; - - - /* Initialize the coarser graph */ - cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize); - cxadj = cgraph->xadj; - cvwgt = cgraph->vwgt; - cvsize = cgraph->vsize; - cadjncy = cgraph->adjncy; - cadjwgt = cgraph->adjwgt; - - htable = iset(cnvtxs, -1, iwspacemalloc(ctrl, cnvtxs)); - - cxadj[0] = cnvtxs = cnedges = 0; - for (v=0; vnedges = cnedges; - - for (j=0; jtvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon); - cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1); - } - - ReAdjustMemory(ctrl, graph, cgraph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr)); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function creates the coarser graph. It uses a simple hash-table - for identifying the adjacent vertices that get collapsed to the same - node. The hash-table can have conflicts, which are handled via a - linear scan. It relies on the perm[] array to visit the vertices in - increasing cnvtxs order. - */ -/*************************************************************************/ -void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, - idx_t *match, idx_t *perm) -{ - idx_t i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, - v, u, mask, dovsize; - idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; - idx_t *cmap, *htable; - idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt; - graph_t *cgraph; - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr)); - - dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0); - - mask = HTLENGTH; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - vsize = graph->vsize; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - cmap = graph->cmap; - - /* Initialize the coarser graph */ - cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize); - cxadj = cgraph->xadj; - cvwgt = cgraph->vwgt; - cvsize = cgraph->vsize; - cadjncy = cgraph->adjncy; - cadjwgt = cgraph->adjwgt; - - htable = iset(mask+1, -1, iwspacemalloc(ctrl, mask+1)); - - cxadj[0] = cnvtxs = cnedges = 0; - for (i=0; i= 0 && cadjncy[jj] != cnvtxs) { - for (jj=0; jj= 0 && cadjncy[jj] == cnvtxs) { /* This 2nd check is needed for non-adjacent matchings */ - cadjncy[jj] = cadjncy[--nedges]; - cadjwgt[jj] = cadjwgt[nedges]; - } - } - - for (j=0; jnedges = cnedges; - - for (i=0; itvwgt[i] = isum(cgraph->nvtxs, cgraph->vwgt+i, ncon); - cgraph->invtvwgt[i] = 1.0/(cgraph->tvwgt[i] > 0 ? cgraph->tvwgt[i] : 1); - } - - - ReAdjustMemory(ctrl, graph, cgraph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr)); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! Setup the various arrays for the coarse graph - */ -/*************************************************************************/ -graph_t *SetupCoarseGraph(graph_t *graph, idx_t cnvtxs, idx_t dovsize) -{ - graph_t *cgraph; - - cgraph = CreateGraph(); - - cgraph->nvtxs = cnvtxs; - cgraph->ncon = graph->ncon; - - cgraph->finer = graph; - graph->coarser = cgraph; - - - /* Allocate memory for the coarser graph */ - cgraph->xadj = imalloc(cnvtxs+1, "SetupCoarseGraph: xadj"); - cgraph->adjncy = imalloc(graph->nedges, "SetupCoarseGraph: adjncy"); - cgraph->adjwgt = imalloc(graph->nedges, "SetupCoarseGraph: adjwgt"); - cgraph->vwgt = imalloc(cgraph->ncon*cnvtxs, "SetupCoarseGraph: vwgt"); - cgraph->tvwgt = imalloc(cgraph->ncon, "SetupCoarseGraph: tvwgt"); - cgraph->invtvwgt = rmalloc(cgraph->ncon, "SetupCoarseGraph: invtvwgt"); - - if (dovsize) - cgraph->vsize = imalloc(cnvtxs, "SetupCoarseGraph: vsize"); - - return cgraph; -} - - -/*************************************************************************/ -/*! This function re-adjusts the amount of memory that was allocated if - it will lead to significant savings - */ -/*************************************************************************/ -void ReAdjustMemory(ctrl_t *ctrl, graph_t *graph, graph_t *cgraph) -{ - if (cgraph->nedges > 10000 && cgraph->nedges < 0.9*graph->nedges) { - cgraph->adjncy = irealloc(cgraph->adjncy, cgraph->nedges, "ReAdjustMemory: adjncy"); - cgraph->adjwgt = irealloc(cgraph->adjwgt, cgraph->nedges, "ReAdjustMemory: adjwgt"); - } -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/compress.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/compress.c deleted file mode 100644 index d72472b25be..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/compress.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * compress.c - * - * This file contains code for compressing nodes with identical adjacency - * structure and for prunning dense columns - * - * Started 9/17/97 - * George - */ - -#include "metislib.h" - -/*************************************************************************/ -/*! This function compresses a graph by merging identical vertices - The compression should lead to at least 10% reduction. - - The compressed graph that is generated has its adjwgts set to 1. - - \returns 1 if compression was performed, otherwise it returns 0. - -*/ -/**************************************************************************/ -graph_t *CompressGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *cptr, idx_t *cind) -{ - idx_t i, ii, iii, j, jj, k, l, cnvtxs, cnedges; - idx_t *cxadj, *cadjncy, *cvwgt, *mark, *map; - ikv_t *keys; - graph_t *graph=NULL; - - mark = ismalloc(nvtxs, -1, "CompressGraph: mark"); - map = ismalloc(nvtxs, -1, "CompressGraph: map"); - keys = ikvmalloc(nvtxs, "CompressGraph: keys"); - - /* Compute a key for each adjacency list */ - for (i=0; idbglvl, METIS_DBG_INFO, - printf(" Compression: reduction in # of vertices: %"PRIDX".\n", nvtxs-cnvtxs)); - - - if (cnvtxs < COMPRESSION_FRACTION*nvtxs) { - /* Sufficient compression is possible, so go ahead and create the - compressed graph */ - - graph = CreateGraph(); - - cnedges = 0; - for (i=0; ixadj = imalloc(cnvtxs+1, "CompressGraph: xadj"); - cvwgt = graph->vwgt = ismalloc(cnvtxs, 0, "CompressGraph: vwgt"); - cadjncy = graph->adjncy = imalloc(cnedges, "CompressGraph: adjncy"); - graph->adjwgt = ismalloc(cnedges, 1, "CompressGraph: adjwgt"); - - /* Now go and compress the graph */ - iset(nvtxs, -1, mark); - l = cxadj[0] = 0; - for (i=0; invtxs = cnvtxs; - graph->nedges = l; - graph->ncon = 1; - - SetupGraph_tvwgt(graph); - SetupGraph_label(graph); - } - - gk_free((void **)&keys, &map, &mark, LTERM); - - return graph; - -} - - - -/*************************************************************************/ -/*! This function prunes all the vertices in a graph with degree greater - than factor*average. - - \returns the number of vertices that were prunned. -*/ -/*************************************************************************/ -graph_t *PruneGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *iperm, real_t factor) -{ - idx_t i, j, k, l, nlarge, pnvtxs, pnedges; - idx_t *pxadj, *padjncy, *padjwgt, *pvwgt; - idx_t *perm; - graph_t *graph=NULL; - - perm = imalloc(nvtxs, "PruneGraph: perm"); - - factor = factor*xadj[nvtxs]/nvtxs; - - pnvtxs = pnedges = nlarge = 0; - for (i=0; idbglvl, METIS_DBG_INFO, - printf(" Pruned %"PRIDX" of %"PRIDX" vertices.\n", nlarge, nvtxs)); - - - if (nlarge > 0 && nlarge < nvtxs) { - /* Prunning is possible, so go ahead and create the prunned graph */ - graph = CreateGraph(); - - /* Allocate memory for the prunned graph*/ - pxadj = graph->xadj = imalloc(pnvtxs+1, "PruneGraph: xadj"); - pvwgt = graph->vwgt = imalloc(pnvtxs, "PruneGraph: vwgt"); - padjncy = graph->adjncy = imalloc(pnedges, "PruneGraph: adjncy"); - graph->adjwgt = ismalloc(pnedges, 1, "PruneGraph: adjwgt"); - - pxadj[0] = pnedges = l = 0; - for (i=0; invtxs = pnvtxs; - graph->nedges = pnedges; - graph->ncon = 1; - - SetupGraph_tvwgt(graph); - SetupGraph_label(graph); - } - else if (nlarge > 0 && nlarge == nvtxs) { - IFSET(ctrl->dbglvl, METIS_DBG_INFO, - printf(" Pruning is ignored as it removes all vertices.\n")); - nlarge = 0; - } - - - gk_free((void **)&perm, LTERM); - - return graph; -} - - - - - - - - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/contig.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/contig.c deleted file mode 100644 index 3f45902db54..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/contig.c +++ /dev/null @@ -1,699 +0,0 @@ -/*! -\file -\brief Functions that deal with eliminating disconnected partitions - -\date Started 7/15/98 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version $Id: contig.c 10513 2011-07-07 22:06:03Z karypis $ -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function finds the connected components induced by the - partitioning vector. - - \param graph is the graph structure - \param where is the partitioning vector. If this is NULL, then the - entire graph is treated to belong into a single partition. - \param cptr is the ptr structure of the CSR representation of the - components. The length of this vector must be graph->nvtxs+1. - \param cind is the indices structure of the CSR representation of - the components. The length of this vector must be graph->nvtxs. - - \returns the number of components that it found. - - \note The cptr and cind parameters can be NULL, in which case only the - number of connected components is returned. -*/ -/*************************************************************************/ -idx_t FindPartitionInducedComponents(graph_t *graph, idx_t *where, - idx_t *cptr, idx_t *cind) -{ - idx_t i, ii, j, jj, k, me=0, nvtxs, first, last, nleft, ncmps; - idx_t *xadj, *adjncy; - idx_t *touched, *perm, *todo; - idx_t mustfree_ccsr=0, mustfree_where=0; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* Deal with NULL supplied cptr/cind vectors */ - if (cptr == NULL) { - cptr = imalloc(nvtxs+1, "FindPartitionInducedComponents: cptr"); - cind = imalloc(nvtxs, "FindPartitionInducedComponents: cind"); - mustfree_ccsr = 1; - } - - /* Deal with NULL supplied where vector */ - if (where == NULL) { - where = ismalloc(nvtxs, 0, "FindPartitionInducedComponents: where"); - mustfree_where = 1; - } - - /* Allocate memory required for the BFS traversal */ - perm = iincset(nvtxs, 0, imalloc(nvtxs, "FindPartitionInducedComponents: perm")); - todo = iincset(nvtxs, 0, imalloc(nvtxs, "FindPartitionInducedComponents: todo")); - touched = ismalloc(nvtxs, 0, "FindPartitionInducedComponents: touched"); - - - /* Find the connected componends induced by the partition */ - ncmps = -1; - first = last = 0; - nleft = nvtxs; - while (nleft > 0) { - if (first == last) { /* Find another starting vertex */ - cptr[++ncmps] = first; - ASSERT(touched[todo[0]] == 0); - i = todo[0]; - cind[last++] = i; - touched[i] = 1; - me = where[i]; - } - - i = cind[first++]; - k = perm[i]; - j = todo[k] = todo[--nleft]; - perm[j] = k; - - for (j=xadj[i]; jnvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* Allocate memory required for the BFS traversal */ - perm = iincset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - - iincset(nvtxs, 0, bfsperm); /* this array will also store the vertices - still to be processed */ - - /* Find the connected componends induced by the partition */ - first = last = 0; - while (first < nvtxs) { - if (first == last) { /* Find another starting vertex */ - k = bfsperm[last]; - ASSERT(perm[k] != -1); - perm[k] = -1; /* mark node as being visited */ - last++; - } - - i = bfsperm[first++]; - for (j=xadj[i]; jnvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - where = graph->where; - - touched = ismalloc(nvtxs, 0, "IsConnected: touched"); - queue = imalloc(nvtxs, "IsConnected: queue"); - cptr = imalloc(nvtxs+1, "IsConnected: cptr"); - - nleft = 0; - for (i=0; i 1 && report) { - printf("The graph has %"PRIDX" connected components in partition %"PRIDX":\t", ncmps, pid); - for (i=0; ivwgt[queue[j]]; - printf("[%5"PRIDX" %5"PRIDX"] ", cptr[i+1]-cptr[i], wgt); - /* - if (cptr[i+1]-cptr[i] == 1) - printf("[%"PRIDX" %"PRIDX"] ", queue[cptr[i]], xadj[queue[cptr[i]]+1]-xadj[queue[cptr[i]]]); - */ - } - printf("\n"); - } - - gk_free((void **)&touched, &queue, &cptr, LTERM); - - return (ncmps == 1 ? 1 : 0); -} - - -/*************************************************************************/ -/*! This function identifies the number of connected components in a graph - that result after removing the vertices that belong to the vertex - separator (i.e., graph->where[i] == 2). - The connected component memberships are returned in the CSR-style - pair of arrays cptr, cind. -*/ -/**************************************************************************/ -idx_t FindSepInducedComponents(ctrl_t *ctrl, graph_t *graph, idx_t *cptr, - idx_t *cind) -{ - idx_t i, j, k, nvtxs, first, last, nleft, ncmps, wgt; - idx_t *xadj, *adjncy, *where, *touched, *queue; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - where = graph->where; - - touched = ismalloc(nvtxs, 0, "IsConnected: queue"); - - for (i=0; inbnd; i++) - touched[graph->bndind[i]] = 1; - - queue = cind; - - nleft = 0; - for (i=0; iwhere and tries to push them around to - remove some of them. */ -/*************************************************************************/ -void EliminateComponents(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, jj, k, me, nparts, nvtxs, ncon, ncmps, other, - ncand, target; - idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts; - idx_t *cptr, *cind, *cpvec, *pcptr, *pcind, *cwhere; - idx_t cid, bestcid, *cwgt, *bestcwgt; - idx_t ntodo, oldntodo, *todo; - rkv_t *cand; - real_t *tpwgts; - idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL; /* volume specific work arrays */ - - WCOREPUSH; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt); - - where = graph->where; - pwgts = graph->pwgts; - - nparts = ctrl->nparts; - tpwgts = ctrl->tpwgts; - - cptr = iwspacemalloc(ctrl, nvtxs+1); - cind = iwspacemalloc(ctrl, nvtxs); - - ncmps = FindPartitionInducedComponents(graph, where, cptr, cind); - - IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, - printf("I found %"PRIDX" components, for this %"PRIDX"-way partition\n", - ncmps, nparts)); - - /* There are more components than partitions */ - if (ncmps > nparts) { - cwgt = iwspacemalloc(ctrl, ncon); - bestcwgt = iwspacemalloc(ctrl, ncon); - cpvec = iwspacemalloc(ctrl, nparts); - pcptr = iset(nparts+1, 0, iwspacemalloc(ctrl, nparts+1)); - pcind = iwspacemalloc(ctrl, ncmps); - cwhere = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - todo = iwspacemalloc(ctrl, ncmps); - cand = (rkv_t *)wspacemalloc(ctrl, nparts*sizeof(rkv_t)); - - if (ctrl->objtype == METIS_OBJTYPE_VOL) { - /* Vol-refinement specific working arrays */ - modind = iwspacemalloc(ctrl, nvtxs); - vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); - } - - - /* Get a CSR representation of the components-2-partitions mapping */ - for (i=0; i 0) { - oldntodo = ntodo; - for (i=0; idbglvl, METIS_DBG_CONTIGINFO, - printf("Trying to move %"PRIDX" [%"PRIDX"] from %"PRIDX"\n", - cid, isum(ncon, cwgt, 1), me)); - - /* Determine the connectivity */ - iset(nparts, 0, cpvec); - for (j=cptr[cid]; j 0) { - cand[ncand].key = cpvec[j]; - cand[ncand++].val = j; - } - } - if (ncand == 0) - continue; - - rkvsortd(ncand, cand); - - /* Limit the moves to only the top candidates, which are defined as - those with connectivity at least 50% of the best. - This applies only when ncon=1, as for multi-constraint, balancing - will be hard. */ - if (ncon == 1) { - for (j=1; jubfactors, - 1, pwgts+target*ncon, ctrl->pijbm+target*ncon, - 1, pwgts+cand[j].val*ncon, ctrl->pijbm+cand[j].val*ncon)) - target = cand[j].val; - } - - IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, - printf("\tMoving it to %"PRIDX" [%"PRIDX"] [%"PRIDX"]\n", target, cpvec[target], ncand)); - - /* Note that as a result of a previous movement, a connected component may - now will like to stay to its original partition */ - if (target != me) { - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - MoveGroupContigForCut(ctrl, graph, target, cid, cptr, cind); - break; - - case METIS_OBJTYPE_VOL: - MoveGroupContigForVol(ctrl, graph, target, cid, cptr, cind, - vmarker, pmarker, modind); - break; - - default: - gk_errexit(SIGERR, "Unknown objtype %d\n", ctrl->objtype); - } - } - - /* Update the cwhere vector */ - for (j=cptr[cid]; jdbglvl, METIS_DBG_CONTIGINFO, printf("Stopped at ntodo: %"PRIDX"\n", ntodo)); - break; - } - } - - for (i=0; invtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - - nbnd = graph->nbnd; - - for (iii=ptr[gid]; iiickrinfo+i; - if (myrinfo->inbr == -1) { - myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); - myrinfo->nnbrs = 0; - } - mynbrs = ctrl->cnbrpool + myrinfo->inbr; - - /* find the location of 'to' in myrinfo or create it if it is not there */ - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == to) - break; - } - if (k == myrinfo->nnbrs) { - mynbrs[k].pid = to; - mynbrs[k].ed = 0; - myrinfo->nnbrs++; - } - - graph->mincut -= mynbrs[k].ed-myrinfo->id; - - /* Update ID/ED and BND related information for the moved vertex */ - iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); - iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); - UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, - bndptr, bndind, BNDTYPE_REFINE); - - /* Update the degrees of adjacent vertices */ - for (j=xadj[i]; jckrinfo+ii; - - UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, - from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE); - } - - ASSERT(CheckRInfo(ctrl, graph->ckrinfo+i)); - } - - graph->nbnd = nbnd; -} - - -/*************************************************************************/ -/*! This function moves a collection of vertices and updates their rinfo - */ -/*************************************************************************/ -void MoveGroupContigForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid, - idx_t *ptr, idx_t *ind, idx_t *vmarker, idx_t *pmarker, - idx_t *modind) -{ - idx_t i, ii, iii, j, jj, k, l, nvtxs, from, me, other, xgain; - idx_t *xadj, *vsize, *adjncy, *where; - vkrinfo_t *myrinfo, *orinfo; - vnbr_t *mynbrs, *onbrs; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vsize = graph->vsize; - adjncy = graph->adjncy; - where = graph->where; - - for (iii=ptr[gid]; iiivkrinfo+i; - if (myrinfo->inbr == -1) { - myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); - myrinfo->nnbrs = 0; - } - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? vsize[i] : 0); - - /* find the location of 'to' in myrinfo or create it if it is not there */ - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == to) - break; - } - if (k == myrinfo->nnbrs) { - if (myrinfo->nid > 0) - xgain -= vsize[i]; - - /* determine the volume gain resulting from that move */ - for (j=xadj[i]; jvkrinfo+ii; - onbrs = ctrl->vnbrpool + orinfo->inbr; - ASSERT(other != to) - - if (from == other) { - /* Same subdomain vertex: Decrease the gain if 'to' is a new neighbor. */ - for (l=0; lnnbrs; l++) { - if (onbrs[l].pid == to) - break; - } - if (l == orinfo->nnbrs) - xgain -= vsize[ii]; - } - else { - /* Remote vertex: increase if 'to' is a new subdomain */ - for (l=0; lnnbrs; l++) { - if (onbrs[l].pid == to) - break; - } - if (l == orinfo->nnbrs) - xgain -= vsize[ii]; - - /* Remote vertex: decrease if i is the only connection to 'from' */ - for (l=0; lnnbrs; l++) { - if (onbrs[l].pid == from && onbrs[l].ned == 1) { - xgain += vsize[ii]; - break; - } - } - } - } - graph->minvol -= xgain; - graph->mincut -= -myrinfo->nid; - } - else { - graph->minvol -= (xgain + mynbrs[k].gv); - graph->mincut -= mynbrs[k].ned-myrinfo->nid; - } - - - /* Update where and pwgts */ - where[i] = to; - iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); - iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); - - /* Update the id/ed/gains/bnd of potentially affected nodes */ - KWayVolUpdate(ctrl, graph, i, from, to, NULL, NULL, NULL, NULL, - NULL, BNDTYPE_REFINE, vmarker, pmarker, modind); - - /*CheckKWayVolPartitionParams(ctrl, graph);*/ - } - - ASSERT(ComputeCut(graph, where) == graph->mincut); - ASSERTP(ComputeVolume(graph, where) == graph->minvol, - ("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol)); - -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/debug.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/debug.c deleted file mode 100644 index e188135da57..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/debug.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * debug.c - * - * This file contains code that performs self debuging - * - * Started 7/24/97 - * George - * - */ - -#include "metislib.h" - - - -/*************************************************************************/ -/*! This function computes the total edgecut - */ -/*************************************************************************/ -idx_t ComputeCut(graph_t *graph, idx_t *where) -{ - idx_t i, j, cut; - - if (graph->adjwgt == NULL) { - for (cut=0, i=0; invtxs; i++) { - for (j=graph->xadj[i]; jxadj[i+1]; j++) - if (where[i] != where[graph->adjncy[j]]) - cut++; - } - } - else { - for (cut=0, i=0; invtxs; i++) { - for (j=graph->xadj[i]; jxadj[i+1]; j++) - if (where[i] != where[graph->adjncy[j]]) - cut += graph->adjwgt[j]; - } - } - - return cut/2; -} - - -/*************************************************************************/ -/*! This function computes the total volume - */ -/*************************************************************************/ -idx_t ComputeVolume(graph_t *graph, idx_t *where) -{ - idx_t i, j, k, me, nvtxs, nparts, totalv; - idx_t *xadj, *adjncy, *vsize, *marker; - - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - vsize = graph->vsize; - - nparts = where[iargmax(nvtxs, where)]+1; - marker = ismalloc(nparts, -1, "ComputeVolume: marker"); - - totalv = 0; - - for (i=0; iadjwgt == NULL) { - for (i=0; invtxs; i++) { - for (j=graph->xadj[i]; jxadj[i+1]; j++) - if (where[i] != where[graph->adjncy[j]]) - cuts[where[i]]++; - } - } - else { - for (i=0; invtxs; i++) { - for (j=graph->xadj[i]; jxadj[i+1]; j++) - if (where[i] != where[graph->adjncy[j]]) - cuts[where[i]] += graph->adjwgt[j]; - } - } - - maxcut = cuts[iargmax(nparts, cuts)]; - - printf("%zu => %"PRIDX"\n", iargmax(nparts, cuts), maxcut); - - gk_free((void **)&cuts, LTERM); - - return maxcut; -} - - -/*************************************************************************/ -/*! This function checks whether or not the boundary information is correct - */ -/*************************************************************************/ -idx_t CheckBnd(graph_t *graph) -{ - idx_t i, j, nvtxs, nbnd; - idx_t *xadj, *adjncy, *where, *bndptr, *bndind; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - - for (nbnd=0, i=0; inbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd)); - - return 1; -} - - - -/*************************************************************************/ -/*! This function checks whether or not the boundary information is correct - */ -/*************************************************************************/ -idx_t CheckBnd2(graph_t *graph) -{ - idx_t i, j, nvtxs, nbnd, id, ed; - idx_t *xadj, *adjncy, *where, *bndptr, *bndind; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - - for (nbnd=0, i=0; iadjwgt[j]; - else - id += graph->adjwgt[j]; - } - if (ed - id >= 0 && xadj[i] < xadj[i+1]) { - nbnd++; - ASSERTP(bndptr[i] != -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", i, id, ed)); - ASSERT(bndind[bndptr[i]] == i); - } - } - - ASSERTP(nbnd == graph->nbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd)); - - return 1; -} - - -/*************************************************************************/ -/*! This function checks whether or not the boundary information is correct - */ -/*************************************************************************/ -idx_t CheckNodeBnd(graph_t *graph, idx_t onbnd) -{ - idx_t i, j, nvtxs, nbnd; - idx_t *xadj, *adjncy, *where, *bndptr, *bndind; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - - for (nbnd=0, i=0; icnbrpool + rinfo->inbr; - - for (i=0; innbrs; i++) { - for (j=i+1; jnnbrs; j++) - ASSERTP(nbrs[i].pid != nbrs[j].pid, - ("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", - i, j, nbrs[i].pid, nbrs[j].pid)); - } - - return 1; -} - - - -/*************************************************************************/ -/*! This function checks the correctness of the NodeFM data structures - */ -/*************************************************************************/ -idx_t CheckNodePartitionParams(graph_t *graph) -{ - idx_t i, j, k, l, nvtxs, me, other; - idx_t *xadj, *adjncy, *adjwgt, *vwgt, *where; - idx_t edegrees[2], pwgts[3]; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - where = graph->where; - - /*------------------------------------------------------------ - / Compute now the separator external degrees - /------------------------------------------------------------*/ - pwgts[0] = pwgts[1] = pwgts[2] = 0; - for (i=0; inrinfo[i].edegrees[0] || - edegrees[1] != graph->nrinfo[i].edegrees[1]) { - printf("Something wrong with edegrees: %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", - i, edegrees[0], edegrees[1], - graph->nrinfo[i].edegrees[0], graph->nrinfo[i].edegrees[1]); - return 0; - } - } - } - - if (pwgts[0] != graph->pwgts[0] || - pwgts[1] != graph->pwgts[1] || - pwgts[2] != graph->pwgts[2]) { - printf("Something wrong with part-weights: %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", pwgts[0], pwgts[1], pwgts[2], graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]); - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function checks if the separator is indeed a separator - */ -/*************************************************************************/ -idx_t IsSeparable(graph_t *graph) -{ - idx_t i, j, nvtxs, other; - idx_t *xadj, *adjncy, *where; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - where = graph->where; - - for (i=0; ivrinfo structure */ -/*************************************************************************/ -void CheckKWayVolPartitionParams(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, k, kk, l, nvtxs, nbnd, mincut, minvol, me, other, pid; - idx_t *xadj, *vsize, *adjncy, *pwgts, *where, *bndind, *bndptr; - vkrinfo_t *rinfo, *myrinfo, *orinfo, tmprinfo; - vnbr_t *mynbrs, *onbrs, *tmpnbrs; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vsize = graph->vsize; - adjncy = graph->adjncy; - where = graph->where; - rinfo = graph->vkrinfo; - - tmpnbrs = (vnbr_t *)wspacemalloc(ctrl, ctrl->nparts*sizeof(vnbr_t)); - - /*------------------------------------------------------------ - / Compute now the iv/ev degrees - /------------------------------------------------------------*/ - for (i=0; ivnbrpool + myrinfo->inbr; - - for (k=0; knnbrs; k++) - tmpnbrs[k] = mynbrs[k]; - - tmprinfo.nnbrs = myrinfo->nnbrs; - tmprinfo.nid = myrinfo->nid; - tmprinfo.ned = myrinfo->ned; - - myrinfo = &tmprinfo; - mynbrs = tmpnbrs; - - for (k=0; knnbrs; k++) - mynbrs[k].gv = 0; - - for (j=xadj[i]; jvnbrpool + orinfo->inbr; - - if (me == other) { - /* Find which domains 'i' is connected and 'ii' is not and update their gain */ - for (k=0; knnbrs; k++) { - pid = mynbrs[k].pid; - for (kk=0; kknnbrs; kk++) { - if (onbrs[kk].pid == pid) - break; - } - if (kk == orinfo->nnbrs) - mynbrs[k].gv -= vsize[ii]; - } - } - else { - /* Find the orinfo[me].ed and see if I'm the only connection */ - for (k=0; knnbrs; k++) { - if (onbrs[k].pid == me) - break; - } - - if (onbrs[k].ned == 1) { /* I'm the only connection of 'ii' in 'me' */ - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == other) { - mynbrs[k].gv += vsize[ii]; - break; - } - } - - /* Increase the gains for all the common domains between 'i' and 'ii' */ - for (k=0; knnbrs; k++) { - if ((pid = mynbrs[k].pid) == other) - continue; - for (kk=0; kknnbrs; kk++) { - if (onbrs[kk].pid == pid) { - mynbrs[k].gv += vsize[ii]; - break; - } - } - } - - } - else { - /* Find which domains 'i' is connected and 'ii' is not and update their gain */ - for (k=0; knnbrs; k++) { - if ((pid = mynbrs[k].pid) == other) - continue; - for (kk=0; kknnbrs; kk++) { - if (onbrs[kk].pid == pid) - break; - } - if (kk == orinfo->nnbrs) - mynbrs[k].gv -= vsize[ii]; - } - } - } - } - - myrinfo = rinfo+i; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - for (k=0; knnbrs; k++) { - pid = mynbrs[k].pid; - for (kk=0; kkncon == 1) - FM_2WayCutRefine(ctrl, graph, ntpwgts, niter); - else - FM_Mc2WayCutRefine(ctrl, graph, ntpwgts, niter); -} - - -/*************************************************************************/ -/*! This function performs a cut-focused FM refinement */ -/*************************************************************************/ -void FM_2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) -{ - idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, limit, tmp; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; - idx_t *moved, *swaps, *perm; - rpq_t *queues[2]; - idx_t higain, mincut, mindiff, origdiff, initcut, newcut, mincutorder, avgvwgt; - idx_t tpwgts[2]; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - where = graph->where; - id = graph->id; - ed = graph->ed; - pwgts = graph->pwgts; - bndptr = graph->bndptr; - bndind = graph->bndind; - - moved = iwspacemalloc(ctrl, nvtxs); - swaps = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - - tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; - tpwgts[1] = graph->tvwgt[0]-tpwgts[0]; - - limit = gk_min(gk_max(0.01*nvtxs, 15), 100); - avgvwgt = gk_min((pwgts[0]+pwgts[1])/20, 2*(pwgts[0]+pwgts[1])/nvtxs); - - queues[0] = rpqCreate(nvtxs); - queues[1] = rpqCreate(nvtxs); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - Print2WayRefineStats(ctrl, graph, ntpwgts, 0, -2)); - - origdiff = iabs(tpwgts[0]-pwgts[0]); - iset(nvtxs, -1, moved); - for (pass=0; passmincut; - mindiff = iabs(tpwgts[0]-pwgts[0]); - - ASSERT(ComputeCut(graph, where) == graph->mincut); - ASSERT(CheckBnd(graph)); - - /* Insert boundary nodes in the priority queues */ - nbnd = graph->nbnd; - irandArrayPermute(nbnd, perm, nbnd, 1); - for (ii=0; ii 0 || id[bndind[i]] == 0); - ASSERT(bndptr[bndind[i]] != -1); - rpqInsert(queues[where[bndind[i]]], bndind[i], ed[bndind[i]]-id[bndind[i]]); - } - - for (nswaps=0; nswaps limit) { /* We hit the limit, undo last move */ - newcut += (ed[higain]-id[higain]); - INC_DEC(pwgts[from], pwgts[to], vwgt[higain]); - break; - } - - where[higain] = to; - moved[higain] = nswaps; - swaps[nswaps] = higain; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], newcut, pwgts[0], pwgts[1])); - - /************************************************************** - * Update the id[i]/ed[i] values of the affected nodes - ***************************************************************/ - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - - for (j=xadj[higain]; j 0) { /* It will now become a boundary vertex */ - BNDInsert(nbnd, bndind, bndptr, k); - if (moved[k] == -1) - rpqInsert(queues[where[k]], k, ed[k]-id[k]); - } - } - } - - } - - - /**************************************************************** - * Roll back computations - *****************************************************************/ - for (i=0; imincutorder; nswaps--) { - higain = swaps[nswaps]; - - to = where[higain] = (where[higain]+1)%2; - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - else if (ed[higain] > 0 && bndptr[higain] == -1) - BNDInsert(nbnd, bndind, bndptr, higain); - - INC_DEC(pwgts[to], pwgts[(to+1)%2], vwgt[higain]); - for (j=xadj[higain]; j 0) - BNDInsert(nbnd, bndind, bndptr, k); - } - } - - graph->mincut = mincut; - graph->nbnd = nbnd; - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - Print2WayRefineStats(ctrl, graph, ntpwgts, 0, mincutorder)); - - if (mincutorder <= 0 || mincut == initcut) - break; - } - - rpqDestroy(queues[0]); - rpqDestroy(queues[1]); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function performs a cut-focused multi-constraint FM refinement */ -/*************************************************************************/ -void FM_Mc2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) -{ - idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass, - me, limit, tmp, cnum; - idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *id, *ed, - *bndptr, *bndind; - idx_t *moved, *swaps, *perm, *qnum; - idx_t higain, mincut, initcut, newcut, mincutorder; - real_t *invtvwgt, *ubfactors, *minbalv, *newbalv; - real_t origbal, minbal, newbal, rgain, ffactor; - rpq_t **queues; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - invtvwgt = graph->invtvwgt; - where = graph->where; - id = graph->id; - ed = graph->ed; - pwgts = graph->pwgts; - bndptr = graph->bndptr; - bndind = graph->bndind; - - moved = iwspacemalloc(ctrl, nvtxs); - swaps = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - qnum = iwspacemalloc(ctrl, nvtxs); - ubfactors = rwspacemalloc(ctrl, ncon); - newbalv = rwspacemalloc(ctrl, ncon); - minbalv = rwspacemalloc(ctrl, ncon); - - limit = gk_min(gk_max(0.01*nvtxs, 25), 150); - - - /* Determine a fudge factor to allow the refinement routines to get out - of tight balancing constraints. */ - ffactor = .5/gk_max(20, nvtxs); - - /* Initialize the queues */ - queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *)); - for (i=0; i<2*ncon; i++) - queues[i] = rpqCreate(nvtxs); - for (i=0; ipijbm, ctrl->ubfactors, ubfactors); - for (i=0; i 0 ? ctrl->ubfactors[i]+ubfactors[i] : ctrl->ubfactors[i]); - - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - Print2WayRefineStats(ctrl, graph, ntpwgts, origbal, -2)); - - iset(nvtxs, -1, moved); - for (pass=0; passmincut; - - minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, minbalv); - - ASSERT(ComputeCut(graph, where) == graph->mincut); - ASSERT(CheckBnd(graph)); - - /* Insert boundary nodes in the priority queues */ - nbnd = graph->nbnd; - irandArrayPermute(nbnd, perm, nbnd/5, 1); - for (ii=0; ii 0 || id[i] == 0); - ASSERT(bndptr[i] != -1); - //rgain = 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1); - //rgain = (ed[i]-id[i] > 0 ? 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1) : ed[i]-id[i]); - rgain = ed[i]-id[i]; - rpqInsert(queues[2*qnum[i]+where[i]], i, rgain); - } - - for (nswaps=0; nswapspijbm, ubfactors, queues, &from, &cnum); - - to = (from+1)%2; - - if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1) - break; - ASSERT(bndptr[higain] != -1); - - newcut -= (ed[higain]-id[higain]); - - iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); - iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); - newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, newbalv); - - if ((newcut < mincut && newbal <= ffactor) || - (newcut == mincut && (newbal < minbal || - (newbal == minbal && BetterBalance2Way(ncon, minbalv, newbalv))))) { - mincut = newcut; - minbal = newbal; - mincutorder = nswaps; - rcopy(ncon, newbalv, minbalv); - } - else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */ - newcut += (ed[higain]-id[higain]); - iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); - iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); - break; - } - - where[higain] = to; - moved[higain] = nswaps; - swaps[nswaps] = higain; - - if (ctrl->dbglvl&METIS_DBG_MOVEINFO) { - printf("Moved%6"PRIDX" from %"PRIDX"(%"PRIDX") Gain:%5"PRIDX", " - "Cut:%5"PRIDX", NPwgts:", higain, from, cnum, ed[higain]-id[higain], newcut); - for (l=0; lpijbm), newbal); - } - - - /************************************************************** - * Update the id[i]/ed[i] values of the affected nodes - ***************************************************************/ - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - - for (j=xadj[higain]; j 0 ? - // 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]); - rgain = ed[k]-id[k]; - rpqUpdate(queues[2*qnum[k]+where[k]], k, rgain); - } - } - } - else { - if (ed[k] > 0) { /* It will now become a boundary vertex */ - BNDInsert(nbnd, bndind, bndptr, k); - if (moved[k] == -1) { - //rgain = 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1); - //rgain = (ed[k]-id[k] > 0 ? - // 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]); - rgain = ed[k]-id[k]; - rpqInsert(queues[2*qnum[k]+where[k]], k, rgain); - } - } - } - } - - } - - - /**************************************************************** - * Roll back computations - *****************************************************************/ - for (i=0; imincutorder; nswaps--) { - higain = swaps[nswaps]; - - to = where[higain] = (where[higain]+1)%2; - SWAP(id[higain], ed[higain], tmp); - if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) - BNDDelete(nbnd, bndind, bndptr, higain); - else if (ed[higain] > 0 && bndptr[higain] == -1) - BNDInsert(nbnd, bndind, bndptr, higain); - - iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); - iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1); - for (j=xadj[higain]; j 0) - BNDInsert(nbnd, bndind, bndptr, k); - } - } - - graph->mincut = mincut; - graph->nbnd = nbnd; - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - Print2WayRefineStats(ctrl, graph, ntpwgts, minbal, mincutorder)); - - if (mincutorder <= 0 || mincut == initcut) - break; - } - - for (i=0; i<2*ncon; i++) - rpqDestroy(queues[i]); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function selects the partition number and the queue from which - we will move vertices out. */ -/*************************************************************************/ -void SelectQueue(graph_t *graph, real_t *pijbm, real_t *ubfactors, - rpq_t **queues, idx_t *from, idx_t *cnum) -{ - idx_t ncon, i, part; - real_t max, tmp; - - ncon = graph->ncon; - - *from = -1; - *cnum = -1; - - /* First determine the side and the queue, irrespective of the presence of nodes. - The side & queue is determined based on the most violated balancing constraint. */ - for (max=0.0, part=0; part<2; part++) { - for (i=0; ipwgts[part*ncon+i]*pijbm[part*ncon+i] - ubfactors[i]; - /* the '=' in the test bellow is to ensure that under tight constraints - the partition that is at the max is selected */ - if (tmp >= max) { - max = tmp; - *from = part; - *cnum = i; - } - } - } - - - if (*from != -1) { - /* in case the desired queue is empty, select a queue from the same side */ - if (rpqLength(queues[2*(*cnum)+(*from)]) == 0) { - for (i=0; i 0) { - max = graph->pwgts[(*from)*ncon+i]*pijbm[(*from)*ncon+i] - ubfactors[i]; - *cnum = i; - break; - } - } - - for (i++; ipwgts[(*from)*ncon+i]*pijbm[(*from)*ncon+i] - ubfactors[i]; - if (tmp > max && rpqLength(queues[2*i+(*from)]) > 0) { - max = tmp; - *cnum = i; - } - } - } - - /* - printf("Selected1 %"PRIDX"(%"PRIDX") -> %"PRIDX" [%5"PRREAL"]\n", - *from, *cnum, rpqLength(queues[2*(*cnum)+(*from)]), max); - */ - } - else { - /* the partitioning does not violate balancing constraints, in which case select - a queue based on cut criteria */ - for (part=0; part<2; part++) { - for (i=0; i 0 && - (*from == -1 || rpqSeeTopKey(queues[2*i+part]) > max)) { - max = rpqSeeTopKey(queues[2*i+part]); - *from = part; - *cnum = i; - } - } - } - /* - printf("Selected2 %"PRIDX"(%"PRIDX") -> %"PRIDX"\n", - *from, *cnum, rpqLength(queues[2*(*cnum)+(*from)]), max); - */ - } -} - - -/*************************************************************************/ -/*! Prints statistics about the refinement */ -/*************************************************************************/ -void Print2WayRefineStats(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - real_t deltabal, idx_t mincutorder) -{ - int i; - - if (mincutorder == -2) { - printf("Parts: "); - printf("Nv-Nb[%5"PRIDX" %5"PRIDX"] ICut: %6"PRIDX, - graph->nvtxs, graph->nbnd, graph->mincut); - printf(" ["); - for (i=0; incon; i++) - printf("(%.3"PRREAL" %.3"PRREAL" T:%.3"PRREAL" %.3"PRREAL")", - graph->pwgts[i]*graph->invtvwgt[i], - graph->pwgts[graph->ncon+i]*graph->invtvwgt[i], - ntpwgts[i], ntpwgts[graph->ncon+i]); - printf("] LB: %.3"PRREAL"(%+.3"PRREAL")\n", - ComputeLoadImbalance(graph, 2, ctrl->pijbm), deltabal); - } - else { - printf("\tMincut: %6"PRIDX" at %5"PRIDX" NBND %6"PRIDX" NPwgts: [", - graph->mincut, mincutorder, graph->nbnd); - for (i=0; incon; i++) - printf("(%.3"PRREAL" %.3"PRREAL")", - graph->pwgts[i]*graph->invtvwgt[i], graph->pwgts[graph->ncon+i]*graph->invtvwgt[i]); - printf("] LB: %.3"PRREAL"(%+.3"PRREAL")\n", - ComputeLoadImbalance(graph, 2, ctrl->pijbm), deltabal); - } -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/fortran.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/fortran.c deleted file mode 100644 index 5c3ed90297f..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/fortran.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * fortran.c - * - * This file contains code for the fortran to C interface - * - * Started 8/19/97 - * George - * - */ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function changes the numbering to start from 0 instead of 1 */ -/*************************************************************************/ -void Change2CNumbering(idx_t nvtxs, idx_t *xadj, idx_t *adjncy) -{ - idx_t i; - - for (i=0; i<=nvtxs; i++) - xadj[i]--; - - for (i=0; i (b)) -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wempty-body" -#endif -GK_MKPQUEUE(ipq, ipq_t, ikv_t, idx_t, idx_t, ikvmalloc, IDX_MAX, key_gt) -GK_MKPQUEUE(rpq, rpq_t, rkv_t, real_t, idx_t, rkvmalloc, REAL_MAX, key_gt) -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif -#undef key_gt - -/*************************************************************************/ -/*! Random number generation routines */ -/*************************************************************************/ -GK_MKRANDOM(i, idx_t, idx_t) - -/*************************************************************************/ -/*! Utility routines */ -/*************************************************************************/ -GK_MKARRAY2CSR(i, idx_t) - -/*************************************************************************/ -/*! Sorting routines */ -/*************************************************************************/ -void isorti(size_t n, idx_t *base) -{ -#define i_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(idx_t, base, n, i_lt); -#undef i_lt -} - -void isortd(size_t n, idx_t *base) -{ -#define i_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(idx_t, base, n, i_gt); -#undef i_gt -} - -void rsorti(size_t n, real_t *base) -{ -#define r_lt(a, b) ((*a) < (*b)) - GK_MKQSORT(real_t, base, n, r_lt); -#undef r_lt -} - -void rsortd(size_t n, real_t *base) -{ -#define r_gt(a, b) ((*a) > (*b)) - GK_MKQSORT(real_t, base, n, r_gt); -#undef r_gt -} - -void ikvsorti(size_t n, ikv_t *base) -{ -#define ikey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(ikv_t, base, n, ikey_lt); -#undef ikey_lt -} - -/* Sorts based both on key and val */ -void ikvsortii(size_t n, ikv_t *base) -{ -#define ikeyval_lt(a, b) ((a)->key < (b)->key || ((a)->key == (b)->key && (a)->val < (b)->val)) - GK_MKQSORT(ikv_t, base, n, ikeyval_lt); -#undef ikeyval_lt -} - -void ikvsortd(size_t n, ikv_t *base) -{ -#define ikey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(ikv_t, base, n, ikey_gt); -#undef ikey_gt -} - -void rkvsorti(size_t n, rkv_t *base) -{ -#define rkey_lt(a, b) ((a)->key < (b)->key) - GK_MKQSORT(rkv_t, base, n, rkey_lt); -#undef rkey_lt -} - -void rkvsortd(size_t n, rkv_t *base) -{ -#define rkey_gt(a, b) ((a)->key > (b)->key) - GK_MKQSORT(rkv_t, base, n, rkey_gt); -#undef rkey_gt -} - -void uvwsorti(size_t n, uvw_t *base) -{ -#define uvwkey_lt(a, b) ((a)->u < (b)->u || ((a)->u == (b)->u && (a)->v < (b)->v)) - GK_MKQSORT(uvw_t, base, n, uvwkey_lt); -#undef uvwkey_lt -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/gklib_defs.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/gklib_defs.h deleted file mode 100644 index dfac5ca674c..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/gklib_defs.h +++ /dev/null @@ -1,53 +0,0 @@ -/*! -\file -\brief Data structures and prototypes for GKlib integration - -\date Started 12/23/2008 -\author George -\version\verbatim $Id: gklib_defs.h 10395 2011-06-23 23:28:06Z karypis $ \endverbatim -*/ - -#ifndef _LIBMETIS_GKLIB_H_ -#define _LIBMETIS_GKLIB_H_ - -#include "gklib_rename.h" - -/*************************************************************************/ -/*! Stores a weighted edge */ -/*************************************************************************/ -typedef struct { - idx_t u, v, w; /*!< Edge (u,v) with weight w */ -} uvw_t; - -/************************************************************************* -* Define various data structure using GKlib's templates. -**************************************************************************/ -GK_MKKEYVALUE_T(ikv_t, idx_t, idx_t) -GK_MKKEYVALUE_T(rkv_t, real_t, idx_t) -GK_MKPQUEUE_T(ipq_t, ikv_t) -GK_MKPQUEUE_T(rpq_t, rkv_t) - - -/* gklib.c */ -GK_MKBLAS_PROTO(i, idx_t, idx_t) -GK_MKBLAS_PROTO(r, real_t, real_t) -GK_MKALLOC_PROTO(i, idx_t) -GK_MKALLOC_PROTO(r, real_t) -GK_MKALLOC_PROTO(ikv, ikv_t) -GK_MKALLOC_PROTO(rkv, rkv_t) -GK_MKPQUEUE_PROTO(ipq, ipq_t, idx_t, idx_t) -GK_MKPQUEUE_PROTO(rpq, rpq_t, real_t, idx_t) -GK_MKRANDOM_PROTO(i, idx_t, idx_t) -GK_MKARRAY2CSR_PROTO(i, idx_t) -void isorti(size_t n, idx_t *base); -void isortd(size_t n, idx_t *base); -void rsorti(size_t n, real_t *base); -void rsortd(size_t n, real_t *base); -void ikvsorti(size_t n, ikv_t *base); -void ikvsortii(size_t n, ikv_t *base); -void ikvsortd(size_t n, ikv_t *base); -void rkvsorti(size_t n, rkv_t *base); -void rkvsortd(size_t n, rkv_t *base); -void uvwsorti(size_t n, uvw_t *base); - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/gklib_rename.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/gklib_rename.h deleted file mode 100644 index 78dc8b39e9d..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/gklib_rename.h +++ /dev/null @@ -1,122 +0,0 @@ -/*! -\file - - * Copyright 1997, Regents of the University of Minnesota - * - * This file contains header files - * - * Started 10/2/97 - * George - * - * $Id: gklib_rename.h 10395 2011-06-23 23:28:06Z karypis $ - * - */ - - -#ifndef _LIBMETIS_GKLIB_RENAME_H_ -#define _LIBMETIS_GKLIB_RENAME_H_ - -/* gklib.c - generated from the .o files using the ./utils/listundescapedsumbols.csh */ -#define iAllocMatrix libmetis__iAllocMatrix -#define iFreeMatrix libmetis__iFreeMatrix -#define iSetMatrix libmetis__iSetMatrix -#define iargmax libmetis__iargmax -#define iargmax_n libmetis__iargmax_n -#define iargmin libmetis__iargmin -#define iarray2csr libmetis__iarray2csr -#define iaxpy libmetis__iaxpy -#define icopy libmetis__icopy -#define idot libmetis__idot -#define iincset libmetis__iincset -#define ikvAllocMatrix libmetis__ikvAllocMatrix -#define ikvFreeMatrix libmetis__ikvFreeMatrix -#define ikvSetMatrix libmetis__ikvSetMatrix -#define ikvcopy libmetis__ikvcopy -#define ikvmalloc libmetis__ikvmalloc -#define ikvrealloc libmetis__ikvrealloc -#define ikvset libmetis__ikvset -#define ikvsmalloc libmetis__ikvsmalloc -#define ikvsortd libmetis__ikvsortd -#define ikvsorti libmetis__ikvsorti -#define ikvsortii libmetis__ikvsortii -#define imalloc libmetis__imalloc -#define imax libmetis__imax -#define imin libmetis__imin -#define inorm2 libmetis__inorm2 -#define ipqCheckHeap libmetis__ipqCheckHeap -#define ipqCreate libmetis__ipqCreate -#define ipqDelete libmetis__ipqDelete -#define ipqDestroy libmetis__ipqDestroy -#define ipqFree libmetis__ipqFree -#define ipqGetTop libmetis__ipqGetTop -#define ipqInit libmetis__ipqInit -#define ipqInsert libmetis__ipqInsert -#define ipqLength libmetis__ipqLength -#define ipqReset libmetis__ipqReset -#define ipqSeeKey libmetis__ipqSeeKey -#define ipqSeeTopKey libmetis__ipqSeeTopKey -#define ipqSeeTopVal libmetis__ipqSeeTopVal -#define ipqUpdate libmetis__ipqUpdate -#define isrand libmetis__isrand -#define irand libmetis__irand -#define irandArrayPermute libmetis__irandArrayPermute -#define irandArrayPermuteFine libmetis__irandArrayPermuteFine -#define irandInRange libmetis__irandInRange -#define irealloc libmetis__irealloc -#define iscale libmetis__iscale -#define iset libmetis__iset -#define ismalloc libmetis__ismalloc -#define isortd libmetis__isortd -#define isorti libmetis__isorti -#define isrand libmetis__isrand -#define isum libmetis__isum -#define rAllocMatrix libmetis__rAllocMatrix -#define rFreeMatrix libmetis__rFreeMatrix -#define rSetMatrix libmetis__rSetMatrix -#define rargmax libmetis__rargmax -#define rargmax_n libmetis__rargmax_n -#define rargmin libmetis__rargmin -#define raxpy libmetis__raxpy -#define rcopy libmetis__rcopy -#define rdot libmetis__rdot -#define rincset libmetis__rincset -#define rkvAllocMatrix libmetis__rkvAllocMatrix -#define rkvFreeMatrix libmetis__rkvFreeMatrix -#define rkvSetMatrix libmetis__rkvSetMatrix -#define rkvcopy libmetis__rkvcopy -#define rkvmalloc libmetis__rkvmalloc -#define rkvrealloc libmetis__rkvrealloc -#define rkvset libmetis__rkvset -#define rkvsmalloc libmetis__rkvsmalloc -#define rkvsortd libmetis__rkvsortd -#define rkvsorti libmetis__rkvsorti -#define rmalloc libmetis__rmalloc -#define rmax libmetis__rmax -#define rmin libmetis__rmin -#define rnorm2 libmetis__rnorm2 -#define rpqCheckHeap libmetis__rpqCheckHeap -#define rpqCreate libmetis__rpqCreate -#define rpqDelete libmetis__rpqDelete -#define rpqDestroy libmetis__rpqDestroy -#define rpqFree libmetis__rpqFree -#define rpqGetTop libmetis__rpqGetTop -#define rpqInit libmetis__rpqInit -#define rpqInsert libmetis__rpqInsert -#define rpqLength libmetis__rpqLength -#define rpqReset libmetis__rpqReset -#define rpqSeeKey libmetis__rpqSeeKey -#define rpqSeeTopKey libmetis__rpqSeeTopKey -#define rpqSeeTopVal libmetis__rpqSeeTopVal -#define rpqUpdate libmetis__rpqUpdate -#define rrealloc libmetis__rrealloc -#define rscale libmetis__rscale -#define rset libmetis__rset -#define rsmalloc libmetis__rsmalloc -#define rsortd libmetis__rsortd -#define rsorti libmetis__rsorti -#define rsum libmetis__rsum -#define uvwsorti libmetis__uvwsorti - -#endif - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/graph.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/graph.c deleted file mode 100644 index 37f7d09dc83..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/graph.c +++ /dev/null @@ -1,274 +0,0 @@ -/** -\file -\brief Functions that deal with setting up the graphs for METIS. - -\date Started 7/25/1997 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version\verbatim $Id: graph.c 10513 2011-07-07 22:06:03Z karypis $ \endverbatim -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function sets up the graph from the user input */ -/*************************************************************************/ -graph_t *SetupGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t ncon, idx_t *xadj, - idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt) -{ - idx_t i, j, k, sum; - real_t *nvwgt; - graph_t *graph; - - /* allocate the graph and fill in the fields */ - graph = CreateGraph(); - - graph->nvtxs = nvtxs; - graph->nedges = xadj[nvtxs]; - graph->ncon = ncon; - - graph->xadj = xadj; - graph->free_xadj = 0; - - graph->adjncy = adjncy; - graph->free_adjncy = 0; - - - /* setup the vertex weights */ - if (vwgt) { - graph->vwgt = vwgt; - graph->free_vwgt = 0; - } - else { - vwgt = graph->vwgt = ismalloc(ncon*nvtxs, 1, "SetupGraph: vwgt"); - } - - graph->tvwgt = imalloc(ncon, "SetupGraph: tvwgts"); - graph->invtvwgt = rmalloc(ncon, "SetupGraph: invtvwgts"); - for (i=0; itvwgt[i] = isum(nvtxs, vwgt+i, ncon); - graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1); - } - - - if (ctrl->objtype == METIS_OBJTYPE_VOL) { - /* Setup the vsize */ - if (vsize) { - graph->vsize = vsize; - graph->free_vsize = 0; - } - else { - vsize = graph->vsize = ismalloc(nvtxs, 1, "SetupGraph: vsize"); - } - - /* Allocate memory for edge weights and initialize them to the sum of the vsize */ - adjwgt = graph->adjwgt = imalloc(graph->nedges, "SetupGraph: adjwgt"); - for (i=0; iadjwgt = adjwgt; - graph->free_adjwgt = 0; - } - else { - adjwgt = graph->adjwgt = ismalloc(graph->nedges, 1, "SetupGraph: adjwgt"); - } - } - - - /* setup various derived info */ - SetupGraph_tvwgt(graph); - - if (ctrl->optype == METIS_OP_PMETIS || ctrl->optype == METIS_OP_OMETIS) - SetupGraph_label(graph); - - ASSERT(CheckGraph(graph, ctrl->numflag, 1)); - - return graph; -} - - -/*************************************************************************/ -/*! Set's up the tvwgt/invtvwgt info */ -/*************************************************************************/ -void SetupGraph_tvwgt(graph_t *graph) -{ - idx_t i; - - if (graph->tvwgt == NULL) - graph->tvwgt = imalloc(graph->ncon, "SetupGraph_tvwgt: tvwgt"); - if (graph->invtvwgt == NULL) - graph->invtvwgt = rmalloc(graph->ncon, "SetupGraph_tvwgt: invtvwgt"); - - for (i=0; incon; i++) { - graph->tvwgt[i] = isum(graph->nvtxs, graph->vwgt+i, graph->ncon); - graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1); - } -} - - -/*************************************************************************/ -/*! Set's up the label info */ -/*************************************************************************/ -void SetupGraph_label(graph_t *graph) -{ - idx_t i; - - if (graph->label == NULL) - graph->label = imalloc(graph->nvtxs, "SetupGraph_label: label"); - - for (i=0; invtxs; i++) - graph->label[i] = i; -} - - -/*************************************************************************/ -/*! Setup the various arrays for the splitted graph */ -/*************************************************************************/ -graph_t *SetupSplitGraph(graph_t *graph, idx_t snvtxs, idx_t snedges) -{ - graph_t *sgraph; - - sgraph = CreateGraph(); - - sgraph->nvtxs = snvtxs; - sgraph->nedges = snedges; - sgraph->ncon = graph->ncon; - - /* Allocate memory for the splitted graph */ - sgraph->xadj = imalloc(snvtxs+1, "SetupSplitGraph: xadj"); - sgraph->vwgt = imalloc(sgraph->ncon*snvtxs, "SetupSplitGraph: vwgt"); - sgraph->adjncy = imalloc(snedges, "SetupSplitGraph: adjncy"); - sgraph->adjwgt = imalloc(snedges, "SetupSplitGraph: adjwgt"); - sgraph->label = imalloc(snvtxs, "SetupSplitGraph: label"); - sgraph->tvwgt = imalloc(sgraph->ncon, "SetupSplitGraph: tvwgt"); - sgraph->invtvwgt = rmalloc(sgraph->ncon, "SetupSplitGraph: invtvwgt"); - - if (graph->vsize) - sgraph->vsize = imalloc(snvtxs, "SetupSplitGraph: vsize"); - - return sgraph; -} - - -/*************************************************************************/ -/*! This function creates and initializes a graph_t data structure */ -/*************************************************************************/ -graph_t *CreateGraph(void) -{ - graph_t *graph; - - graph = (graph_t *)gk_malloc(sizeof(graph_t), "CreateGraph: graph"); - - InitGraph(graph); - - return graph; -} - - -/*************************************************************************/ -/*! This function initializes a graph_t data structure */ -/*************************************************************************/ -void InitGraph(graph_t *graph) -{ - memset((void *)graph, 0, sizeof(graph_t)); - - /* graph size constants */ - graph->nvtxs = -1; - graph->nedges = -1; - graph->ncon = -1; - graph->mincut = -1; - graph->minvol = -1; - graph->nbnd = -1; - - /* memory for the graph structure */ - graph->xadj = NULL; - graph->vwgt = NULL; - graph->vsize = NULL; - graph->adjncy = NULL; - graph->adjwgt = NULL; - graph->label = NULL; - graph->cmap = NULL; - graph->tvwgt = NULL; - graph->invtvwgt = NULL; - - /* by default these are set to true, but the can be explicitly changed afterwards */ - graph->free_xadj = 1; - graph->free_vwgt = 1; - graph->free_vsize = 1; - graph->free_adjncy = 1; - graph->free_adjwgt = 1; - - - /* memory for the partition/refinement structure */ - graph->where = NULL; - graph->pwgts = NULL; - graph->id = NULL; - graph->ed = NULL; - graph->bndptr = NULL; - graph->bndind = NULL; - graph->nrinfo = NULL; - graph->ckrinfo = NULL; - graph->vkrinfo = NULL; - - /* linked-list structure */ - graph->coarser = NULL; - graph->finer = NULL; -} - - -/*************************************************************************/ -/*! This function frees the refinement/partition memory stored in a graph */ -/*************************************************************************/ -void FreeRData(graph_t *graph) -{ - - /* The following is for the -minconn and -contig to work properly in - the vol-refinement routines */ - if ((void *)graph->ckrinfo == (void *)graph->vkrinfo) - graph->ckrinfo = NULL; - - - /* free partition/refinement structure */ - gk_free((void **)&graph->where, &graph->pwgts, &graph->id, &graph->ed, - &graph->bndptr, &graph->bndind, &graph->nrinfo, &graph->ckrinfo, - &graph->vkrinfo, LTERM); -} - - -/*************************************************************************/ -/*! This function deallocates any memory stored in a graph */ -/*************************************************************************/ -void FreeGraph(graph_t **r_graph) -{ - graph_t *graph; - - graph = *r_graph; - - /* free graph structure */ - if (graph->free_xadj) - gk_free((void **)&graph->xadj, LTERM); - if (graph->free_vwgt) - gk_free((void **)&graph->vwgt, LTERM); - if (graph->free_vsize) - gk_free((void **)&graph->vsize, LTERM); - if (graph->free_adjncy) - gk_free((void **)&graph->adjncy, LTERM); - if (graph->free_adjwgt) - gk_free((void **)&graph->adjwgt, LTERM); - - /* free partition/refinement structure */ - FreeRData(graph); - - gk_free((void **)&graph->tvwgt, &graph->invtvwgt, &graph->label, - &graph->cmap, &graph, LTERM); - - *r_graph = NULL; -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/initpart.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/initpart.c deleted file mode 100644 index 2f6c81b7288..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/initpart.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * initpart.c - * - * This file contains code that performs the initial partition of the - * coarsest graph - * - * Started 7/23/97 - * George - * - */ - -#include "metislib.h" - -/*************************************************************************/ -/*! This function computes the initial bisection of the coarsest graph */ -/*************************************************************************/ -void Init2WayPartition(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - mdbglvl_et dbglvl; - - ASSERT(graph->tvwgt[0] >= 0); - - dbglvl = ctrl->dbglvl; - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE); - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr)); - - switch (ctrl->iptype) { - case METIS_IPTYPE_RANDOM: - if (graph->ncon == 1) - RandomBisection(ctrl, graph, ntpwgts, niparts); - else - McRandomBisection(ctrl, graph, ntpwgts, niparts); - break; - - case METIS_IPTYPE_GROW: - if (graph->nedges == 0) - if (graph->ncon == 1) - RandomBisection(ctrl, graph, ntpwgts, niparts); - else - McRandomBisection(ctrl, graph, ntpwgts, niparts); - else - if (graph->ncon == 1) - GrowBisection(ctrl, graph, ntpwgts, niparts); - else - McGrowBisection(ctrl, graph, ntpwgts, niparts); - break; - - default: - gk_errexit(SIGERR, "Unknown initial partition type: %d\n", ctrl->iptype); - } - - IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Cut: %"PRIDX"\n", graph->mincut)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr)); - ctrl->dbglvl = dbglvl; - -} - - -/*************************************************************************/ -/*! This function computes the initial separator of the coarsest graph */ -/*************************************************************************/ -void InitSeparator(ctrl_t *ctrl, graph_t *graph, idx_t niparts) -{ - real_t ntpwgts[2] = {0.5, 0.5}; - mdbglvl_et dbglvl; - - dbglvl = ctrl->dbglvl; - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE); - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr)); - - /* this is required for the cut-based part of the refinement */ - Setup2WayBalMultipliers(ctrl, graph, ntpwgts); - - switch (ctrl->iptype) { - case METIS_IPTYPE_EDGE: - if (graph->nedges == 0) - RandomBisection(ctrl, graph, ntpwgts, niparts); - else - GrowBisection(ctrl, graph, ntpwgts, niparts); - - Compute2WayPartitionParams(ctrl, graph); - ConstructSeparator(ctrl, graph); - break; - - case METIS_IPTYPE_NODE: - GrowBisectionNode(ctrl, graph, ntpwgts, niparts); - break; - - default: - gk_errexit(SIGERR, "Unkown iptype of %"PRIDX"\n", ctrl->iptype); - } - - IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Sep: %"PRIDX"\n", graph->mincut)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr)); - - ctrl->dbglvl = dbglvl; - -} - - -/*************************************************************************/ -/*! This function computes a bisection of a graph by randomly assigning - the vertices followed by a bisection refinement. - The resulting partition is returned in graph->where. -*/ -/*************************************************************************/ -void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - idx_t i, ii, j, k, nvtxs, pwgts[2], zeromaxpwgt, from, me, - bestcut=0, icut, mincut, inbfs; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where; - idx_t *perm, *bestwhere; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - Allocate2WayPartitionMemory(ctrl, graph); - where = graph->where; - - bestwhere = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - - zeromaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[0]; - - for (inbfs=0; inbfs 0) { - irandArrayPermute(nvtxs, perm, nvtxs/2, 1); - pwgts[1] = graph->tvwgt[0]; - pwgts[0] = 0; - - for (ii=0; ii zeromaxpwgt) - break; - } - } - } - - /* Do some partition refinement */ - Compute2WayPartitionParams(ctrl, graph); - /* printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */ - - Balance2Way(ctrl, graph, ntpwgts); - /* printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */ - - FM_2WayRefine(ctrl, graph, ntpwgts, 4); - /* printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */ - - if (inbfs==0 || bestcut > graph->mincut) { - bestcut = graph->mincut; - icopy(nvtxs, where, bestwhere); - if (bestcut == 0) - break; - } - } - - graph->mincut = bestcut; - icopy(nvtxs, bestwhere, where); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function takes a graph and produces a bisection by using a region - growing algorithm. The resulting bisection is refined using FM. - The resulting partition is returned in graph->where. -*/ -/*************************************************************************/ -void GrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - idx_t i, j, k, nvtxs, drain, nleft, first, last, - pwgts[2], oneminpwgt, onemaxpwgt, - from, me, bestcut=0, icut, mincut, inbfs; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where; - idx_t *queue, *touched, *gain, *bestwhere; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - Allocate2WayPartitionMemory(ctrl, graph); - where = graph->where; - - bestwhere = iwspacemalloc(ctrl, nvtxs); - queue = iwspacemalloc(ctrl, nvtxs); - touched = iwspacemalloc(ctrl, nvtxs); - - onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[1]; - oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*ntpwgts[1]; - - for (inbfs=0; inbfstvwgt[0]; - pwgts[0] = 0; - - - queue[0] = irandInRange(nvtxs); - touched[queue[0]] = 1; - first = 0; - last = 1; - nleft = nvtxs-1; - drain = 0; - - /* Start the BFS from queue to get a partition */ - for (;;) { - if (first == last) { /* Empty. Disconnected graph! */ - if (nleft == 0 || drain) - break; - - k = irandInRange(nleft); - for (i=0; i 0 && pwgts[1]-vwgt[i] < oneminpwgt) { - drain = 1; - continue; - } - - where[i] = 0; - INC_DEC(pwgts[0], pwgts[1], vwgt[i]); - if (pwgts[1] <= onemaxpwgt) - break; - - drain = 0; - for (j=xadj[i]; jnvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); - */ - - Balance2Way(ctrl, graph, ntpwgts); - /* - printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], - graph->pwgts[1], graph->mincut); - */ - - FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); - /* - printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], - graph->pwgts[1], graph->mincut); - */ - - if (inbfs == 0 || bestcut > graph->mincut) { - bestcut = graph->mincut; - icopy(nvtxs, where, bestwhere); - if (bestcut == 0) - break; - } - } - - graph->mincut = bestcut; - icopy(nvtxs, bestwhere, where); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function takes a multi-constraint graph and computes a bisection - by randomly assigning the vertices and then refining it. The resulting - partition is returned in graph->where. -*/ -/**************************************************************************/ -void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum; - idx_t *bestwhere, *where, *perm, *counts; - idx_t *vwgt; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - vwgt = graph->vwgt; - - Allocate2WayPartitionMemory(ctrl, graph); - where = graph->where; - - bestwhere = iwspacemalloc(ctrl, nvtxs); - perm = iwspacemalloc(ctrl, nvtxs); - counts = iwspacemalloc(ctrl, ncon); - - for (inbfs=0; inbfs<2*niparts; inbfs++) { - irandArrayPermute(nvtxs, perm, nvtxs/2, 1); - iset(ncon, 0, counts); - - /* partition by spliting the queues randomly */ - for (ii=0; iiniter); - Balance2Way(ctrl, graph, ntpwgts); - FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); - Balance2Way(ctrl, graph, ntpwgts); - FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); - - if (inbfs == 0 || bestcut >= graph->mincut) { - bestcut = graph->mincut; - icopy(nvtxs, where, bestwhere); - if (bestcut == 0) - break; - } - } - - graph->mincut = bestcut; - icopy(nvtxs, bestwhere, where); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function takes a multi-constraint graph and produces a bisection - by using a region growing algorithm. The resulting partition is - returned in graph->where. -*/ -/*************************************************************************/ -void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs; - idx_t *bestwhere, *where; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - - Allocate2WayPartitionMemory(ctrl, graph); - where = graph->where; - - bestwhere = iwspacemalloc(ctrl, nvtxs); - - for (inbfs=0; inbfs<2*niparts; inbfs++) { - iset(nvtxs, 1, where); - where[irandInRange(nvtxs)] = 0; - - Compute2WayPartitionParams(ctrl, graph); - - Balance2Way(ctrl, graph, ntpwgts); - FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); - Balance2Way(ctrl, graph, ntpwgts); - FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); - - if (inbfs == 0 || bestcut >= graph->mincut) { - bestcut = graph->mincut; - icopy(nvtxs, where, bestwhere); - if (bestcut == 0) - break; - } - } - - graph->mincut = bestcut; - icopy(nvtxs, bestwhere, where); - - WCOREPOP; -} - - -/*************************************************************************/ -/* This function takes a graph and produces a tri-section into left, right, - and separator using a region growing algorithm. The resulting separator - is refined using node FM. - The resulting partition is returned in graph->where. -*/ -/**************************************************************************/ -void GrowBisectionNode(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt, - onemaxpwgt, from, me, bestcut=0, icut, mincut, inbfs; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *bndind; - idx_t *queue, *touched, *gain, *bestwhere; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - bestwhere = iwspacemalloc(ctrl, nvtxs); - queue = iwspacemalloc(ctrl, nvtxs); - touched = iwspacemalloc(ctrl, nvtxs); - - onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*0.5; - oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*0.5; - - - /* Allocate refinement memory. Allocate sufficient memory for both edge and node */ - graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts"); - graph->where = imalloc(nvtxs, "GrowBisectionNode: where"); - graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr"); - graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind"); - graph->id = imalloc(nvtxs, "GrowBisectionNode: id"); - graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed"); - graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo"); - - where = graph->where; - bndind = graph->bndind; - - for (inbfs=0; inbfstvwgt[0]; - pwgts[0] = 0; - - queue[0] = irandInRange(nvtxs); - touched[queue[0]] = 1; - first = 0; last = 1; - nleft = nvtxs-1; - drain = 0; - - /* Start the BFS from queue to get a partition */ - for (;;) { - if (first == last) { /* Empty. Disconnected graph! */ - if (nleft == 0 || drain) - break; - - k = irandInRange(nleft); - for (i=0; inbnd; i++) { - j = bndind[i]; - if (xadj[j+1]-xadj[j] > 0) /* ignore islands */ - where[j] = 2; - } - - Compute2WayNodePartitionParams(ctrl, graph); - FM_2WayNodeRefine2Sided(ctrl, graph, 1); - FM_2WayNodeRefine1Sided(ctrl, graph, 4); - - /* - printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n", - inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); - */ - - if (inbfs == 0 || bestcut > graph->mincut) { - bestcut = graph->mincut; - icopy(nvtxs, where, bestwhere); - } - } - - graph->mincut = bestcut; - icopy(nvtxs, bestwhere, where); - - WCOREPOP; -} - - -/*************************************************************************/ -/* This function takes a graph and produces a tri-section into left, right, - and separator using a region growing algorithm. The resulting separator - is refined using node FM. - The resulting partition is returned in graph->where. -*/ -/**************************************************************************/ -void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - idx_t niparts) -{ - idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs; - idx_t *xadj, *where, *bndind, *bestwhere; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - - /* Allocate refinement memory. Allocate sufficient memory for both edge and node */ - graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts"); - graph->where = imalloc(nvtxs, "GrowBisectionNode: where"); - graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr"); - graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind"); - graph->id = imalloc(nvtxs, "GrowBisectionNode: id"); - graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed"); - graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo"); - - bestwhere = iwspacemalloc(ctrl, nvtxs); - - where = graph->where; - bndind = graph->bndind; - - for (inbfs=0; inbfs 0) - where[irandInRange(nvtxs)] = 0; - - Compute2WayPartitionParams(ctrl, graph); - General2WayBalance(ctrl, graph, ntpwgts); - FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); - - /* Construct and refine the vertex separator */ - for (i=0; inbnd; i++) { - j = bndind[i]; - if (xadj[j+1]-xadj[j] > 0) /* ignore islands */ - where[j] = 2; - } - - Compute2WayNodePartitionParams(ctrl, graph); - FM_2WayNodeRefine2Sided(ctrl, graph, 4); - - /* - printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n", - inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); - */ - - if (inbfs == 0 || bestcut > graph->mincut) { - bestcut = graph->mincut; - icopy(nvtxs, where, bestwhere); - } - } - - graph->mincut = bestcut; - icopy(nvtxs, bestwhere, where); - - WCOREPOP; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kmetis.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kmetis.c deleted file mode 100644 index cb6d1afb3d5..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kmetis.c +++ /dev/null @@ -1,243 +0,0 @@ -/*! -\file -\brief The top-level routines for multilevel k-way partitioning that minimizes - the edge cut. - -\date Started 7/28/1997 -\author George -\author Copyright 1997-2011, Regents of the University of Minnesota -\version\verbatim $Id: kmetis.c 13905 2013-03-25 13:21:20Z karypis $ \endverbatim -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function is the entry point for MCKMETIS */ -/*************************************************************************/ -int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, - real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval, - idx_t *part) -{ - int sigrval=0, renumber=0; - graph_t *graph; - ctrl_t *ctrl; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - - /* set up the run parameters */ - ctrl = SetupCtrl(METIS_OP_KMETIS, options, *ncon, *nparts, tpwgts, ubvec); - if (!ctrl) { - gk_siguntrap(); - return METIS_ERROR_INPUT; - } - - /* if required, change the numbering to 0 */ - if (ctrl->numflag == 1) { - Change2CNumbering(*nvtxs, xadj, adjncy); - renumber = 1; - } - - /* set up the graph */ - graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt); - - /* set up multipliers for making balance computations easier */ - SetupKWayBalMultipliers(ctrl, graph); - - /* set various run parameters that depend on the graph */ - ctrl->CoarsenTo = gk_max((*nvtxs)/(20*gk_log2(*nparts)), 30*(*nparts)); - ctrl->nIparts = (ctrl->CoarsenTo == 30*(*nparts) ? 4 : 5); - - /* take care contiguity requests for disconnected graphs */ - if (ctrl->contig && !IsConnected(graph, 0)) - gk_errexit(SIGERR, "METIS Error: A contiguous partition is requested for a non-contiguous input graph.\n"); - - /* allocate workspace memory */ - AllocateWorkSpace(ctrl, graph); - - /* start the partitioning */ - IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); - - *objval = MlevelKWayPartitioning(ctrl, graph, part); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); - - /* clean up */ - FreeCtrl(&ctrl); - -SIGTHROW: - /* if required, change the numbering back to 1 */ - if (renumber) - Change2FNumbering(*nvtxs, xadj, adjncy, part); - - gk_siguntrap(); - gk_malloc_cleanup(0); - - return metis_rcode(sigrval); -} - - -/*************************************************************************/ -/*! This function computes a k-way partitioning of a graph that minimizes - the specified objective function. - - \param ctrl is the control structure - \param graph is the graph to be partitioned - \param part is the vector that on return will store the partitioning - - \returns the objective value of the partitoning. The partitioning - itself is stored in the part vector. -*/ -/*************************************************************************/ -idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part) -{ - idx_t i, j, objval=0, curobj=0, bestobj=0; - real_t curbal=0.0, bestbal=0.0; - graph_t *cgraph; - int status; - - - for (i=0; incuts; i++) { - cgraph = CoarsenGraph(ctrl, graph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr)); - AllocateKWayPartitionMemory(ctrl, cgraph); - - /* Release the work space */ - FreeWorkSpace(ctrl); - - /* Compute the initial partitioning */ - InitKWayPartitioning(ctrl, cgraph); - - /* Re-allocate the work space */ - AllocateWorkSpace(ctrl, graph); - AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr)); - IFSET(ctrl->dbglvl, METIS_DBG_IPART, - printf("Initial %"PRIDX"-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval)); - - RefineKWay(ctrl, graph, cgraph); - - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - curobj = graph->mincut; - break; - - case METIS_OBJTYPE_VOL: - curobj = graph->minvol; - break; - - default: - gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); - } - - curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors); - - if (i == 0 - || (curbal <= 0.0005 && bestobj > curobj) - || (bestbal > 0.0005 && curbal < bestbal)) { - icopy(graph->nvtxs, graph->where, part); - bestobj = curobj; - bestbal = curbal; - } - - FreeRData(graph); - - if (bestobj == 0) - break; - } - - FreeGraph(&graph); - - return bestobj; -} - - -/*************************************************************************/ -/*! This function computes the initial k-way partitioning using PMETIS -*/ -/*************************************************************************/ -void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ntrials, options[METIS_NOPTIONS], curobj=0, bestobj=0; - idx_t *bestwhere=NULL; - real_t *ubvec=NULL; - int status; - - METIS_SetDefaultOptions(options); - options[METIS_OPTION_NITER] = 10; - options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; - options[METIS_OPTION_NO2HOP] = ctrl->no2hop; - - - ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec"); - for (i=0; incon; i++) - ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts)); - - - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - case METIS_OBJTYPE_VOL: - options[METIS_OPTION_NCUTS] = ctrl->nIparts; - status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, - graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, - graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, - options, &curobj, graph->where); - - if (status != METIS_OK) - gk_errexit(SIGERR, "Failed during initial partitioning\n"); - - break; - -#ifdef XXX /* This does not seem to help */ - case METIS_OBJTYPE_VOL: - bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere"); - options[METIS_OPTION_NCUTS] = 2; - - ntrials = (ctrl->nIparts+1)/2; - for (i=0; invtxs, &graph->ncon, - graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, - graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, - options, &curobj, graph->where); - if (status != METIS_OK) - gk_errexit(SIGERR, "Failed during initial partitioning\n"); - - curobj = ComputeVolume(graph, graph->where); - - if (i == 0 || bestobj > curobj) { - bestobj = curobj; - if (i < ntrials-1) - icopy(graph->nvtxs, graph->where, bestwhere); - } - - if (bestobj == 0) - break; - } - if (bestobj != curobj) - icopy(graph->nvtxs, bestwhere, graph->where); - - break; -#endif - - default: - gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); - } - - gk_free((void **)&ubvec, &bestwhere, LTERM); - -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kwayfm.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kwayfm.c deleted file mode 100644 index dedfd39098c..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kwayfm.c +++ /dev/null @@ -1,1852 +0,0 @@ -/*! -\file -\brief Routines for k-way refinement - -\date Started 7/28/97 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version $Id: kwayfm.c 10567 2011-07-13 16:17:07Z karypis $ -*/ - -#include "metislib.h" - - - -/*************************************************************************/ -/* Top-level routine for k-way partitioning refinement. This routine just - calls the appropriate refinement routine based on the objectives and - constraints. */ -/*************************************************************************/ -void Greedy_KWayOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode) -{ - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - if (graph->ncon == 1) - Greedy_KWayCutOptimize(ctrl, graph, niter, ffactor, omode); - else - Greedy_McKWayCutOptimize(ctrl, graph, niter, ffactor, omode); - break; - - case METIS_OBJTYPE_VOL: - if (graph->ncon == 1) - Greedy_KWayVolOptimize(ctrl, graph, niter, ffactor, omode); - else - Greedy_McKWayVolOptimize(ctrl, graph, niter, ffactor, omode); - break; - - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } -} - - -/*************************************************************************/ -/*! K-way partitioning optimization in which the vertices are visited in - decreasing ed/sqrt(nnbrs)-id order. Note this is just an - approximation, as the ed is often split across different subdomains - and the sqrt(nnbrs) is just a crude approximation. - - \param graph is the graph that is being refined. - \param niter is the number of refinement iterations. - \param ffactor is the \em fudge-factor for allowing positive gain moves - to violate the max-pwgt constraint. - \param omode is the type of optimization that will performed among - OMODE_REFINE and OMODE_BALANCE - - -*/ -/**************************************************************************/ -void Greedy_KWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode) -{ - /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, nparts, gain; - idx_t from, me, to, oldcut, vwgt; - idx_t *xadj, *adjncy, *adjwgt; - idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts; - idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; - idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; - idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); - - /* Edgecut-specific/different variables */ - idx_t nbnd, oldnnbrs; - rpq_t *queue; - real_t rgain; - ckrinfo_t *myrinfo; - cnbr_t *mynbrs; - - WCOREPUSH; - - /* Link the graph fields */ - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - - where = graph->where; - pwgts = graph->pwgts; - - nparts = ctrl->nparts; - - /* Setup the weight intervals of the various subdomains */ - minwgt = iwspacemalloc(ctrl, nparts); - maxwgt = iwspacemalloc(ctrl, nparts); - itpwgts = iwspacemalloc(ctrl, nparts); - - for (i=0; itpwgts[i]*graph->tvwgt[0]; - maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0]; - minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]); - } - - perm = iwspacemalloc(ctrl, nvtxs); - - - /* This stores the valid target subdomains. It is used when ctrl->minconn to - control the subdomains to which moves are allowed to be made. - When ctrl->minconn is false, the default values of 2 allow all moves to - go through and it does not interfere with the zero-gain move selection. */ - safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); - - if (ctrl->minconn) { - ComputeSubDomainGraph(ctrl, graph); - - nads = ctrl->nads; - adids = ctrl->adids; - adwgts = ctrl->adwgts; - doms = iset(nparts, 0, ctrl->pvec1); - } - - - /* Setup updptr, updind like boundary info to keep track of the vertices whose - vstatus's need to be reset at the end of the inner iteration */ - vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); - updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - updind = iwspacemalloc(ctrl, nvtxs); - - if (ctrl->contig) { - /* The arrays that will be used for limited check of articulation points */ - bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - bfsind = iwspacemalloc(ctrl, nvtxs); - bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - } - - if (ctrl->dbglvl&METIS_DBG_REFINE) { - printf("%s: [%6"PRIDX" %6"PRIDX"]-[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"," - " Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %6"PRIDX, - (omode == OMODE_REFINE ? "GRC" : "GBC"), - pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), minwgt[0], maxwgt[0], - ComputeLoadImbalance(graph, nparts, ctrl->pijbm), - graph->nvtxs, graph->nbnd, graph->mincut); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - queue = rpqCreate(nvtxs); - - /*===================================================================== - * The top-level refinement loop - *======================================================================*/ - for (pass=0; passmincut); - - if (omode == OMODE_BALANCE) { - /* Check to see if things are out of balance, given the tolerance */ - for (i=0; i maxwgt[i]) - break; - } - if (i == nparts) /* Things are balanced. Return right away */ - break; - } - - oldcut = graph->mincut; - nbnd = graph->nbnd; - nupd = 0; - - if (ctrl->minconn) - maxndoms = imax(nparts, nads); - - /* Insert the boundary vertices in the priority queue */ - irandArrayPermute(nbnd, perm, nbnd/4, 1); - for (ii=0; iickrinfo[i].nnbrs > 0 ? - 1.0*graph->ckrinfo[i].ed/sqrt(graph->ckrinfo[i].nnbrs) : 0.0) - - graph->ckrinfo[i].id; - rpqInsert(queue, i, rgain); - vstatus[i] = VPQSTATUS_PRESENT; - ListInsert(nupd, updind, updptr, i); - } - - /* Start extracting vertices from the queue and try to move them */ - for (nmoved=0, iii=0;;iii++) { - if ((i = rpqGetTop(queue)) == -1) - break; - vstatus[i] = VPQSTATUS_EXTRACTED; - - myrinfo = graph->ckrinfo+i; - mynbrs = ctrl->cnbrpool + myrinfo->inbr; - - from = where[i]; - vwgt = graph->vwgt[i]; - - /* Prevent moves that make 'from' domain underbalanced */ - if (omode == OMODE_REFINE) { - if (myrinfo->id > 0 && pwgts[from]-vwgt < minwgt[from]) - continue; - } - else { /* OMODE_BALANCE */ - if (pwgts[from]-vwgt < minwgt[from]) - continue; - } - - if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) - continue; - - if (ctrl->minconn) - SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); - - /* Find the most promising subdomain to move to */ - if (omode == OMODE_REFINE) { - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - gain = mynbrs[k].ed-myrinfo->id; - if (gain >= 0 && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - gain = mynbrs[j].ed-myrinfo->id; - if ((mynbrs[j].ed > mynbrs[k].ed && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) - || - (mynbrs[j].ed == mynbrs[k].ed && - itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid])) - k = j; - } - - to = mynbrs[k].pid; - - gain = mynbrs[k].ed-myrinfo->id; - if (!(gain > 0 - || (gain == 0 - && (pwgts[from] >= maxwgt[from] - || itpwgts[to]*pwgts[from] > itpwgts[from]*(pwgts[to]+vwgt) - || (iii%2 == 0 && safetos[to] == 2) - ) - ) - ) - ) - continue; - } - else { /* OMODE_BALANCE */ - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - if (pwgts[to]+vwgt <= maxwgt[to] || - itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from]) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - if (itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]) - k = j; - } - - to = mynbrs[k].pid; - - if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] && - mynbrs[k].ed-myrinfo->id < 0) - continue; - } - - - - /*===================================================================== - * If we got here, we can now move the vertex from 'from' to 'to' - *======================================================================*/ - graph->mincut -= mynbrs[k].ed-myrinfo->id; - nmoved++; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("\t\tMoving %6"PRIDX" to %3"PRIDX". Gain: %4"PRIDX". Cut: %6"PRIDX"\n", - i, to, mynbrs[k].ed-myrinfo->id, graph->mincut)); - - /* Update the subdomain connectivity information */ - if (ctrl->minconn) { - /* take care of i's move itself */ - UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, &maxndoms); - - /* take care of the adjancent vertices */ - for (j=xadj[i]; jckrinfo+ii; - - oldnnbrs = myrinfo->nnbrs; - - UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, - from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, bndtype); - - UpdateQueueInfo(queue, vstatus, ii, me, from, to, myrinfo, oldnnbrs, - nupd, updptr, updind, bndtype); - - ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]); - } - } - - graph->nbnd = nbnd; - - /* Reset the vstatus and associated data structures */ - for (i=0; idbglvl&METIS_DBG_REFINE) { - printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." - " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, - pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), - ComputeLoadImbalance(graph, nparts, ctrl->pijbm), - graph->nbnd, nmoved, graph->mincut, ComputeVolume(graph, where)); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - if (nmoved == 0 || (omode == OMODE_REFINE && graph->mincut == oldcut)) - break; - } - - rpqDestroy(queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! K-way refinement that minimizes the communication volume. This is a - greedy routine and the vertices are visited in decreasing gv order. - - \param graph is the graph that is being refined. - \param niter is the number of refinement iterations. - \param ffactor is the \em fudge-factor for allowing positive gain moves - to violate the max-pwgt constraint. - -*/ -/**************************************************************************/ -void Greedy_KWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode) -{ - /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, nparts, gain; - idx_t from, me, to, oldcut, vwgt; - idx_t *xadj, *adjncy; - idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts; - idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; - idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; - idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); - - /* Volume-specific/different variables */ - ipq_t *queue; - idx_t oldvol, xgain; - idx_t *vmarker, *pmarker, *modind; - vkrinfo_t *myrinfo; - vnbr_t *mynbrs; - - WCOREPUSH; - - /* Link the graph fields */ - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - bndptr = graph->bndptr; - bndind = graph->bndind; - where = graph->where; - pwgts = graph->pwgts; - - nparts = ctrl->nparts; - - /* Setup the weight intervals of the various subdomains */ - minwgt = iwspacemalloc(ctrl, nparts); - maxwgt = iwspacemalloc(ctrl, nparts); - itpwgts = iwspacemalloc(ctrl, nparts); - - for (i=0; itpwgts[i]*graph->tvwgt[0]; - maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0]; - minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]); - } - - perm = iwspacemalloc(ctrl, nvtxs); - - - /* This stores the valid target subdomains. It is used when ctrl->minconn to - control the subdomains to which moves are allowed to be made. - When ctrl->minconn is false, the default values of 2 allow all moves to - go through and it does not interfere with the zero-gain move selection. */ - safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); - - if (ctrl->minconn) { - ComputeSubDomainGraph(ctrl, graph); - - nads = ctrl->nads; - adids = ctrl->adids; - adwgts = ctrl->adwgts; - doms = iset(nparts, 0, ctrl->pvec1); - } - - - /* Setup updptr, updind like boundary info to keep track of the vertices whose - vstatus's need to be reset at the end of the inner iteration */ - vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); - updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - updind = iwspacemalloc(ctrl, nvtxs); - - if (ctrl->contig) { - /* The arrays that will be used for limited check of articulation points */ - bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - bfsind = iwspacemalloc(ctrl, nvtxs); - bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - } - - /* Vol-refinement specific working arrays */ - modind = iwspacemalloc(ctrl, nvtxs); - vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); - - if (ctrl->dbglvl&METIS_DBG_REFINE) { - printf("%s: [%6"PRIDX" %6"PRIDX"]-[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL - ", Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %5"PRIDX", Vol: %5"PRIDX, - (omode == OMODE_REFINE ? "GRV" : "GBV"), - pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), minwgt[0], maxwgt[0], - ComputeLoadImbalance(graph, nparts, ctrl->pijbm), - graph->nvtxs, graph->nbnd, graph->mincut, graph->minvol); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - queue = ipqCreate(nvtxs); - - - /*===================================================================== - * The top-level refinement loop - *======================================================================*/ - for (pass=0; passminvol); - - if (omode == OMODE_BALANCE) { - /* Check to see if things are out of balance, given the tolerance */ - for (i=0; i maxwgt[i]) - break; - } - if (i == nparts) /* Things are balanced. Return right away */ - break; - } - - oldcut = graph->mincut; - oldvol = graph->minvol; - nupd = 0; - - if (ctrl->minconn) - maxndoms = imax(nparts, nads); - - /* Insert the boundary vertices in the priority queue */ - irandArrayPermute(graph->nbnd, perm, graph->nbnd/4, 1); - for (ii=0; iinbnd; ii++) { - i = bndind[perm[ii]]; - ipqInsert(queue, i, graph->vkrinfo[i].gv); - vstatus[i] = VPQSTATUS_PRESENT; - ListInsert(nupd, updind, updptr, i); - } - - /* Start extracting vertices from the queue and try to move them */ - for (nmoved=0, iii=0;;iii++) { - if ((i = ipqGetTop(queue)) == -1) - break; - vstatus[i] = VPQSTATUS_EXTRACTED; - - myrinfo = graph->vkrinfo+i; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - from = where[i]; - vwgt = graph->vwgt[i]; - - /* Prevent moves that make 'from' domain underbalanced */ - if (omode == OMODE_REFINE) { - if (myrinfo->nid > 0 && pwgts[from]-vwgt < minwgt[from]) - continue; - } - else { /* OMODE_BALANCE */ - if (pwgts[from]-vwgt < minwgt[from]) - continue; - } - - if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) - continue; - - if (ctrl->minconn) - SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); - - xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? graph->vsize[i] : 0); - - /* Find the most promising subdomain to move to */ - if (omode == OMODE_REFINE) { - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - gain = mynbrs[k].gv + xgain; - if (gain >= 0 && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - gain = mynbrs[j].gv + xgain; - if ((mynbrs[j].gv > mynbrs[k].gv && - pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) - || - (mynbrs[j].gv == mynbrs[k].gv && - mynbrs[j].ned > mynbrs[k].ned && - pwgts[to]+vwgt <= maxwgt[to]) - || - (mynbrs[j].gv == mynbrs[k].gv && - mynbrs[j].ned == mynbrs[k].ned && - itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]) - ) - k = j; - } - to = mynbrs[k].pid; - - ASSERT(xgain+mynbrs[k].gv >= 0); - - j = 0; - if (xgain+mynbrs[k].gv > 0 || mynbrs[k].ned-myrinfo->nid > 0) - j = 1; - else if (mynbrs[k].ned-myrinfo->nid == 0) { - if ((iii%2 == 0 && safetos[to] == 2) || - pwgts[from] >= maxwgt[from] || - itpwgts[from]*(pwgts[to]+vwgt) < itpwgts[to]*pwgts[from]) - j = 1; - } - if (j == 0) - continue; - } - else { /* OMODE_BALANCE */ - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - if (pwgts[to]+vwgt <= maxwgt[to] || - itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from]) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - if (itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]) - k = j; - } - to = mynbrs[k].pid; - - if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] && - (xgain+mynbrs[k].gv < 0 || - (xgain+mynbrs[k].gv == 0 && mynbrs[k].ned-myrinfo->nid < 0)) - ) - continue; - } - - - /*===================================================================== - * If we got here, we can now move the vertex from 'from' to 'to' - *======================================================================*/ - INC_DEC(pwgts[to], pwgts[from], vwgt); - graph->mincut -= mynbrs[k].ned-myrinfo->nid; - graph->minvol -= (xgain+mynbrs[k].gv); - where[i] = to; - nmoved++; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("\t\tMoving %6"PRIDX" from %3"PRIDX" to %3"PRIDX". " - "Gain: [%4"PRIDX" %4"PRIDX"]. Cut: %6"PRIDX", Vol: %6"PRIDX"\n", - i, from, to, xgain+mynbrs[k].gv, mynbrs[k].ned-myrinfo->nid, - graph->mincut, graph->minvol)); - - /* Update the subdomain connectivity information */ - if (ctrl->minconn) { - /* take care of i's move itself */ - UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->nid-mynbrs[k].ned, &maxndoms); - - /* take care of the adjancent vertices */ - for (j=xadj[i]; jdbglvl&METIS_DBG_REFINE) { - printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." - " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, - pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), - ComputeLoadImbalance(graph, nparts, ctrl->pijbm), - graph->nbnd, nmoved, graph->mincut, graph->minvol); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - if (nmoved == 0 || - (omode == OMODE_REFINE && graph->minvol == oldvol && graph->mincut == oldcut)) - break; - } - - ipqDestroy(queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! K-way partitioning optimization in which the vertices are visited in - decreasing ed/sqrt(nnbrs)-id order. Note this is just an - approximation, as the ed is often split across different subdomains - and the sqrt(nnbrs) is just a crude approximation. - - \param graph is the graph that is being refined. - \param niter is the number of refinement iterations. - \param ffactor is the \em fudge-factor for allowing positive gain moves - to violate the max-pwgt constraint. - \param omode is the type of optimization that will performed among - OMODE_REFINE and OMODE_BALANCE - - -*/ -/**************************************************************************/ -void Greedy_McKWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode) -{ - /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, ncon, nparts, gain; - idx_t from, me, to, cto, oldcut; - idx_t *xadj, *vwgt, *adjncy, *adjwgt; - idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt; - idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; - idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; - idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); - real_t *ubfactors, *pijbm; - real_t origbal; - - /* Edgecut-specific/different variables */ - idx_t nbnd, oldnnbrs; - rpq_t *queue; - real_t rgain; - ckrinfo_t *myrinfo; - cnbr_t *mynbrs; - - WCOREPUSH; - - /* Link the graph fields */ - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - - where = graph->where; - pwgts = graph->pwgts; - - nparts = ctrl->nparts; - pijbm = ctrl->pijbm; - - - /* Determine the ubfactors. The method used is different based on omode. - When OMODE_BALANCE, the ubfactors are those supplied by the user. - When OMODE_REFINE, the ubfactors are the max of the current partition - and the user-specified ones. */ - ubfactors = rwspacemalloc(ctrl, ncon); - ComputeLoadImbalanceVec(graph, nparts, pijbm, ubfactors); - origbal = rvecmaxdiff(ncon, ubfactors, ctrl->ubfactors); - if (omode == OMODE_BALANCE) { - rcopy(ncon, ctrl->ubfactors, ubfactors); - } - else { - for (i=0; i ctrl->ubfactors[i] ? ubfactors[i] : ctrl->ubfactors[i]); - } - - - /* Setup the weight intervals of the various subdomains */ - minwgt = iwspacemalloc(ctrl, nparts*ncon); - maxwgt = iwspacemalloc(ctrl, nparts*ncon); - - for (i=0; itpwgts[i*ncon+j]*graph->tvwgt[j]*ubfactors[j]; - /*minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*(.9/ubfactors[j]);*/ - minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*.2; - } - } - - perm = iwspacemalloc(ctrl, nvtxs); - - - /* This stores the valid target subdomains. It is used when ctrl->minconn to - control the subdomains to which moves are allowed to be made. - When ctrl->minconn is false, the default values of 2 allow all moves to - go through and it does not interfere with the zero-gain move selection. */ - safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); - - if (ctrl->minconn) { - ComputeSubDomainGraph(ctrl, graph); - - nads = ctrl->nads; - adids = ctrl->adids; - adwgts = ctrl->adwgts; - doms = iset(nparts, 0, ctrl->pvec1); - } - - - /* Setup updptr, updind like boundary info to keep track of the vertices whose - vstatus's need to be reset at the end of the inner iteration */ - vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); - updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - updind = iwspacemalloc(ctrl, nvtxs); - - if (ctrl->contig) { - /* The arrays that will be used for limited check of articulation points */ - bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - bfsind = iwspacemalloc(ctrl, nvtxs); - bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - } - - if (ctrl->dbglvl&METIS_DBG_REFINE) { - printf("%s: [%6"PRIDX" %6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"(%.3"PRREAL")," - " Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %6"PRIDX", (%"PRIDX")", - (omode == OMODE_REFINE ? "GRC" : "GBC"), - imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), imax(nparts*ncon, maxwgt), - ComputeLoadImbalance(graph, nparts, pijbm), origbal, - graph->nvtxs, graph->nbnd, graph->mincut, niter); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - queue = rpqCreate(nvtxs); - - - /*===================================================================== - * The top-level refinement loop - *======================================================================*/ - for (pass=0; passmincut); - - /* In balancing mode, exit as soon as balance is reached */ - if (omode == OMODE_BALANCE && IsBalanced(ctrl, graph, 0)) - break; - - oldcut = graph->mincut; - nbnd = graph->nbnd; - nupd = 0; - - if (ctrl->minconn) - maxndoms = imax(nparts, nads); - - /* Insert the boundary vertices in the priority queue */ - irandArrayPermute(nbnd, perm, nbnd/4, 1); - for (ii=0; iickrinfo[i].nnbrs > 0 ? - 1.0*graph->ckrinfo[i].ed/sqrt(graph->ckrinfo[i].nnbrs) : 0.0) - - graph->ckrinfo[i].id; - rpqInsert(queue, i, rgain); - vstatus[i] = VPQSTATUS_PRESENT; - ListInsert(nupd, updind, updptr, i); - } - - /* Start extracting vertices from the queue and try to move them */ - for (nmoved=0, iii=0;;iii++) { - if ((i = rpqGetTop(queue)) == -1) - break; - vstatus[i] = VPQSTATUS_EXTRACTED; - - myrinfo = graph->ckrinfo+i; - mynbrs = ctrl->cnbrpool + myrinfo->inbr; - - from = where[i]; - - /* Prevent moves that make 'from' domain underbalanced */ - if (omode == OMODE_REFINE) { - if (myrinfo->id > 0 && - !ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) - continue; - } - else { /* OMODE_BALANCE */ - if (!ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) - continue; - } - - if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) - continue; - - if (ctrl->minconn) - SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); - - /* Find the most promising subdomain to move to */ - if (omode == OMODE_REFINE) { - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - gain = mynbrs[k].ed-myrinfo->id; - if (gain >= 0 && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - cto = to; - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - if ((mynbrs[j].ed > mynbrs[k].ed && - ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) - || - (mynbrs[j].ed == mynbrs[k].ed && - BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - 1, pwgts+cto*ncon, pijbm+cto*ncon, - 1, pwgts+to*ncon, pijbm+to*ncon))) { - k = j; - cto = to; - } - } - to = cto; - - gain = mynbrs[k].ed-myrinfo->id; - if (!(gain > 0 - || (gain == 0 - && (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - -1, pwgts+from*ncon, pijbm+from*ncon, - +1, pwgts+to*ncon, pijbm+to*ncon) - || (iii%2 == 0 && safetos[to] == 2) - ) - ) - ) - ) - continue; - } - else { /* OMODE_BALANCE */ - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - if (ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon) || - BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - -1, pwgts+from*ncon, pijbm+from*ncon, - +1, pwgts+to*ncon, pijbm+to*ncon)) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - cto = to; - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - if (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - 1, pwgts+cto*ncon, pijbm+cto*ncon, - 1, pwgts+to*ncon, pijbm+to*ncon)) { - k = j; - cto = to; - } - } - to = cto; - - if (mynbrs[k].ed-myrinfo->id < 0 && - !BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - -1, pwgts+from*ncon, pijbm+from*ncon, - +1, pwgts+to*ncon, pijbm+to*ncon)) - continue; - } - - - - /*===================================================================== - * If we got here, we can now move the vertex from 'from' to 'to' - *======================================================================*/ - graph->mincut -= mynbrs[k].ed-myrinfo->id; - nmoved++; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("\t\tMoving %6"PRIDX" to %3"PRIDX". Gain: %4"PRIDX". Cut: %6"PRIDX"\n", - i, to, mynbrs[k].ed-myrinfo->id, graph->mincut)); - - /* Update the subdomain connectivity information */ - if (ctrl->minconn) { - /* take care of i's move itself */ - UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, &maxndoms); - - /* take care of the adjancent vertices */ - for (j=xadj[i]; jckrinfo+ii; - - oldnnbrs = myrinfo->nnbrs; - - UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, - from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, bndtype); - - UpdateQueueInfo(queue, vstatus, ii, me, from, to, myrinfo, oldnnbrs, - nupd, updptr, updind, bndtype); - - ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]); - } - } - - graph->nbnd = nbnd; - - /* Reset the vstatus and associated data structures */ - for (i=0; idbglvl&METIS_DBG_REFINE) { - printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." - " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, - imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), - ComputeLoadImbalance(graph, nparts, pijbm), - graph->nbnd, nmoved, graph->mincut, ComputeVolume(graph, where)); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - if (nmoved == 0 || (omode == OMODE_REFINE && graph->mincut == oldcut)) - break; - } - - rpqDestroy(queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! K-way refinement that minimizes the communication volume. This is a - greedy routine and the vertices are visited in decreasing gv order. - - \param graph is the graph that is being refined. - \param niter is the number of refinement iterations. - \param ffactor is the \em fudge-factor for allowing positive gain moves - to violate the max-pwgt constraint. - -*/ -/**************************************************************************/ -void Greedy_McKWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode) -{ - /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, ncon, nparts, gain; - idx_t from, me, to, cto, oldcut; - idx_t *xadj, *vwgt, *adjncy; - idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt; - idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; - idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; - idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); - real_t *ubfactors, *pijbm; - real_t origbal; - - /* Volume-specific/different variables */ - ipq_t *queue; - idx_t oldvol, xgain; - idx_t *vmarker, *pmarker, *modind; - vkrinfo_t *myrinfo; - vnbr_t *mynbrs; - - WCOREPUSH; - - /* Link the graph fields */ - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - bndptr = graph->bndptr; - bndind = graph->bndind; - where = graph->where; - pwgts = graph->pwgts; - - nparts = ctrl->nparts; - pijbm = ctrl->pijbm; - - - /* Determine the ubfactors. The method used is different based on omode. - When OMODE_BALANCE, the ubfactors are those supplied by the user. - When OMODE_REFINE, the ubfactors are the max of the current partition - and the user-specified ones. */ - ubfactors = rwspacemalloc(ctrl, ncon); - ComputeLoadImbalanceVec(graph, nparts, pijbm, ubfactors); - origbal = rvecmaxdiff(ncon, ubfactors, ctrl->ubfactors); - if (omode == OMODE_BALANCE) { - rcopy(ncon, ctrl->ubfactors, ubfactors); - } - else { - for (i=0; i ctrl->ubfactors[i] ? ubfactors[i] : ctrl->ubfactors[i]); - } - - - /* Setup the weight intervals of the various subdomains */ - minwgt = iwspacemalloc(ctrl, nparts*ncon); - maxwgt = iwspacemalloc(ctrl, nparts*ncon); - - for (i=0; itpwgts[i*ncon+j]*graph->tvwgt[j]*ubfactors[j]; - /*minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*(.9/ubfactors[j]); */ - minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*.2; - } - } - - perm = iwspacemalloc(ctrl, nvtxs); - - - /* This stores the valid target subdomains. It is used when ctrl->minconn to - control the subdomains to which moves are allowed to be made. - When ctrl->minconn is false, the default values of 2 allow all moves to - go through and it does not interfere with the zero-gain move selection. */ - safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); - - if (ctrl->minconn) { - ComputeSubDomainGraph(ctrl, graph); - - nads = ctrl->nads; - adids = ctrl->adids; - adwgts = ctrl->adwgts; - doms = iset(nparts, 0, ctrl->pvec1); - } - - - /* Setup updptr, updind like boundary info to keep track of the vertices whose - vstatus's need to be reset at the end of the inner iteration */ - vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); - updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - updind = iwspacemalloc(ctrl, nvtxs); - - if (ctrl->contig) { - /* The arrays that will be used for limited check of articulation points */ - bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - bfsind = iwspacemalloc(ctrl, nvtxs); - bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - } - - /* Vol-refinement specific working arrays */ - modind = iwspacemalloc(ctrl, nvtxs); - vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); - - if (ctrl->dbglvl&METIS_DBG_REFINE) { - printf("%s: [%6"PRIDX" %6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"(%.3"PRREAL")," - ", Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %5"PRIDX", Vol: %5"PRIDX", (%"PRIDX")", - (omode == OMODE_REFINE ? "GRV" : "GBV"), - imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), imax(nparts*ncon, maxwgt), - ComputeLoadImbalance(graph, nparts, pijbm), origbal, - graph->nvtxs, graph->nbnd, graph->mincut, graph->minvol, niter); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - queue = ipqCreate(nvtxs); - - - /*===================================================================== - * The top-level refinement loop - *======================================================================*/ - for (pass=0; passminvol); - - /* In balancing mode, exit as soon as balance is reached */ - if (omode == OMODE_BALANCE && IsBalanced(ctrl, graph, 0)) - break; - - oldcut = graph->mincut; - oldvol = graph->minvol; - nupd = 0; - - if (ctrl->minconn) - maxndoms = imax(nparts, nads); - - /* Insert the boundary vertices in the priority queue */ - irandArrayPermute(graph->nbnd, perm, graph->nbnd/4, 1); - for (ii=0; iinbnd; ii++) { - i = bndind[perm[ii]]; - ipqInsert(queue, i, graph->vkrinfo[i].gv); - vstatus[i] = VPQSTATUS_PRESENT; - ListInsert(nupd, updind, updptr, i); - } - - /* Start extracting vertices from the queue and try to move them */ - for (nmoved=0, iii=0;;iii++) { - if ((i = ipqGetTop(queue)) == -1) - break; - vstatus[i] = VPQSTATUS_EXTRACTED; - - myrinfo = graph->vkrinfo+i; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - from = where[i]; - - /* Prevent moves that make 'from' domain underbalanced */ - if (omode == OMODE_REFINE) { - if (myrinfo->nid > 0 && - !ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) - continue; - } - else { /* OMODE_BALANCE */ - if (!ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) - continue; - } - - if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) - continue; - - if (ctrl->minconn) - SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); - - xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? graph->vsize[i] : 0); - - /* Find the most promising subdomain to move to */ - if (omode == OMODE_REFINE) { - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - gain = mynbrs[k].gv + xgain; - if (gain >= 0 && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - cto = to; - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - gain = mynbrs[j].gv + xgain; - if ((mynbrs[j].gv > mynbrs[k].gv && - ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) - || - (mynbrs[j].gv == mynbrs[k].gv && - mynbrs[j].ned > mynbrs[k].ned && - ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) - || - (mynbrs[j].gv == mynbrs[k].gv && - mynbrs[j].ned == mynbrs[k].ned && - BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - 1, pwgts+cto*ncon, pijbm+cto*ncon, - 1, pwgts+to*ncon, pijbm+to*ncon))) { - k = j; - cto = to; - } - } - to = cto; - - j = 0; - if (xgain+mynbrs[k].gv > 0 || mynbrs[k].ned-myrinfo->nid > 0) - j = 1; - else if (mynbrs[k].ned-myrinfo->nid == 0) { - if ((iii%2 == 0 && safetos[to] == 2) || - BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - -1, pwgts+from*ncon, pijbm+from*ncon, - +1, pwgts+to*ncon, pijbm+to*ncon)) - j = 1; - } - if (j == 0) - continue; - } - else { /* OMODE_BALANCE */ - for (k=myrinfo->nnbrs-1; k>=0; k--) { - if (!safetos[to=mynbrs[k].pid]) - continue; - if (ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon) || - BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - -1, pwgts+from*ncon, pijbm+from*ncon, - +1, pwgts+to*ncon, pijbm+to*ncon)) - break; - } - if (k < 0) - continue; /* break out if you did not find a candidate */ - - cto = to; - for (j=k-1; j>=0; j--) { - if (!safetos[to=mynbrs[j].pid]) - continue; - if (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - 1, pwgts+cto*ncon, pijbm+cto*ncon, - 1, pwgts+to*ncon, pijbm+to*ncon)) { - k = j; - cto = to; - } - } - to = cto; - - if ((xgain+mynbrs[k].gv < 0 || - (xgain+mynbrs[k].gv == 0 && mynbrs[k].ned-myrinfo->nid < 0)) - && - !BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, - -1, pwgts+from*ncon, pijbm+from*ncon, - +1, pwgts+to*ncon, pijbm+to*ncon)) - continue; - } - - - /*===================================================================== - * If we got here, we can now move the vertex from 'from' to 'to' - *======================================================================*/ - graph->mincut -= mynbrs[k].ned-myrinfo->nid; - graph->minvol -= (xgain+mynbrs[k].gv); - where[i] = to; - nmoved++; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("\t\tMoving %6"PRIDX" from %3"PRIDX" to %3"PRIDX". " - "Gain: [%4"PRIDX" %4"PRIDX"]. Cut: %6"PRIDX", Vol: %6"PRIDX"\n", - i, from, to, xgain+mynbrs[k].gv, mynbrs[k].ned-myrinfo->nid, - graph->mincut, graph->minvol)); - - /* Update the subdomain connectivity information */ - if (ctrl->minconn) { - /* take care of i's move itself */ - UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->nid-mynbrs[k].ned, &maxndoms); - - /* take care of the adjancent vertices */ - for (j=xadj[i]; jdbglvl&METIS_DBG_REFINE) { - printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." - " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, - imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), - ComputeLoadImbalance(graph, nparts, pijbm), - graph->nbnd, nmoved, graph->mincut, graph->minvol); - if (ctrl->minconn) - printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); - printf("\n"); - } - - if (nmoved == 0 || - (omode == OMODE_REFINE && graph->minvol == oldvol && graph->mincut == oldcut)) - break; - } - - ipqDestroy(queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function performs an approximate articulation vertex test. - It assumes that the bfslvl, bfsind, and bfsmrk arrays are initialized - appropriately. */ -/*************************************************************************/ -idx_t IsArticulationNode(idx_t i, idx_t *xadj, idx_t *adjncy, idx_t *where, - idx_t *bfslvl, idx_t *bfsind, idx_t *bfsmrk) -{ - idx_t ii, j, k=0, head, tail, nhits, tnhits, from, BFSDEPTH=5; - - from = where[i]; - - /* Determine if the vertex is safe to move from a contiguity standpoint */ - for (tnhits=0, j=xadj[i]; jxadj; - adjncy = graph->adjncy; - vsize = graph->vsize; - where = graph->where; - - myrinfo = graph->vkrinfo+v; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - - /*====================================================================== - * Remove the contributions on the gain made by 'v'. - *=====================================================================*/ - for (k=0; knnbrs; k++) - pmarker[mynbrs[k].pid] = k; - pmarker[from] = k; - - myidx = pmarker[to]; /* Keep track of the index in mynbrs of the 'to' domain */ - - for (j=xadj[v]; jvkrinfo+ii; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - if (other == from) { - for (k=0; knnbrs; k++) { - if (pmarker[onbrs[k].pid] == -1) - onbrs[k].gv += vsize[v]; - } - } - else { - ASSERT(pmarker[other] != -1); - - if (mynbrs[pmarker[other]].ned > 1) { - for (k=0; knnbrs; k++) { - if (pmarker[onbrs[k].pid] == -1) - onbrs[k].gv += vsize[v]; - } - } - else { /* There is only one connection */ - for (k=0; knnbrs; k++) { - if (pmarker[onbrs[k].pid] != -1) - onbrs[k].gv -= vsize[v]; - } - } - } - } - - for (k=0; knnbrs; k++) - pmarker[mynbrs[k].pid] = -1; - pmarker[from] = -1; - - - /*====================================================================== - * Update the id/ed of vertex 'v' - *=====================================================================*/ - if (myidx == -1) { - myidx = myrinfo->nnbrs++; - ASSERT(myidx < xadj[v+1]-xadj[v]); - mynbrs[myidx].ned = 0; - } - myrinfo->ned += myrinfo->nid-mynbrs[myidx].ned; - SWAP(myrinfo->nid, mynbrs[myidx].ned, j); - if (mynbrs[myidx].ned == 0) - mynbrs[myidx] = mynbrs[--myrinfo->nnbrs]; - else - mynbrs[myidx].pid = from; - - - /*====================================================================== - * Update the degrees of adjacent vertices and their volume gains - *=====================================================================*/ - vmarker[v] = 1; - modind[0] = v; - nmod = 1; - for (j=xadj[v]; jvkrinfo+ii; - if (myrinfo->inbr == -1) - myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[ii+1]-xadj[ii]+1); - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - if (me == from) { - INC_DEC(myrinfo->ned, myrinfo->nid, 1); - } - else if (me == to) { - INC_DEC(myrinfo->nid, myrinfo->ned, 1); - } - - /* Remove the edgeweight from the 'pid == from' entry of the vertex */ - if (me != from) { - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == from) { - if (mynbrs[k].ned == 1) { - mynbrs[k] = mynbrs[--myrinfo->nnbrs]; - vmarker[ii] = 1; /* You do a complete .gv calculation */ - - /* All vertices adjacent to 'ii' need to be updated */ - for (jj=xadj[ii]; jjvkrinfo+u; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - for (kk=0; kknnbrs; kk++) { - if (onbrs[kk].pid == from) { - onbrs[kk].gv -= vsize[ii]; - if (!vmarker[u]) { /* Need to update boundary etc */ - vmarker[u] = 2; - modind[nmod++] = u; - } - break; - } - } - } - } - else { - mynbrs[k].ned--; - - /* Update the gv due to single 'ii' connection to 'from' */ - if (mynbrs[k].ned == 1) { - /* find the vertex 'u' that 'ii' was connected into 'from' */ - for (jj=xadj[ii]; jjvkrinfo+u; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - /* The following is correct because domains in common - between ii and u will lead to a reduction over the - previous gain, whereas domains only in u but not in - ii, will lead to no change as opposed to the earlier - increase */ - for (kk=0; kknnbrs; kk++) - onbrs[kk].gv += vsize[ii]; - - if (!vmarker[u]) { /* Need to update boundary etc */ - vmarker[u] = 2; - modind[nmod++] = u; - } - break; - } - } - } - } - break; - } - } - } - - - /* Add the edgeweight to the 'pid == to' entry of the vertex */ - if (me != to) { - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == to) { - mynbrs[k].ned++; - - /* Update the gv due to non-single 'ii' connection to 'to' */ - if (mynbrs[k].ned == 2) { - /* find the vertex 'u' that 'ii' was connected into 'to' */ - for (jj=xadj[ii]; jjvkrinfo+u; - onbrs = ctrl->vnbrpool + orinfo->inbr; - for (kk=0; kknnbrs; kk++) - onbrs[kk].gv -= vsize[ii]; - - if (!vmarker[u]) { /* Need to update boundary etc */ - vmarker[u] = 2; - modind[nmod++] = u; - } - break; - } - } - } - break; - } - } - - if (k == myrinfo->nnbrs) { - mynbrs[myrinfo->nnbrs].pid = to; - mynbrs[myrinfo->nnbrs++].ned = 1; - vmarker[ii] = 1; /* You do a complete .gv calculation */ - - /* All vertices adjacent to 'ii' need to be updated */ - for (jj=xadj[ii]; jjvkrinfo+u; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - for (kk=0; kknnbrs; kk++) { - if (onbrs[kk].pid == to) { - onbrs[kk].gv += vsize[ii]; - if (!vmarker[u]) { /* Need to update boundary etc */ - vmarker[u] = 2; - modind[nmod++] = u; - } - break; - } - } - } - } - } - - ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]); - } - - - /*====================================================================== - * Add the contributions on the volume gain due to 'v' - *=====================================================================*/ - myrinfo = graph->vkrinfo+v; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - for (k=0; knnbrs; k++) - pmarker[mynbrs[k].pid] = k; - pmarker[to] = k; - - for (j=xadj[v]; jvkrinfo+ii; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - if (other == to) { - for (k=0; knnbrs; k++) { - if (pmarker[onbrs[k].pid] == -1) - onbrs[k].gv -= vsize[v]; - } - } - else { - ASSERT(pmarker[other] != -1); - - if (mynbrs[pmarker[other]].ned > 1) { - for (k=0; knnbrs; k++) { - if (pmarker[onbrs[k].pid] == -1) - onbrs[k].gv -= vsize[v]; - } - } - else { /* There is only one connection */ - for (k=0; knnbrs; k++) { - if (pmarker[onbrs[k].pid] != -1) - onbrs[k].gv += vsize[v]; - } - } - } - } - for (k=0; knnbrs; k++) - pmarker[mynbrs[k].pid] = -1; - pmarker[to] = -1; - - - /*====================================================================== - * Recompute the volume information of the 'hard' nodes, and update the - * max volume gain for all the modified vertices and the priority queue - *=====================================================================*/ - for (iii=0; iiivkrinfo+i; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - if (vmarker[i] == 1) { /* Only complete gain updates go through */ - for (k=0; knnbrs; k++) - mynbrs[k].gv = 0; - - for (j=xadj[i]; jvkrinfo+ii; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - for (kk=0; kknnbrs; kk++) - pmarker[onbrs[kk].pid] = kk; - pmarker[other] = 1; - - if (me == other) { - /* Find which domains 'i' is connected and 'ii' is not and update their gain */ - for (k=0; knnbrs; k++) { - if (pmarker[mynbrs[k].pid] == -1) - mynbrs[k].gv -= vsize[ii]; - } - } - else { - ASSERT(pmarker[me] != -1); - - /* I'm the only connection of 'ii' in 'me' */ - if (onbrs[pmarker[me]].ned == 1) { - /* Increase the gains for all the common domains between 'i' and 'ii' */ - for (k=0; knnbrs; k++) { - if (pmarker[mynbrs[k].pid] != -1) - mynbrs[k].gv += vsize[ii]; - } - } - else { - /* Find which domains 'i' is connected and 'ii' is not and update their gain */ - for (k=0; knnbrs; k++) { - if (pmarker[mynbrs[k].pid] == -1) - mynbrs[k].gv -= vsize[ii]; - } - } - } - - for (kk=0; kknnbrs; kk++) - pmarker[onbrs[kk].pid] = -1; - pmarker[other] = -1; - - } - } - - /* Compute the overall gv for that node */ - myrinfo->gv = IDX_MIN; - for (k=0; knnbrs; k++) { - if (mynbrs[k].gv > myrinfo->gv) - myrinfo->gv = mynbrs[k].gv; - } - - /* Add the xtra gain due to id == 0 */ - if (myrinfo->ned > 0 && myrinfo->nid == 0) - myrinfo->gv += vsize[i]; - - - /*====================================================================== - * Maintain a consistent boundary - *=====================================================================*/ - if (bndtype == BNDTYPE_REFINE) { - if (myrinfo->gv >= 0 && graph->bndptr[i] == -1) - BNDInsert(graph->nbnd, graph->bndind, graph->bndptr, i); - - if (myrinfo->gv < 0 && graph->bndptr[i] != -1) - BNDDelete(graph->nbnd, graph->bndind, graph->bndptr, i); - } - else { - if (myrinfo->ned > 0 && graph->bndptr[i] == -1) - BNDInsert(graph->nbnd, graph->bndind, graph->bndptr, i); - - if (myrinfo->ned == 0 && graph->bndptr[i] != -1) - BNDDelete(graph->nbnd, graph->bndind, graph->bndptr, i); - } - - - /*====================================================================== - * Update the priority queue appropriately (if allowed) - *=====================================================================*/ - if (queue != NULL) { - if (vstatus[i] != VPQSTATUS_EXTRACTED) { - if (graph->bndptr[i] != -1) { /* In-boundary vertex */ - if (vstatus[i] == VPQSTATUS_PRESENT) { - ipqUpdate(queue, i, myrinfo->gv); - } - else { - ipqInsert(queue, i, myrinfo->gv); - vstatus[i] = VPQSTATUS_PRESENT; - ListInsert(*r_nupd, updind, updptr, i); - } - } - else { /* Off-boundary vertex */ - if (vstatus[i] == VPQSTATUS_PRESENT) { - ipqDelete(queue, i); - vstatus[i] = VPQSTATUS_NOTPRESENT; - ListDelete(*r_nupd, updind, updptr, i); - } - } - } - } - - vmarker[i] = 0; - } -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kwayrefine.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kwayrefine.c deleted file mode 100644 index 0e3c6dbd292..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/kwayrefine.c +++ /dev/null @@ -1,672 +0,0 @@ -/*! -\file -\brief Driving routines for multilevel k-way refinement - -\date Started 7/28/1997 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version $Id: kwayrefine.c 10737 2011-09-13 13:37:25Z karypis $ -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function is the entry point of cut-based refinement */ -/*************************************************************************/ -void RefineKWay(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph) -{ - idx_t i, nlevels, contig=ctrl->contig; - graph_t *ptr; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); - - /* Determine how many levels are there */ - for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++); - - /* Compute the parameters of the coarsest graph */ - ComputeKWayPartitionParams(ctrl, graph); - - /* Try to minimize the sub-domain connectivity */ - if (ctrl->minconn) - EliminateSubDomainEdges(ctrl, graph); - - /* Deal with contiguity constraints at the beginning */ - if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { - EliminateComponents(ctrl, graph); - - ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); - Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); - - ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); - Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); - - ctrl->contig = 0; - } - - /* Refine each successively finer graph */ - for (i=0; ;i++) { - if (ctrl->minconn && i == nlevels/2) - EliminateSubDomainEdges(ctrl, graph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); - - if (2*i >= nlevels && !IsBalanced(ctrl, graph, .02)) { - ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); - Greedy_KWayOptimize(ctrl, graph, 1, 0, OMODE_BALANCE); - ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); - } - - Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 5.0, OMODE_REFINE); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); - - /* Deal with contiguity constraints in the middle */ - if (contig && i == nlevels/2) { - if (FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { - EliminateComponents(ctrl, graph); - - if (!IsBalanced(ctrl, graph, .02)) { - ctrl->contig = 1; - ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); - Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); - - ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); - Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); - ctrl->contig = 0; - } - } - } - - if (graph == orggraph) - break; - - graph = graph->finer; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); - ASSERT(graph->vwgt != NULL); - - ProjectKWayPartition(ctrl, graph); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); - } - - /* Deal with contiguity requirement at the end */ - ctrl->contig = contig; - if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) - EliminateComponents(ctrl, graph); - - if (!IsBalanced(ctrl, graph, 0.0)) { - ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); - Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE); - - ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); - Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); - } - - if (ctrl->contig) - ASSERT(FindPartitionInducedComponents(graph, graph->where, NULL, NULL) == ctrl->nparts); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); -} - - -/*************************************************************************/ -/*! This function allocates memory for the k-way cut-based refinement */ -/*************************************************************************/ -void AllocateKWayPartitionMemory(ctrl_t *ctrl, graph_t *graph) -{ - - graph->pwgts = imalloc(ctrl->nparts*graph->ncon, "AllocateKWayPartitionMemory: pwgts"); - graph->where = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: where"); - graph->bndptr = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: bndptr"); - graph->bndind = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: bndind"); - - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - graph->ckrinfo = (ckrinfo_t *)gk_malloc(graph->nvtxs*sizeof(ckrinfo_t), - "AllocateKWayPartitionMemory: ckrinfo"); - break; - - case METIS_OBJTYPE_VOL: - graph->vkrinfo = (vkrinfo_t *)gk_malloc(graph->nvtxs*sizeof(vkrinfo_t), - "AllocateKWayVolPartitionMemory: vkrinfo"); - - /* This is to let the cut-based -minconn and -contig large-scale graph - changes to go through */ - graph->ckrinfo = (ckrinfo_t *)graph->vkrinfo; - break; - - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } - -} - - -/*************************************************************************/ -/*! This function computes the initial id/ed for cut-based partitioning */ -/**************************************************************************/ -void ComputeKWayPartitionParams(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, k, l, nvtxs, ncon, nparts, nbnd, mincut, me, other; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where, *bndind, *bndptr; - - nparts = ctrl->nparts; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - where = graph->where; - pwgts = iset(nparts*ncon, 0, graph->pwgts); - bndind = graph->bndind; - bndptr = iset(nvtxs, -1, graph->bndptr); - - nbnd = mincut = 0; - - /* Compute pwgts */ - if (ncon == 1) { - for (i=0; i= 0 && where[i] < nparts); - pwgts[where[i]] += vwgt[i]; - } - } - else { - for (i=0; iobjtype) { - case METIS_OBJTYPE_CUT: - { - ckrinfo_t *myrinfo; - cnbr_t *mynbrs; - - memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); - cnbrpoolReset(ctrl); - - for (i=0; ickrinfo+i; - - for (j=xadj[i]; jid += adjwgt[j]; - else - myrinfo->ed += adjwgt[j]; - } - - /* Time to compute the particular external degrees */ - if (myrinfo->ed > 0) { - mincut += myrinfo->ed; - - myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); - mynbrs = ctrl->cnbrpool + myrinfo->inbr; - - for (j=xadj[i]; jnnbrs; k++) { - if (mynbrs[k].pid == other) { - mynbrs[k].ed += adjwgt[j]; - break; - } - } - if (k == myrinfo->nnbrs) { - mynbrs[k].pid = other; - mynbrs[k].ed = adjwgt[j]; - myrinfo->nnbrs++; - } - } - } - - ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]); - - /* Only ed-id>=0 nodes are considered to be in the boundary */ - if (myrinfo->ed-myrinfo->id >= 0) - BNDInsert(nbnd, bndind, bndptr, i); - } - else { - myrinfo->inbr = -1; - } - } - - graph->mincut = mincut/2; - graph->nbnd = nbnd; - - } - ASSERT(CheckBnd2(graph)); - break; - - case METIS_OBJTYPE_VOL: - { - vkrinfo_t *myrinfo; - vnbr_t *mynbrs; - - memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); - vnbrpoolReset(ctrl); - - /* Compute now the id/ed degrees */ - for (i=0; ivkrinfo+i; - - for (j=xadj[i]; jnid++; - else - myrinfo->ned++; - } - - /* Time to compute the particular external degrees */ - if (myrinfo->ned > 0) { - mincut += myrinfo->ned; - - myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - for (j=xadj[i]; jnnbrs; k++) { - if (mynbrs[k].pid == other) { - mynbrs[k].ned++; - break; - } - } - if (k == myrinfo->nnbrs) { - mynbrs[k].gv = 0; - mynbrs[k].pid = other; - mynbrs[k].ned = 1; - myrinfo->nnbrs++; - } - } - } - ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]); - } - else { - myrinfo->inbr = -1; - } - } - graph->mincut = mincut/2; - - ComputeKWayVolGains(ctrl, graph); - } - ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); - break; - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } - -} - - -/*************************************************************************/ -/*! This function projects a partition, and at the same time computes the - parameters for refinement. */ -/*************************************************************************/ -void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, k, nvtxs, nbnd, nparts, me, other, istart, iend, tid, ted; - idx_t *xadj, *adjncy, *adjwgt; - idx_t *cmap, *where, *bndptr, *bndind, *cwhere, *htable; - graph_t *cgraph; - - WCOREPUSH; - - nparts = ctrl->nparts; - - cgraph = graph->coarser; - cwhere = cgraph->where; - - nvtxs = graph->nvtxs; - cmap = graph->cmap; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - AllocateKWayPartitionMemory(ctrl, graph); - - where = graph->where; - bndind = graph->bndind; - bndptr = iset(nvtxs, -1, graph->bndptr); - - htable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); - - /* Compute the required info for refinement */ - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - ASSERT(CheckBnd2(cgraph)); - { - ckrinfo_t *myrinfo; - cnbr_t *mynbrs; - - /* go through and project partition and compute id/ed for the nodes */ - for (i=0; ickrinfo[k].ed; /* For optimization */ - } - - memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); - cnbrpoolReset(ctrl); - - for (nbnd=0, i=0; ickrinfo+i; - - if (cmap[i] == 0) { /* Interior node. Note that cmap[i] = crinfo[cmap[i]].ed */ - for (tid=0, j=istart; jid = tid; - myrinfo->inbr = -1; - } - else { /* Potentially an interface node */ - myrinfo->inbr = cnbrpoolGetNext(ctrl, iend-istart+1); - mynbrs = ctrl->cnbrpool + myrinfo->inbr; - - me = where[i]; - for (tid=0, ted=0, j=istart; jnnbrs; - mynbrs[myrinfo->nnbrs].pid = other; - mynbrs[myrinfo->nnbrs++].ed = adjwgt[j]; - } - else { - mynbrs[k].ed += adjwgt[j]; - } - } - } - myrinfo->id = tid; - myrinfo->ed = ted; - - /* Remove space for edegrees if it was interior */ - if (ted == 0) { - ctrl->nbrpoolcpos -= iend-istart+1; - myrinfo->inbr = -1; - } - else { - if (ted-tid >= 0) - BNDInsert(nbnd, bndind, bndptr, i); - - for (j=0; jnnbrs; j++) - htable[mynbrs[j].pid] = -1; - } - } - } - - graph->nbnd = nbnd; - - } - ASSERT(CheckBnd2(graph)); - break; - - case METIS_OBJTYPE_VOL: - { - vkrinfo_t *myrinfo; - vnbr_t *mynbrs; - - ASSERT(cgraph->minvol == ComputeVolume(cgraph, cgraph->where)); - - /* go through and project partition and compute id/ed for the nodes */ - for (i=0; ivkrinfo[k].ned; /* For optimization */ - } - - memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); - vnbrpoolReset(ctrl); - - for (i=0; ivkrinfo+i; - - if (cmap[i] == 0) { /* Note that cmap[i] = crinfo[cmap[i]].ed */ - myrinfo->nid = iend-istart; - myrinfo->inbr = -1; - } - else { /* Potentially an interface node */ - myrinfo->inbr = vnbrpoolGetNext(ctrl, iend-istart+1); - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - me = where[i]; - for (tid=0, ted=0, j=istart; jnnbrs; - mynbrs[myrinfo->nnbrs].gv = 0; - mynbrs[myrinfo->nnbrs].pid = other; - mynbrs[myrinfo->nnbrs++].ned = 1; - } - else { - mynbrs[k].ned++; - } - } - } - myrinfo->nid = tid; - myrinfo->ned = ted; - - /* Remove space for edegrees if it was interior */ - if (ted == 0) { - ctrl->nbrpoolcpos -= iend-istart+1; - myrinfo->inbr = -1; - } - else { - for (j=0; jnnbrs; j++) - htable[mynbrs[j].pid] = -1; - } - } - } - - ComputeKWayVolGains(ctrl, graph); - - ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); - } - break; - - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } - - graph->mincut = cgraph->mincut; - icopy(nparts*graph->ncon, cgraph->pwgts, graph->pwgts); - - FreeGraph(&graph->coarser); - graph->coarser = NULL; - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function computes the boundary definition for balancing. */ -/*************************************************************************/ -void ComputeKWayBoundary(ctrl_t *ctrl, graph_t *graph, idx_t bndtype) -{ - idx_t i, nvtxs, nbnd; - idx_t *bndind, *bndptr; - - nvtxs = graph->nvtxs; - bndind = graph->bndind; - bndptr = iset(nvtxs, -1, graph->bndptr); - - nbnd = 0; - - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - /* Compute the boundary */ - if (bndtype == BNDTYPE_REFINE) { - for (i=0; ickrinfo[i].ed-graph->ckrinfo[i].id >= 0) - BNDInsert(nbnd, bndind, bndptr, i); - } - } - else { /* BNDTYPE_BALANCE */ - for (i=0; ickrinfo[i].ed > 0) - BNDInsert(nbnd, bndind, bndptr, i); - } - } - break; - - case METIS_OBJTYPE_VOL: - /* Compute the boundary */ - if (bndtype == BNDTYPE_REFINE) { - for (i=0; ivkrinfo[i].gv >= 0) - BNDInsert(nbnd, bndind, bndptr, i); - } - } - else { /* BNDTYPE_BALANCE */ - for (i=0; ivkrinfo[i].ned > 0) - BNDInsert(nbnd, bndind, bndptr, i); - } - } - break; - - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } - - graph->nbnd = nbnd; -} - - -/*************************************************************************/ -/*! This function computes the initial gains in the communication volume */ -/*************************************************************************/ -void ComputeKWayVolGains(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, k, l, nvtxs, nparts, me, other, pid; - idx_t *xadj, *vsize, *adjncy, *adjwgt, *where, - *bndind, *bndptr, *ophtable; - vkrinfo_t *myrinfo, *orinfo; - vnbr_t *mynbrs, *onbrs; - - WCOREPUSH; - - nparts = ctrl->nparts; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vsize = graph->vsize; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - where = graph->where; - bndind = graph->bndind; - bndptr = iset(nvtxs, -1, graph->bndptr); - - ophtable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); - - /* Compute the volume gains */ - graph->minvol = graph->nbnd = 0; - for (i=0; ivkrinfo+i; - myrinfo->gv = IDX_MIN; - - if (myrinfo->nnbrs > 0) { - me = where[i]; - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - graph->minvol += myrinfo->nnbrs*vsize[i]; - - for (j=xadj[i]; jvkrinfo+ii; - onbrs = ctrl->vnbrpool + orinfo->inbr; - - for (k=0; knnbrs; k++) - ophtable[onbrs[k].pid] = k; - ophtable[other] = 1; /* this is to simplify coding */ - - if (me == other) { - /* Find which domains 'i' is connected to but 'ii' is not - and update their gain */ - for (k=0; knnbrs; k++) { - if (ophtable[mynbrs[k].pid] == -1) - mynbrs[k].gv -= vsize[ii]; - } - } - else { - ASSERT(ophtable[me] != -1); - - if (onbrs[ophtable[me]].ned == 1) { - /* I'm the only connection of 'ii' in 'me' */ - /* Increase the gains for all the common domains between 'i' and 'ii' */ - for (k=0; knnbrs; k++) { - if (ophtable[mynbrs[k].pid] != -1) - mynbrs[k].gv += vsize[ii]; - } - } - else { - /* Find which domains 'i' is connected to and 'ii' is not - and update their gain */ - for (k=0; knnbrs; k++) { - if (ophtable[mynbrs[k].pid] == -1) - mynbrs[k].gv -= vsize[ii]; - } - } - } - - /* Reset the marker vector */ - for (k=0; knnbrs; k++) - ophtable[onbrs[k].pid] = -1; - ophtable[other] = -1; - } - - /* Compute the max vgain */ - for (k=0; knnbrs; k++) { - if (mynbrs[k].gv > myrinfo->gv) - myrinfo->gv = mynbrs[k].gv; - } - - /* Add the extra gain due to id == 0 */ - if (myrinfo->ned > 0 && myrinfo->nid == 0) - myrinfo->gv += vsize[i]; - } - - if (myrinfo->gv >= 0) - BNDInsert(graph->nbnd, bndind, bndptr, i); - } - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function checks if the partition weights are within the balance -contraints */ -/*************************************************************************/ -int IsBalanced(ctrl_t *ctrl, graph_t *graph, real_t ffactor) -{ - return - (ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors) - <= ffactor); -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/macros.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/macros.h deleted file mode 100644 index 3f6f7d9ed26..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/macros.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * macros.h - * - * This file contains macros used in multilevel - * - * Started 9/25/94 - * George - * - * $Id: macros.h 10060 2011-06-02 18:56:30Z karypis $ - * - */ - -#ifndef _LIBMETIS_MACROS_H_ -#define _LIBMETIS_MACROS_H_ - -/************************************************************************* -* The following macro returns a random number in the specified range -**************************************************************************/ -#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b))) -#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b))) -#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b))) - -//#define icopy(n, a, b) (idx_t *)memcpy((void *)(b), (void *)(a), sizeof(idx_t)*(n)) - -#define HASHFCT(key, size) ((key)%(size)) -#define SWAP gk_SWAP - -/* gets the appropriate option value */ -#define GETOPTION(options, idx, defval) \ - ((options) == NULL || (options)[idx] == -1 ? defval : (options)[idx]) - -/* converts a user provided ufactor into a real ubfactor */ -#define I2RUBFACTOR(ufactor) (1.0+0.001*(ufactor)) - -/* set/reset the current workspace core */ -#define WCOREPUSH wspacepush(ctrl) -#define WCOREPOP wspacepop(ctrl) - - - -/************************************************************************* -* These macros insert and remove nodes from a Direct Access list -**************************************************************************/ -#define ListInsert(n, lind, lptr, i) \ - do { \ - ASSERT(lptr[i] == -1); \ - lind[n] = i; \ - lptr[i] = (n)++;\ - } while(0) - -#define ListDelete(n, lind, lptr, i) \ - do { \ - ASSERT(lptr[i] != -1); \ - lind[lptr[i]] = lind[--(n)]; \ - lptr[lind[n]] = lptr[i]; \ - lptr[i] = -1; \ - } while(0) - - -/************************************************************************* -* These macros insert and remove nodes from the boundary list -**************************************************************************/ -#define BNDInsert(nbnd, bndind, bndptr, vtx) \ - ListInsert(nbnd, bndind, bndptr, vtx) - -#define BNDDelete(nbnd, bndind, bndptr, vtx) \ - ListDelete(nbnd, bndind, bndptr, vtx) - - -/************************************************************************* -* These macros deal with id/ed updating during k-way refinement -**************************************************************************/ -#define UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, \ - nbnd, bndptr, bndind, bndtype) \ - do { \ - where[i] = to; \ - myrinfo->ed += myrinfo->id-mynbrs[k].ed; \ - SWAP(myrinfo->id, mynbrs[k].ed, j); \ - if (mynbrs[k].ed == 0) \ - mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \ - else \ - mynbrs[k].pid = from; \ - \ - /* Update the boundary information. Both deletion and addition is \ - allowed as this routine can be used for moving arbitrary nodes. */ \ - if (bndtype == BNDTYPE_REFINE) { \ - if (bndptr[i] != -1 && myrinfo->ed - myrinfo->id < 0) \ - BNDDelete(nbnd, bndind, bndptr, i); \ - if (bndptr[i] == -1 && myrinfo->ed - myrinfo->id >= 0) \ - BNDInsert(nbnd, bndind, bndptr, i); \ - } \ - else { \ - if (bndptr[i] != -1 && myrinfo->ed <= 0) \ - BNDDelete(nbnd, bndind, bndptr, i); \ - if (bndptr[i] == -1 && myrinfo->ed > 0) \ - BNDInsert(nbnd, bndind, bndptr, i); \ - } \ - } while(0) - - -#define UpdateAdjacentVertexInfoAndBND(ctrl, vid, adjlen, me, from, to, \ - myrinfo, ewgt, nbnd, bndptr, bndind, bndtype) \ - do { \ - idx_t k; \ - cnbr_t *mynbrs; \ - \ - if (myrinfo->inbr == -1) { \ - myrinfo->inbr = cnbrpoolGetNext(ctrl, adjlen+1); \ - myrinfo->nnbrs = 0; \ - } \ - ASSERT(CheckRInfo(ctrl, myrinfo)); \ - \ - mynbrs = ctrl->cnbrpool + myrinfo->inbr; \ - \ - /* Update global ID/ED and boundary */ \ - if (me == from) { \ - INC_DEC(myrinfo->ed, myrinfo->id, (ewgt)); \ - if (bndtype == BNDTYPE_REFINE) { \ - if (myrinfo->ed-myrinfo->id >= 0 && bndptr[(vid)] == -1) \ - BNDInsert(nbnd, bndind, bndptr, (vid)); \ - } \ - else { \ - if (myrinfo->ed > 0 && bndptr[(vid)] == -1) \ - BNDInsert(nbnd, bndind, bndptr, (vid)); \ - } \ - } \ - else if (me == to) { \ - INC_DEC(myrinfo->id, myrinfo->ed, (ewgt)); \ - if (bndtype == BNDTYPE_REFINE) { \ - if (myrinfo->ed-myrinfo->id < 0 && bndptr[(vid)] != -1) \ - BNDDelete(nbnd, bndind, bndptr, (vid)); \ - } \ - else { \ - if (myrinfo->ed <= 0 && bndptr[(vid)] != -1) \ - BNDDelete(nbnd, bndind, bndptr, (vid)); \ - } \ - } \ - \ - /* Remove contribution from the .ed of 'from' */ \ - if (me != from) { \ - for (k=0; knnbrs; k++) { \ - if (mynbrs[k].pid == from) { \ - if (mynbrs[k].ed == (ewgt)) \ - mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \ - else \ - mynbrs[k].ed -= (ewgt); \ - break; \ - } \ - } \ - } \ - \ - /* Add contribution to the .ed of 'to' */ \ - if (me != to) { \ - for (k=0; knnbrs; k++) { \ - if (mynbrs[k].pid == to) { \ - mynbrs[k].ed += (ewgt); \ - break; \ - } \ - } \ - if (k == myrinfo->nnbrs) { \ - mynbrs[k].pid = to; \ - mynbrs[k].ed = (ewgt); \ - myrinfo->nnbrs++; \ - } \ - } \ - \ - ASSERT(CheckRInfo(ctrl, myrinfo));\ - } while(0) - - -#define UpdateQueueInfo(queue, vstatus, vid, me, from, to, myrinfo, oldnnbrs, \ - nupd, updptr, updind, bndtype) \ - do { \ - real_t rgain; \ - \ - if (me == to || me == from || oldnnbrs != myrinfo->nnbrs) { \ - rgain = (myrinfo->nnbrs > 0 ? \ - 1.0*myrinfo->ed/sqrt(myrinfo->nnbrs) : 0.0) - myrinfo->id; \ - \ - if (bndtype == BNDTYPE_REFINE) { \ - if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \ - if (myrinfo->ed-myrinfo->id >= 0) \ - rpqUpdate(queue, (vid), rgain); \ - else { \ - rpqDelete(queue, (vid)); \ - vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \ - ListDelete(nupd, updind, updptr, (vid)); \ - } \ - } \ - else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed-myrinfo->id >= 0) { \ - rpqInsert(queue, (vid), rgain); \ - vstatus[(vid)] = VPQSTATUS_PRESENT; \ - ListInsert(nupd, updind, updptr, (vid)); \ - } \ - } \ - else { \ - if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \ - if (myrinfo->ed > 0) \ - rpqUpdate(queue, (vid), rgain); \ - else { \ - rpqDelete(queue, (vid)); \ - vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \ - ListDelete(nupd, updind, updptr, (vid)); \ - } \ - } \ - else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed > 0) { \ - rpqInsert(queue, (vid), rgain); \ - vstatus[(vid)] = VPQSTATUS_PRESENT; \ - ListInsert(nupd, updind, updptr, (vid)); \ - } \ - } \ - } \ - } while(0) - - - -/*************************************************************************/ -/*! This macro determines the set of subdomains that a vertex can move to - without increasins the maxndoms. */ -/*************************************************************************/ -#define SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, vtmp) \ - do { \ - idx_t j, k, l, nadd, to; \ - for (j=0; jnnbrs; j++) { \ - safetos[to = mynbrs[j].pid] = 0; \ - \ - /* uncompress the connectivity info for the 'to' subdomain */ \ - for (k=0; knnbrs; k++) { \ - if (k == j) \ - continue; \ - \ - l = mynbrs[k].pid; \ - if (vtmp[l] == 0) { \ - if (nads[l] > maxndoms-1) { \ - nadd = maxndoms; \ - break; \ - } \ - nadd++; \ - } \ - } \ - if (nads[to]+nadd <= maxndoms) \ - safetos[to] = 1; \ - if (nadd == 0) \ - safetos[to] = 2; \ - \ - /* cleanup the connectivity info due to the 'to' subdomain */ \ - for (k=0; k=0; n--) { - if (x[n] > y[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function compares two vectors x & y and returns true - if \forall i, x[i] >= y[i]. -*/ -/**************************************************************************/ -int rvecge(idx_t n, real_t *x, real_t *y) -{ - for (n--; n>=0; n--) { - if (x[n] < y[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function compares vectors x1+x2 against y and returns true - if \forall i, x1[i]+x2[i] <= y[i]. -*/ -/**************************************************************************/ -int rvecsumle(idx_t n, real_t *x1, real_t *x2, real_t *y) -{ - for (n--; n>=0; n--) { - if (x1[n]+x2[n] > y[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function returns max_i(x[i]-y[i]) */ -/**************************************************************************/ -real_t rvecmaxdiff(idx_t n, real_t *x, real_t *y) -{ - real_t max; - - max = x[0]-y[0]; - - for (n--; n>0; n--) { - if (max < x[n]-y[n]) - max = x[n]-y[n]; - } - - return max; -} - - -/*************************************************************************/ -/*! This function returns true if \forall i, x[i] <= z[i]. */ -/**************************************************************************/ -int ivecle(idx_t n, idx_t *x, idx_t *z) -{ - for (n--; n>=0; n--) { - if (x[n] > z[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function returns true if \forall i, x[i] >= z[i]. */ -/**************************************************************************/ -int ivecge(idx_t n, idx_t *x, idx_t *z) -{ - for (n--; n>=0; n--) { - if (x[n] < z[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function returns true if \forall i, a*x[i]+y[i] <= z[i]. */ -/**************************************************************************/ -int ivecaxpylez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z) -{ - for (n--; n>=0; n--) { - if (a*x[n]+y[n] > z[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function returns true if \forall i, a*x[i]+y[i] >= z[i]. */ -/**************************************************************************/ -int ivecaxpygez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z) -{ - for (n--; n>=0; n--) { - if (a*x[n]+y[n] < z[n]) - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function checks if v+u2 provides a better balance in the weight - vector that v+u1 */ -/*************************************************************************/ -int BetterVBalance(idx_t ncon, real_t *invtvwgt, idx_t *v_vwgt, idx_t *u1_vwgt, - idx_t *u2_vwgt) -{ - idx_t i; - real_t sum1=0.0, sum2=0.0, diff1=0.0, diff2=0.0; - - for (i=0; i= 0); -} - - -/*************************************************************************/ -/*! This function takes two ubfactor-centered load imbalance vectors x & y, - and returns true if y is better balanced than x. */ -/*************************************************************************/ -int BetterBalance2Way(idx_t n, real_t *x, real_t *y) -{ - real_t nrm1=0.0, nrm2=0.0; - - for (--n; n>=0; n--) { - if (x[n] > 0) nrm1 += x[n]*x[n]; - if (y[n] > 0) nrm2 += y[n]*y[n]; - } - return nrm2 < nrm1; -} - - -/*************************************************************************/ -/*! Given a vertex and two weights, this function returns 1, if the second - partition will be more balanced than the first after the weighted - additional of that vertex. - The balance determination takes into account the ideal target weights - of the two partitions. -*/ -/*************************************************************************/ -int BetterBalanceKWay(idx_t ncon, idx_t *vwgt, real_t *ubvec, - idx_t a1, idx_t *pt1, real_t *bm1, - idx_t a2, idx_t *pt2, real_t *bm2) -{ - idx_t i; - real_t tmp, nrm1=0.0, nrm2=0.0, max1=0.0, max2=0.0; - - for (i=0; i max1 ? tmp : max1); - - tmp = bm2[i]*(pt2[i]+a2*vwgt[i]) - ubvec[i]; - //printf("%+.4f ", (float)tmp); - nrm2 += tmp*tmp; - max2 = (tmp > max2 ? tmp : max2); - - //printf("%4d %4d %4d %4d %4d %4d %4d %.2f\n", - // (int)vwgt[i], - // (int)a1, (int)pt1[i], (int)tpt1[i], - // (int)a2, (int)pt2[i], (int)tpt2[i], ubvec[i]); - } - //printf(" %.3f %.3f %.3f %.3f\n", (float)max1, (float)nrm1, (float)max2, (float)nrm2); - - if (max2 < max1) - return 1; - - if (max2 == max1 && nrm2 < nrm1) - return 1; - - return 0; -} - - -/*************************************************************************/ -/*! Computes the maximum load imbalance of a partitioning solution over - all the constraints. */ -/**************************************************************************/ -real_t ComputeLoadImbalance(graph_t *graph, idx_t nparts, real_t *pijbm) -{ - idx_t i, j, ncon, *pwgts; - real_t max, cur; - - ncon = graph->ncon; - pwgts = graph->pwgts; - - max = 1.0; - for (i=0; i max) - max = cur; - } - } - - return max; -} - - -/*************************************************************************/ -/*! Computes the maximum load imbalance difference of a partitioning - solution over all the constraints. - The difference is defined with respect to the allowed maximum - unbalance for the respective constraint. - */ -/**************************************************************************/ -real_t ComputeLoadImbalanceDiff(graph_t *graph, idx_t nparts, real_t *pijbm, - real_t *ubvec) -{ - idx_t i, j, ncon, *pwgts; - real_t max, cur; - - ncon = graph->ncon; - pwgts = graph->pwgts; - - max = -1.0; - for (i=0; i max) - max = cur; - } - } - - return max; -} - - -/*************************************************************************/ -/*! Computes the difference between load imbalance of each constraint across - the partitions minus the desired upper bound on the load imabalnce. - It also returns the maximum load imbalance across the partitions & - constraints. */ -/**************************************************************************/ -real_t ComputeLoadImbalanceDiffVec(graph_t *graph, idx_t nparts, real_t *pijbm, - real_t *ubfactors, real_t *diffvec) -{ - idx_t i, j, ncon, *pwgts; - real_t cur, max; - - ncon = graph->ncon; - pwgts = graph->pwgts; - - for (max=-1.0, i=0; i diffvec[i]) - diffvec[i] = cur; - } - if (max < diffvec[i]) - max = diffvec[i]; - } - - return max; -} - - -/*************************************************************************/ -/*! Computes the load imbalance of each constraint across the partitions. */ -/**************************************************************************/ -void ComputeLoadImbalanceVec(graph_t *graph, idx_t nparts, real_t *pijbm, - real_t *lbvec) -{ - idx_t i, j, ncon, *pwgts; - real_t cur; - - ncon = graph->ncon; - pwgts = graph->pwgts; - - for (i=0; i lbvec[i]) - lbvec[i] = cur; - } - } -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/mesh.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/mesh.c deleted file mode 100644 index 3c526121123..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/mesh.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * mesh.c - * - * This file contains routines for converting 3D and 4D finite element - * meshes into dual or nodal graphs - * - * Started 8/18/97 - * George - * - * $Id: mesh.c 13804 2013-03-04 23:49:08Z karypis $ - * - */ - -#include "metislib.h" - - -/*****************************************************************************/ -/*! This function creates a graph corresponding to the dual of a finite element - mesh. - - \param ne is the number of elements in the mesh. - \param nn is the number of nodes in the mesh. - \param eptr is an array of size ne+1 used to mark the start and end - locations in the nind array. - \param eind is an array that stores for each element the set of node IDs - (indices) that it is made off. The length of this array is equal - to the total number of nodes over all the mesh elements. - \param ncommon is the minimum number of nodes that two elements must share - in order to be connected via an edge in the dual graph. - \param numflag is either 0 or 1 indicating if the numbering of the nodes - starts from 0 or 1, respectively. The same numbering is used for the - returned graph as well. - \param r_xadj indicates where the adjacency list of each vertex is stored - in r_adjncy. The memory for this array is allocated by this routine. - It can be freed by calling METIS_free(). - \param r_adjncy stores the adjacency list of each vertex in the generated - dual graph. The memory for this array is allocated by this routine. - It can be freed by calling METIS_free(). - -*/ -/*****************************************************************************/ -int METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy) -{ - int sigrval=0, renumber=0; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - - /* renumber the mesh */ - if (*numflag == 1) { - ChangeMesh2CNumbering(*ne, eptr, eind); - renumber = 1; - } - - /* create dual graph */ - *r_xadj = *r_adjncy = NULL; - CreateGraphDual(*ne, *nn, eptr, eind, *ncommon, r_xadj, r_adjncy); - - -SIGTHROW: - if (renumber) - ChangeMesh2FNumbering(*ne, eptr, eind, *ne, *r_xadj, *r_adjncy); - - gk_siguntrap(); - gk_malloc_cleanup(0); - - if (sigrval != 0) { - if (*r_xadj != NULL) - free(*r_xadj); - if (*r_adjncy != NULL) - free(*r_adjncy); - *r_xadj = *r_adjncy = NULL; - } - - return metis_rcode(sigrval); -} - - -/*****************************************************************************/ -/*! This function creates a graph corresponding to (almost) the nodal of a - finite element mesh. In the nodal graph, each node is connected to the - nodes corresponding to the union of nodes present in all the elements - in which that node belongs. - - \param ne is the number of elements in the mesh. - \param nn is the number of nodes in the mesh. - \param eptr is an array of size ne+1 used to mark the start and end - locations in the nind array. - \param eind is an array that stores for each element the set of node IDs - (indices) that it is made off. The length of this array is equal - to the total number of nodes over all the mesh elements. - \param numflag is either 0 or 1 indicating if the numbering of the nodes - starts from 0 or 1, respectively. The same numbering is used for the - returned graph as well. - \param r_xadj indicates where the adjacency list of each vertex is stored - in r_adjncy. The memory for this array is allocated by this routine. - It can be freed by calling METIS_free(). - \param r_adjncy stores the adjacency list of each vertex in the generated - dual graph. The memory for this array is allocated by this routine. - It can be freed by calling METIS_free(). - -*/ -/*****************************************************************************/ -int METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy) -{ - int sigrval=0, renumber=0; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - - /* renumber the mesh */ - if (*numflag == 1) { - ChangeMesh2CNumbering(*ne, eptr, eind); - renumber = 1; - } - - /* create nodal graph */ - *r_xadj = *r_adjncy = NULL; - CreateGraphNodal(*ne, *nn, eptr, eind, r_xadj, r_adjncy); - - -SIGTHROW: - if (renumber) - ChangeMesh2FNumbering(*ne, eptr, eind, *nn, *r_xadj, *r_adjncy); - - gk_siguntrap(); - gk_malloc_cleanup(0); - - if (sigrval != 0) { - if (*r_xadj != NULL) - free(*r_xadj); - if (*r_adjncy != NULL) - free(*r_adjncy); - *r_xadj = *r_adjncy = NULL; - } - - return metis_rcode(sigrval); -} - - -/*****************************************************************************/ -/*! This function creates the dual of a finite element mesh */ -/*****************************************************************************/ -void CreateGraphDual(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t ncommon, - idx_t **r_xadj, idx_t **r_adjncy) -{ - idx_t i, j, nnbrs; - idx_t *nptr, *nind; - idx_t *xadj, *adjncy; - idx_t *marker, *nbrs; - - if (ncommon < 1) { - printf(" Increased ncommon to 1, as it was initially %"PRIDX"\n", ncommon); - ncommon = 1; - } - - /* construct the node-element list first */ - nptr = ismalloc(nn+1, 0, "CreateGraphDual: nptr"); - nind = imalloc(eptr[ne], "CreateGraphDual: nind"); - - for (i=0; i= ncommon || - overlap >= elen-1 || - overlap >= eptr[l+1]-eptr[l]-1) - nbrs[j++] = l; - marker[l] = 0; - } - - return j; -} - - -/*****************************************************************************/ -/*! This function creates the (almost) nodal of a finite element mesh */ -/*****************************************************************************/ -void CreateGraphNodal(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, - idx_t **r_xadj, idx_t **r_adjncy) -{ - idx_t i, j, nnbrs; - idx_t *nptr, *nind; - idx_t *xadj, *adjncy; - idx_t *marker, *nbrs; - - - /* construct the node-element list first */ - nptr = ismalloc(nn+1, 0, "CreateGraphNodal: nptr"); - nind = imalloc(eptr[ne], "CreateGraphNodal: nind"); - - for (i=0; ieptr, &mesh->eind, &mesh->ewgt, &mesh, LTERM); - - *r_mesh = NULL; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/meshpart.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/meshpart.c deleted file mode 100644 index a66d106102f..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/meshpart.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * meshpart.c - * - * This file contains routines for partitioning finite element meshes. - * - * Started 9/29/97 - * George - * - * $Id: meshpart.c 13931 2013-03-29 16:48:48Z karypis $ - * - */ - -#include "metislib.h" - - -/************************************************************************* -* This function partitions a finite element mesh by partitioning its nodal -* graph using KMETIS and then assigning elements in a load balanced fashion. -**************************************************************************/ -int METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts, - idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart) -{ - int sigrval=0, renumber=0, ptype; - idx_t *xadj=NULL, *adjncy=NULL; - idx_t ncon=1, pnumflag=0; - int rstatus=METIS_OK; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - renumber = GETOPTION(options, METIS_OPTION_NUMBERING, 0); - ptype = GETOPTION(options, METIS_OPTION_PTYPE, METIS_PTYPE_KWAY); - - /* renumber the mesh */ - if (renumber) { - ChangeMesh2CNumbering(*ne, eptr, eind); - options[METIS_OPTION_NUMBERING] = 0; - } - - /* get the nodal graph */ - rstatus = METIS_MeshToNodal(ne, nn, eptr, eind, &pnumflag, &xadj, &adjncy); - if (rstatus != METIS_OK) - raise(SIGERR); - - /* partition the graph */ - if (ptype == METIS_PTYPE_KWAY) - rstatus = METIS_PartGraphKway(nn, &ncon, xadj, adjncy, vwgt, vsize, NULL, - nparts, tpwgts, NULL, options, objval, npart); - else - rstatus = METIS_PartGraphRecursive(nn, &ncon, xadj, adjncy, vwgt, vsize, NULL, - nparts, tpwgts, NULL, options, objval, npart); - - if (rstatus != METIS_OK) - raise(SIGERR); - - /* partition the other side of the mesh */ - InduceRowPartFromColumnPart(*ne, eptr, eind, epart, npart, *nparts, tpwgts); - - -SIGTHROW: - if (renumber) { - ChangeMesh2FNumbering2(*ne, *nn, eptr, eind, epart, npart); - options[METIS_OPTION_NUMBERING] = 1; - } - - METIS_Free(xadj); - METIS_Free(adjncy); - - gk_siguntrap(); - gk_malloc_cleanup(0); - - return metis_rcode(sigrval); -} - - - -/************************************************************************* -* This function partitions a finite element mesh by partitioning its dual -* graph using KMETIS and then assigning nodes in a load balanced fashion. -**************************************************************************/ -int METIS_PartMeshDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, - idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts, - real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, - idx_t *npart) -{ - int sigrval=0, renumber=0, ptype; - idx_t i, j; - idx_t *xadj=NULL, *adjncy=NULL, *nptr=NULL, *nind=NULL; - idx_t ncon=1, pnumflag=0; - int rstatus = METIS_OK; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - renumber = GETOPTION(options, METIS_OPTION_NUMBERING, 0); - ptype = GETOPTION(options, METIS_OPTION_PTYPE, METIS_PTYPE_KWAY); - - /* renumber the mesh */ - if (renumber) { - ChangeMesh2CNumbering(*ne, eptr, eind); - options[METIS_OPTION_NUMBERING] = 0; - } - - /* get the dual graph */ - rstatus = METIS_MeshToDual(ne, nn, eptr, eind, ncommon, &pnumflag, &xadj, &adjncy); - if (rstatus != METIS_OK) - raise(SIGERR); - - /* partition the graph */ - if (ptype == METIS_PTYPE_KWAY) - rstatus = METIS_PartGraphKway(ne, &ncon, xadj, adjncy, vwgt, vsize, NULL, - nparts, tpwgts, NULL, options, objval, epart); - else - rstatus = METIS_PartGraphRecursive(ne, &ncon, xadj, adjncy, vwgt, vsize, NULL, - nparts, tpwgts, NULL, options, objval, epart); - - if (rstatus != METIS_OK) - raise(SIGERR); - - - /* construct the node-element list */ - nptr = ismalloc(*nn+1, 0, "METIS_PartMeshDual: nptr"); - nind = imalloc(eptr[*ne], "METIS_PartMeshDual: nind"); - - for (i=0; i<*ne; i++) { - for (j=eptr[i]; j 0); - - /* assign it first to the domain with most things in common */ - rpart[i] = nbrdom[iargmax(nnbrs, nbrwgt)]; - - /* if overweight, assign it to the light domain */ - if (pwgts[rpart[i]] > itpwgts[rpart[i]]) { - for (j=0; j - -#if defined(ENABLE_OPENMP) - #include -#endif - - -#include -#include -#include - -#include -#include -#include -#include - - -#if defined(COMPILER_MSC) -#if defined(rint) - #undef rint -#endif -#define rint(x) ((idx_t)((x)+0.5)) /* MSC does not have rint() function */ -#endif - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/minconn.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/minconn.c deleted file mode 100644 index 86dc90fbee1..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/minconn.c +++ /dev/null @@ -1,729 +0,0 @@ -/*! -\file -\brief Functions that deal with prunning the number of adjacent subdomains in kmetis - -\date Started 7/15/98 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version $Id: minconn.c 10513 2011-07-07 22:06:03Z karypis $ -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function computes the subdomain graph storing the result in the - pre-allocated worspace arrays */ -/*************************************************************************/ -void ComputeSubDomainGraph(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, pid, other, nparts, nvtxs, nnbrs; - idx_t *xadj, *adjncy, *adjwgt, *where; - idx_t *pptr, *pind; - idx_t nads=0, *vadids, *vadwgts; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - where = graph->where; - - nparts = ctrl->nparts; - - vadids = ctrl->pvec1; - vadwgts = iset(nparts, 0, ctrl->pvec2); - - pptr = iwspacemalloc(ctrl, nparts+1); - pind = iwspacemalloc(ctrl, nvtxs); - iarray2csr(nvtxs, nparts, where, pptr, pind); - - for (pid=0; pidobjtype) { - case METIS_OBJTYPE_CUT: - { - ckrinfo_t *rinfo; - cnbr_t *nbrs; - - rinfo = graph->ckrinfo; - for (nads=0, ii=pptr[pid]; ii 0) { - nnbrs = rinfo[i].nnbrs; - nbrs = ctrl->cnbrpool + rinfo[i].inbr; - - for (j=0; jvkrinfo; - for (nads=0, ii=pptr[pid]; ii 0) { - nnbrs = rinfo[i].nnbrs; - nbrs = ctrl->vnbrpool + rinfo[i].inbr; - - for (j=0; jobjtype); - } - - /* See if you have enough memory to store the adjacent info for that subdomain */ - if (ctrl->maxnads[pid] < nads) { - ctrl->maxnads[pid] = 2*nads; - ctrl->adids[pid] = irealloc(ctrl->adids[pid], ctrl->maxnads[pid], - "ComputeSubDomainGraph: adids[pid]"); - ctrl->adwgts[pid] = irealloc(ctrl->adwgts[pid], ctrl->maxnads[pid], - "ComputeSubDomainGraph: adids[pid]"); - } - - ctrl->nads[pid] = nads; - for (j=0; jadids[pid][j] = vadids[j]; - ctrl->adwgts[pid][j] = vadwgts[vadids[j]]; - - vadwgts[vadids[j]] = 0; - } - } - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function updates the weight of an edge in the subdomain graph by - adding to it the value of ewgt. The update can either increase or - decrease the weight of the subdomain edge based on the value of ewgt. - - \param u is the ID of one of the incident subdomains to the edge - \param v is the ID of the other incident subdomains to the edge - \param ewgt is the weight to be added to the subdomain edge - \param nparts is the number of subdomains - \param r_maxndoms is the maximum number of adjacent subdomains and is - updated as necessary. The update is skipped if a NULL value is - supplied. -*/ -/*************************************************************************/ -void UpdateEdgeSubDomainGraph(ctrl_t *ctrl, idx_t u, idx_t v, idx_t ewgt, - idx_t *r_maxndoms) -{ - idx_t i, j, nads; - - if (ewgt == 0) - return; - - for (i=0; i<2; i++) { - nads = ctrl->nads[u]; - /* Find the edge */ - for (j=0; jadids[u][j] == v) { - ctrl->adwgts[u][j] += ewgt; - break; - } - } - - if (j == nads) { - /* Deal with the case in which the edge was not found */ - ASSERT(ewgt > 0); - if (ctrl->maxnads[u] == nads) { - ctrl->maxnads[u] = 2*(nads+1); - ctrl->adids[u] = irealloc(ctrl->adids[u], ctrl->maxnads[u], - "IncreaseEdgeSubDomainGraph: adids[pid]"); - ctrl->adwgts[u] = irealloc(ctrl->adwgts[u], ctrl->maxnads[u], - "IncreaseEdgeSubDomainGraph: adids[pid]"); - } - ctrl->adids[u][nads] = v; - ctrl->adwgts[u][nads] = ewgt; - nads++; - if (r_maxndoms != NULL && nads > *r_maxndoms) { - printf("You just increased the maxndoms: %"PRIDX" %"PRIDX"\n", - nads, *r_maxndoms); - *r_maxndoms = nads; - } - } - else { - /* See if the updated edge becomes 0 */ - ASSERT(ctrl->adwgts[u][j] >= 0); - if (ctrl->adwgts[u][j] == 0) { - ctrl->adids[u][j] = ctrl->adids[u][nads-1]; - ctrl->adwgts[u][j] = ctrl->adwgts[u][nads-1]; - nads--; - if (r_maxndoms != NULL && nads+1 == *r_maxndoms) - *r_maxndoms = ctrl->nads[iargmax(ctrl->nparts, ctrl->nads)]; - } - } - ctrl->nads[u] = nads; - - SWAP(u, v, j); - } -} - - -/*************************************************************************/ -/*! This function computes the subdomain graph */ -/*************************************************************************/ -void EliminateSubDomainEdges(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, k, ncon, nparts, scheme, pid_from, pid_to, me, other, nvtxs, - total, max, avg, totalout, nind=0, ncand=0, ncand2, target, target2, - nadd, bestnadd=0; - idx_t min, move, *cpwgt; - idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *maxpwgt, - *mypmat, *otherpmat, *kpmat, *ind; - idx_t *nads, **adids, **adwgts; - ikv_t *cand, *cand2; - ipq_t queue; - real_t *tpwgts, badfactor=1.4; - idx_t *pptr, *pind; - idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL; /* volume specific work arrays */ - - WCOREPUSH; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt); - - where = graph->where; - pwgts = graph->pwgts; /* We assume that this is properly initialized */ - - nparts = ctrl->nparts; - tpwgts = ctrl->tpwgts; - - cpwgt = iwspacemalloc(ctrl, ncon); - maxpwgt = iwspacemalloc(ctrl, nparts*ncon); - ind = iwspacemalloc(ctrl, nvtxs); - otherpmat = iset(nparts, 0, iwspacemalloc(ctrl, nparts)); - - cand = ikvwspacemalloc(ctrl, nparts); - cand2 = ikvwspacemalloc(ctrl, nparts); - - pptr = iwspacemalloc(ctrl, nparts+1); - pind = iwspacemalloc(ctrl, nvtxs); - iarray2csr(nvtxs, nparts, where, pptr, pind); - - if (ctrl->objtype == METIS_OBJTYPE_VOL) { - /* Vol-refinement specific working arrays */ - modind = iwspacemalloc(ctrl, nvtxs); - vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); - pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); - } - - - /* Compute the pmat matrix and ndoms */ - ComputeSubDomainGraph(ctrl, graph); - - nads = ctrl->nads; - adids = ctrl->adids; - adwgts = ctrl->adwgts; - - mypmat = iset(nparts, 0, ctrl->pvec1); - kpmat = iset(nparts, 0, ctrl->pvec2); - - /* Compute the maximum allowed weight for each domain */ - for (i=0; itvwgt[j]*ctrl->ubfactors[j]; - } - - ipqInit(&queue, nparts); - - /* Get into the loop eliminating subdomain connections */ - while (1) { - total = isum(nparts, nads, 1); - avg = total/nparts; - max = nads[iargmax(nparts, nads)]; - - IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, - printf("Adjacent Subdomain Stats: Total: %3"PRIDX", " - "Max: %3"PRIDX"[%zu], Avg: %3"PRIDX"\n", - total, max, iargmax(nparts, nads), avg)); - - if (max < badfactor*avg) - break; - - /* Add the subdomains that you will try to reduce their connectivity */ - ipqReset(&queue); - for (i=0; i= avg + (max-avg)/2) - ipqInsert(&queue, i, nads[i]); - } - - move = 0; - while ((me = ipqGetTop(&queue)) != -1) { - totalout = isum(nads[me], adwgts[me], 1); - - for (ncand2=0, i=0; idbglvl, METIS_DBG_CONNINFO, - printf("Me: %"PRIDX", Degree: %4"PRIDX", TotalOut: %"PRIDX",\n", - me, nads[me], totalout)); - - /* Sort the connections according to their cut */ - ikvsorti(ncand2, cand2); - - /* Two schemes are used for eliminating subdomain edges. - The first, tries to eliminate subdomain edges by moving remote groups - of vertices to subdomains that 'me' is already connected to. - The second, tries to eliminate subdomain edges by moving entire sets of - my vertices that connect to the 'other' subdomain to a subdomain that - I'm already connected to. - These two schemes are applied in sequence. */ - target = target2 = -1; - for (scheme=0; scheme<2; scheme++) { - for (min=0; min 0); - } - - ikvsortd(ncand, cand); - - IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, - printf("\tMinOut: %4"PRIDX", to: %3"PRIDX", TtlWgt: %5"PRIDX"[#:%"PRIDX"]\n", - mypmat[other], other, isum(ncon, cpwgt, 1), nind)); - - /* Go through and select the first domain that is common with 'me', and does - not increase the nads[target] higher than nads[me], subject to the maxpwgt - constraint. Traversal is done from the mostly connected to the least. */ - for (i=0; i 0) { - /* Check if balance will go off */ - if (!ivecaxpylez(ncon, 1, cpwgt, pwgts+k*ncon, maxpwgt+k*ncon)) - continue; - - /* get a dense vector out of k's connectivity */ - for (j=0; j 0 && kpmat[j] == 0 && nads[j]+1 >= nads[me]) - break; - } - - /* There were no bad second level effects. See if you can find a - subdomain to move to. */ - if (j == nparts) { - for (nadd=0, j=0; j 0 && kpmat[j] == 0) - nadd++; - } - - IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, - printf("\t\tto=%"PRIDX", nadd=%"PRIDX", %"PRIDX"\n", k, nadd, nads[k])); - - if (nads[k]+nadd < nads[me]) { - if (target2 == -1 || nads[target2]+bestnadd > nads[k]+nadd || - (nads[target2]+bestnadd == nads[k]+nadd && bestnadd > nadd)) { - target2 = k; - bestnadd = nadd; - } - } - - if (nadd == 0) - target = k; - } - - /* reset kpmat for the next iteration */ - for (j=0; jdbglvl, METIS_DBG_CONNINFO, - printf("\t\tScheme: %"PRIDX". Moving to %"PRIDX"\n", scheme, target)); - move = 1; - break; - } - } - - if (target != -1) - break; /* A move was found. No need to try the other scheme */ - } - - /* reset the mypmat for next iteration */ - for (i=0; iobjtype) { - case METIS_OBJTYPE_CUT: - MoveGroupMinConnForCut(ctrl, graph, target, nind, ind); - break; - case METIS_OBJTYPE_VOL: - MoveGroupMinConnForVol(ctrl, graph, target, nind, ind, vmarker, - pmarker, modind); - break; - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } - - /* Update the csr representation of the partitioning vector */ - iarray2csr(nvtxs, nparts, where, pptr, pind); - } - } - - if (move == 0) - break; - } - - ipqFree(&queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function moves a collection of vertices and updates their rinfo */ -/*************************************************************************/ -void MoveGroupMinConnForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, - idx_t *ind) -{ - idx_t i, ii, j, jj, k, l, nvtxs, nbnd, from, me; - idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind; - ckrinfo_t *myrinfo; - cnbr_t *mynbrs; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - - nbnd = graph->nbnd; - - while (--nind>=0) { - i = ind[nind]; - from = where[i]; - - myrinfo = graph->ckrinfo+i; - if (myrinfo->inbr == -1) { - myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); - myrinfo->nnbrs = 0; - } - mynbrs = ctrl->cnbrpool + myrinfo->inbr; - - /* find the location of 'to' in myrinfo or create it if it is not there */ - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == to) - break; - } - if (k == myrinfo->nnbrs) { - ASSERT(k < xadj[i+1]-xadj[i]); - mynbrs[k].pid = to; - mynbrs[k].ed = 0; - myrinfo->nnbrs++; - } - - /* Update pwgts */ - iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); - iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); - - /* Update mincut */ - graph->mincut -= mynbrs[k].ed-myrinfo->id; - - /* Update subdomain connectivity graph to reflect the move of 'i' */ - UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, NULL); - - /* Update ID/ED and BND related information for the moved vertex */ - UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, - bndptr, bndind, BNDTYPE_REFINE); - - /* Update the degrees of adjacent vertices */ - for (j=xadj[i]; jckrinfo+ii; - - UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, - from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE); - - /* Update subdomain graph to reflect the move of 'i' for domains other - than 'from' and 'to' */ - if (me != from && me != to) { - UpdateEdgeSubDomainGraph(ctrl, from, me, -adjwgt[j], NULL); - UpdateEdgeSubDomainGraph(ctrl, to, me, adjwgt[j], NULL); - } - } - } - - ASSERT(ComputeCut(graph, where) == graph->mincut); - - graph->nbnd = nbnd; - -} - - -/*************************************************************************/ -/*! This function moves a collection of vertices and updates their rinfo */ -/*************************************************************************/ -void MoveGroupMinConnForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, - idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind) -{ - idx_t i, ii, j, jj, k, l, nvtxs, from, me, other, xgain, ewgt; - idx_t *xadj, *vsize, *adjncy, *where; - vkrinfo_t *myrinfo, *orinfo; - vnbr_t *mynbrs, *onbrs; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vsize = graph->vsize; - adjncy = graph->adjncy; - where = graph->where; - - while (--nind>=0) { - i = ind[nind]; - from = where[i]; - - myrinfo = graph->vkrinfo+i; - if (myrinfo->inbr == -1) { - myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); - myrinfo->nnbrs = 0; - } - mynbrs = ctrl->vnbrpool + myrinfo->inbr; - - xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? vsize[i] : 0); - - //printf("Moving %"PRIDX" from %"PRIDX" to %"PRIDX" [vsize: %"PRIDX"] [xgain: %"PRIDX"]\n", - // i, from, to, vsize[i], xgain); - - /* find the location of 'to' in myrinfo or create it if it is not there */ - for (k=0; knnbrs; k++) { - if (mynbrs[k].pid == to) - break; - } - - if (k == myrinfo->nnbrs) { - //printf("Missing neighbor\n"); - - if (myrinfo->nid > 0) - xgain -= vsize[i]; - - /* determine the volume gain resulting from that move */ - for (j=xadj[i]; jvkrinfo+ii; - onbrs = ctrl->vnbrpool + orinfo->inbr; - ASSERT(other != to) - - //printf(" %8d %8d %3d\n", (int)ii, (int)vsize[ii], (int)other); - - if (from == other) { - /* Same subdomain vertex: Decrease the gain if 'to' is a new neighbor. */ - for (l=0; lnnbrs; l++) { - if (onbrs[l].pid == to) - break; - } - if (l == orinfo->nnbrs) - xgain -= vsize[ii]; - } - else { - /* Remote vertex: increase if 'to' is a new subdomain */ - for (l=0; lnnbrs; l++) { - if (onbrs[l].pid == to) - break; - } - if (l == orinfo->nnbrs) - xgain -= vsize[ii]; - - /* Remote vertex: decrease if i is the only connection to 'from' */ - for (l=0; lnnbrs; l++) { - if (onbrs[l].pid == from && onbrs[l].ned == 1) { - xgain += vsize[ii]; - break; - } - } - } - } - graph->minvol -= xgain; - graph->mincut -= -myrinfo->nid; - ewgt = myrinfo->nid; - } - else { - graph->minvol -= (xgain + mynbrs[k].gv); - graph->mincut -= mynbrs[k].ned-myrinfo->nid; - ewgt = myrinfo->nid-mynbrs[k].ned; - } - - /* Update where and pwgts */ - where[i] = to; - iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); - iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); - - /* Update subdomain connectivity graph to reflect the move of 'i' */ - UpdateEdgeSubDomainGraph(ctrl, from, to, ewgt, NULL); - - /* Update the subdomain connectivity of the adjacent vertices */ - for (j=xadj[i]; jmincut); - ASSERTP(ComputeVolume(graph, where) == graph->minvol, - ("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol)); - -} - - -/*************************************************************************/ -/*! This function computes the subdomain graph. For deubuging purposes. */ -/*************************************************************************/ -void PrintSubDomainGraph(graph_t *graph, idx_t nparts, idx_t *where) -{ - idx_t i, j, k, me, nvtxs, total, max; - idx_t *xadj, *adjncy, *adjwgt, *pmat; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - pmat = ismalloc(nparts*nparts, 0, "ComputeSubDomainGraph: pmat"); - - for (i=0; i 0) - k++; - } - total += k; - - if (k > max) - max = k; -/* - printf("%2"PRIDX" -> %2"PRIDX" ", i, k); - for (j=0; j 0) - printf("[%2"PRIDX" %4"PRIDX"] ", j, pmat[i*nparts+j]); - } - printf("\n"); -*/ - } - printf("Total adjacent subdomains: %"PRIDX", Max: %"PRIDX"\n", total, max); - - gk_free((void **)&pmat, LTERM); -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/mincover.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/mincover.c deleted file mode 100644 index ed437fff1a8..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/mincover.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * mincover.c - * - * This file implements the minimum cover algorithm - * - * Started 8/1/97 - * George - * - * $Id: mincover.c 9942 2011-05-17 22:09:52Z karypis $ - */ - -#include "metislib.h" - -/************************************************************************* -* Constants used by mincover algorithm -**************************************************************************/ -#define INCOL 10 -#define INROW 20 -#define VC 1 -#define SC 2 -#define HC 3 -#define VR 4 -#define SR 5 -#define HR 6 - - -/************************************************************************* -* This function returns the min-cover of a bipartite graph. -* The algorithm used is due to Hopcroft and Karp as modified by Duff etal -* adj: the adjacency list of the bipartite graph -* asize: the number of vertices in the first part of the bipartite graph -* bsize-asize: the number of vertices in the second part -* 0..(asize-1) > A vertices -* asize..bsize > B vertices -* -* Returns: -* cover : the actual cover (array) -* csize : the size of the cover -**************************************************************************/ -void MinCover(idx_t *xadj, idx_t *adjncy, idx_t asize, idx_t bsize, idx_t *cover, idx_t *csize) -{ - idx_t i, j; - idx_t *mate, *queue, *flag, *level, *lst; - idx_t fptr, rptr, lstptr; - idx_t row, maxlevel, col; - - mate = ismalloc(bsize, -1, "MinCover: mate"); - flag = imalloc(bsize, "MinCover: flag"); - level = imalloc(bsize, "MinCover: level"); - queue = imalloc(bsize, "MinCover: queue"); - lst = imalloc(bsize, "MinCover: lst"); - - /* Get a cheap matching */ - for (i=0; i 0) { - mdeg_node = nextmd; - nextmd = invp[mdeg_node]; - marker[mdeg_node] = maxint; - invp[mdeg_node] = -num; - num = num + 1; - } - - /* search for node of the minimum degree. 'mdeg' is the current */ - /* minimum degree; 'tag' is used to facilitate marking nodes. */ - if (num > neqns) - goto n1000; - tag = 1; - head[1] = 0; - mdeg = 2; - - /* infinite loop here ! */ - while (1) { - while (head[mdeg] <= 0) - mdeg++; - - /* use value of 'delta' to set up 'mdlmt', which governs */ - /* when a degree update is to be performed. */ - mdlmt = mdeg + delta; - ehead = 0; - -n500: - mdeg_node = head[mdeg]; - while (mdeg_node <= 0) { - mdeg++; - - if (mdeg > mdlmt) - goto n900; - mdeg_node = head[mdeg]; - }; - - /* remove 'mdeg_node' from the degree structure. */ - nextmd = invp[mdeg_node]; - head[mdeg] = nextmd; - if (nextmd > 0) - perm[nextmd] = -mdeg; - invp[mdeg_node] = -num; - *ncsub += mdeg + qsize[mdeg_node] - 2; - if ((num+qsize[mdeg_node]) > neqns) - goto n1000; - - /* eliminate 'mdeg_node' and perform quotient graph */ - /* transformation. reset 'tag' value if necessary. */ - tag++; - if (tag >= maxint) { - tag = 1; - for (i = 1; i <= neqns; i++) - if (marker[i] < maxint) - marker[i] = 0; - }; - - mmdelm(mdeg_node, xadj, adjncy, head, invp, perm, qsize, list, marker, maxint, tag); - - num += qsize[mdeg_node]; - list[mdeg_node] = ehead; - ehead = mdeg_node; - if (delta >= 0) - goto n500; - - n900: - /* update degrees of the nodes involved in the */ - /* minimum degree nodes elimination. */ - if (num > neqns) - goto n1000; - mmdupd( ehead, neqns, xadj, adjncy, delta, &mdeg, head, invp, perm, qsize, list, marker, maxint, &tag); - }; /* end of -- while ( 1 ) -- */ - -n1000: - mmdnum( neqns, perm, invp, qsize ); - - /* Adjust from Fortran back to C*/ - xadj++; adjncy++; invp++; perm++; head++; qsize++; list++; marker++; -} - - -/************************************************************************** -* mmdelm ...... multiple minimum degree elimination -* Purpose -- This routine eliminates the node mdeg_node of minimum degree -* from the adjacency structure, which is stored in the quotient -* graph format. It also transforms the quotient graph representation -* of the elimination graph. -* Input parameters -- -* mdeg_node -- node of minimum degree. -* maxint -- estimate of maximum representable (short) integer. -* tag -- tag value. -* Updated parameters -- -* (xadj, adjncy) -- updated adjacency structure. -* (head, forward, backward) -- degree doubly linked structure. -* qsize -- size of supernode. -* marker -- marker vector. -* list -- temporary linked list of eliminated nabors. -***************************************************************************/ -void mmdelm(idx_t mdeg_node, idx_t *xadj, idx_t *adjncy, idx_t *head, idx_t *forward, - idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker, idx_t maxint, idx_t tag) -{ - idx_t element, i, istop, istart, j, - jstop, jstart, link, - nabor, node, npv, nqnbrs, nxnode, - pvnode, rlmt, rloc, rnode, xqnbr; - - /* find the reachable set of 'mdeg_node' and */ - /* place it in the data structure. */ - marker[mdeg_node] = tag; - istart = xadj[mdeg_node]; - istop = xadj[mdeg_node+1] - 1; - - /* 'element' points to the beginning of the list of */ - /* eliminated nabors of 'mdeg_node', and 'rloc' gives the */ - /* storage location for the next reachable node. */ - element = 0; - rloc = istart; - rlmt = istop; - for ( i = istart; i <= istop; i++ ) { - nabor = adjncy[i]; - if ( nabor == 0 ) break; - if ( marker[nabor] < tag ) { - marker[nabor] = tag; - if ( forward[nabor] < 0 ) { - list[nabor] = element; - element = nabor; - } else { - adjncy[rloc] = nabor; - rloc++; - }; - }; /* end of -- if -- */ - }; /* end of -- for -- */ - - /* merge with reachable nodes from generalized elements. */ - while ( element > 0 ) { - adjncy[rlmt] = -element; - link = element; - -n400: - jstart = xadj[link]; - jstop = xadj[link+1] - 1; - for ( j = jstart; j <= jstop; j++ ) { - node = adjncy[j]; - link = -node; - if ( node < 0 ) goto n400; - if ( node == 0 ) break; - if ((marker[node]=0)) { - marker[node] = tag; - /*use storage from eliminated nodes if necessary.*/ - while ( rloc >= rlmt ) { - link = -adjncy[rlmt]; - rloc = xadj[link]; - rlmt = xadj[link+1] - 1; - }; - adjncy[rloc] = node; - rloc++; - }; - }; /* end of -- for ( j = jstart; -- */ - element = list[element]; - }; /* end of -- while ( element > 0 ) -- */ - if ( rloc <= rlmt ) adjncy[rloc] = 0; - /* for each node in the reachable set, do the following. */ - link = mdeg_node; - -n1100: - istart = xadj[link]; - istop = xadj[link+1] - 1; - for ( i = istart; i <= istop; i++ ) { - rnode = adjncy[i]; - link = -rnode; - if ( rnode < 0 ) goto n1100; - if ( rnode == 0 ) return; - - /* 'rnode' is in the degree list structure. */ - pvnode = backward[rnode]; - if (( pvnode != 0 ) && ( pvnode != (-maxint) )) { - /* then remove 'rnode' from the structure. */ - nxnode = forward[rnode]; - if ( nxnode > 0 ) backward[nxnode] = pvnode; - if ( pvnode > 0 ) forward[pvnode] = nxnode; - npv = -pvnode; - if ( pvnode < 0 ) head[npv] = nxnode; - }; - - /* purge inactive quotient nabors of 'rnode'. */ - jstart = xadj[rnode]; - jstop = xadj[rnode+1] - 1; - xqnbr = jstart; - for ( j = jstart; j <= jstop; j++ ) { - nabor = adjncy[j]; - if ( nabor == 0 ) break; - if ( marker[nabor] < tag ) { - adjncy[xqnbr] = nabor; - xqnbr++; - }; - }; - - /* no active nabor after the purging. */ - nqnbrs = xqnbr - jstart; - if ( nqnbrs <= 0 ) { - /* merge 'rnode' with 'mdeg_node'. */ - qsize[mdeg_node] += qsize[rnode]; - qsize[rnode] = 0; - marker[rnode] = maxint; - forward[rnode] = -mdeg_node; - backward[rnode] = -maxint; - } else { - /* flag 'rnode' for degree update, and */ - /* add 'mdeg_node' as a nabor of 'rnode'. */ - forward[rnode] = nqnbrs + 1; - backward[rnode] = 0; - adjncy[xqnbr] = mdeg_node; - xqnbr++; - if ( xqnbr <= jstop ) adjncy[xqnbr] = 0; - }; - }; /* end of -- for ( i = istart; -- */ - return; - } - -/*************************************************************************** -* mmdint ---- mult minimum degree initialization -* purpose -- this routine performs initialization for the -* multiple elimination version of the minimum degree algorithm. -* input parameters -- -* neqns -- number of equations. -* (xadj, adjncy) -- adjacency structure. -* output parameters -- -* (head, dfrow, backward) -- degree doubly linked structure. -* qsize -- size of supernode ( initialized to one). -* list -- linked list. -* marker -- marker vector. -****************************************************************************/ -idx_t mmdint(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *head, idx_t *forward, - idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker) -{ - idx_t fnode, ndeg, node; - - for ( node = 1; node <= neqns; node++ ) { - head[node] = 0; - qsize[node] = 1; - marker[node] = 0; - list[node] = 0; - }; - - /* initialize the degree doubly linked lists. */ - for ( node = 1; node <= neqns; node++ ) { - ndeg = xadj[node+1] - xadj[node]/* + 1*/; /* george */ - if (ndeg == 0) - ndeg = 1; - fnode = head[ndeg]; - forward[node] = fnode; - head[ndeg] = node; - if ( fnode > 0 ) backward[fnode] = node; - backward[node] = -ndeg; - }; - return 0; -} - -/**************************************************************************** -* mmdnum --- multi minimum degree numbering -* purpose -- this routine performs the final step in producing -* the permutation and inverse permutation vectors in the -* multiple elimination version of the minimum degree -* ordering algorithm. -* input parameters -- -* neqns -- number of equations. -* qsize -- size of supernodes at elimination. -* updated parameters -- -* invp -- inverse permutation vector. on input, -* if qsize[node] = 0, then node has been merged -* into the node -invp[node]; otherwise, -* -invp[node] is its inverse labelling. -* output parameters -- -* perm -- the permutation vector. -****************************************************************************/ -void mmdnum(idx_t neqns, idx_t *perm, idx_t *invp, idx_t *qsize) -{ - idx_t father, nextf, node, nqsize, num, root; - - for ( node = 1; node <= neqns; node++ ) { - nqsize = qsize[node]; - if ( nqsize <= 0 ) perm[node] = invp[node]; - if ( nqsize > 0 ) perm[node] = -invp[node]; - }; - - /* for each node which has been merged, do the following. */ - for ( node = 1; node <= neqns; node++ ) { - if ( perm[node] <= 0 ) { - - /* trace the merged tree until one which has not */ - /* been merged, call it root. */ - father = node; - while ( perm[father] <= 0 ) - father = - perm[father]; - - /* number node after root. */ - root = father; - num = perm[root] + 1; - invp[node] = -num; - perm[root] = num; - - /* shorten the merged tree. */ - father = node; - nextf = - perm[father]; - while ( nextf > 0 ) { - perm[father] = -root; - father = nextf; - nextf = -perm[father]; - }; - }; /* end of -- if ( perm[node] <= 0 ) -- */ - }; /* end of -- for ( node = 1; -- */ - - /* ready to compute perm. */ - for ( node = 1; node <= neqns; node++ ) { - num = -invp[node]; - invp[node] = num; - perm[num] = node; - }; - return; -} - -/**************************************************************************** -* mmdupd ---- multiple minimum degree update -* purpose -- this routine updates the degrees of nodes after a -* multiple elimination step. -* input parameters -- -* ehead -- the beginning of the list of eliminated nodes -* (i.e., newly formed elements). -* neqns -- number of equations. -* (xadj, adjncy) -- adjacency structure. -* delta -- tolerance value for multiple elimination. -* maxint -- maximum machine representable (short) integer. -* updated parameters -- -* mdeg -- new minimum degree after degree update. -* (head, forward, backward) -- degree doubly linked structure. -* qsize -- size of supernode. -* list -- marker vector for degree update. -* *tag -- tag value. -****************************************************************************/ -void mmdupd(idx_t ehead, idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t delta, idx_t *mdeg, - idx_t *head, idx_t *forward, idx_t *backward, idx_t *qsize, idx_t *list, - idx_t *marker, idx_t maxint, idx_t *tag) -{ - idx_t deg, deg0, element, enode, fnode, i, iq2, istop, - istart, j, jstop, jstart, link, mdeg0, mtag, nabor, - node, q2head, qxhead; - - mdeg0 = *mdeg + delta; - element = ehead; - -n100: - if ( element <= 0 ) return; - - /* for each of the newly formed element, do the following. */ - /* reset tag value if necessary. */ - mtag = *tag + mdeg0; - if ( mtag >= maxint ) { - *tag = 1; - for ( i = 1; i <= neqns; i++ ) - if ( marker[i] < maxint ) marker[i] = 0; - mtag = *tag + mdeg0; - }; - - /* create two linked lists from nodes associated with 'element': */ - /* one with two nabors (q2head) in the adjacency structure, and the*/ - /* other with more than two nabors (qxhead). also compute 'deg0',*/ - /* number of nodes in this element. */ - q2head = 0; - qxhead = 0; - deg0 = 0; - link =element; - -n400: - istart = xadj[link]; - istop = xadj[link+1] - 1; - for ( i = istart; i <= istop; i++ ) { - enode = adjncy[i]; - link = -enode; - if ( enode < 0 ) goto n400; - if ( enode == 0 ) break; - if ( qsize[enode] != 0 ) { - deg0 += qsize[enode]; - marker[enode] = mtag; - - /*'enode' requires a degree update*/ - if ( backward[enode] == 0 ) { - /* place either in qxhead or q2head list. */ - if ( forward[enode] != 2 ) { - list[enode] = qxhead; - qxhead = enode; - } else { - list[enode] = q2head; - q2head = enode; - }; - }; - }; /* enf of -- if ( qsize[enode] != 0 ) -- */ - }; /* end of -- for ( i = istart; -- */ - - /* for each node in q2 list, do the following. */ - enode = q2head; - iq2 = 1; - -n900: - if ( enode <= 0 ) goto n1500; - if ( backward[enode] != 0 ) goto n2200; - (*tag)++; - deg = deg0; - - /* identify the other adjacent element nabor. */ - istart = xadj[enode]; - nabor = adjncy[istart]; - if ( nabor == element ) nabor = adjncy[istart+1]; - link = nabor; - if ( forward[nabor] >= 0 ) { - /* nabor is uneliminated, increase degree count. */ - deg += qsize[nabor]; - goto n2100; - }; - - /* the nabor is eliminated. for each node in the 2nd element */ - /* do the following. */ -n1000: - istart = xadj[link]; - istop = xadj[link+1] - 1; - for ( i = istart; i <= istop; i++ ) { - node = adjncy[i]; - link = -node; - if ( node != enode ) { - if ( node < 0 ) goto n1000; - if ( node == 0 ) goto n2100; - if ( qsize[node] != 0 ) { - if ( marker[node] < *tag ) { - /* 'node' is not yet considered. */ - marker[node] = *tag; - deg += qsize[node]; - } else { - if ( backward[node] == 0 ) { - if ( forward[node] == 2 ) { - /* 'node' is indistinguishable from 'enode'.*/ - /* merge them into a new supernode. */ - qsize[enode] += qsize[node]; - qsize[node] = 0; - marker[node] = maxint; - forward[node] = -enode; - backward[node] = -maxint; - } else { - /* 'node' is outmacthed by 'enode' */ - if (backward[node]==0) backward[node] = -maxint; - }; - }; /* end of -- if ( backward[node] == 0 ) -- */ - }; /* end of -- if ( marker[node] < *tag ) -- */ - }; /* end of -- if ( qsize[node] != 0 ) -- */ - }; /* end of -- if ( node != enode ) -- */ - }; /* end of -- for ( i = istart; -- */ - goto n2100; - -n1500: - /* for each 'enode' in the 'qx' list, do the following. */ - enode = qxhead; - iq2 = 0; - -n1600: if ( enode <= 0 ) goto n2300; - if ( backward[enode] != 0 ) goto n2200; - (*tag)++; - deg = deg0; - - /*for each unmarked nabor of 'enode', do the following.*/ - istart = xadj[enode]; - istop = xadj[enode+1] - 1; - for ( i = istart; i <= istop; i++ ) { - nabor = adjncy[i]; - if ( nabor == 0 ) break; - if ( marker[nabor] < *tag ) { - marker[nabor] = *tag; - link = nabor; - if ( forward[nabor] >= 0 ) - /*if uneliminated, include it in deg count.*/ - deg += qsize[nabor]; - else { -n1700: - /* if eliminated, include unmarked nodes in this*/ - /* element into the degree count. */ - jstart = xadj[link]; - jstop = xadj[link+1] - 1; - for ( j = jstart; j <= jstop; j++ ) { - node = adjncy[j]; - link = -node; - if ( node < 0 ) goto n1700; - if ( node == 0 ) break; - if ( marker[node] < *tag ) { - marker[node] = *tag; - deg += qsize[node]; - }; - }; /* end of -- for ( j = jstart; -- */ - }; /* end of -- if ( forward[nabor] >= 0 ) -- */ - }; /* end of -- if ( marker[nabor] < *tag ) -- */ - }; /* end of -- for ( i = istart; -- */ - -n2100: - /* update external degree of 'enode' in degree structure, */ - /* and '*mdeg' if necessary. */ - deg = deg - qsize[enode] + 1; - fnode = head[deg]; - forward[enode] = fnode; - backward[enode] = -deg; - if ( fnode > 0 ) backward[fnode] = enode; - head[deg] = enode; - if ( deg < *mdeg ) *mdeg = deg; - -n2200: - /* get next enode in current element. */ - enode = list[enode]; - if ( iq2 == 1 ) goto n900; - goto n1600; - -n2300: - /* get next element in the list. */ - *tag = mtag; - element = list[element]; - goto n100; - } diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/ometis.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/ometis.c deleted file mode 100644 index 51e39754c8a..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/ometis.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * ometis.c - * - * This file contains the top level routines for the multilevel recursive - * bisection algorithm PMETIS. - * - * Started 7/24/97 - * George - * - * $Id: ometis.c 10513 2011-07-07 22:06:03Z karypis $ - * - */ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function is the entry point for the multilevel nested dissection - ordering code. At each bisection, a node-separator is computed using - a node-based refinement approach. - - \param nvtxs is the number of vertices in the graph. - \param xadj is of length nvtxs+1 marking the start of the adjancy - list of each vertex in adjncy. - \param adjncy stores the adjacency lists of the vertices. The adjnacy - list of a vertex should not contain the vertex itself. - \param vwgt is an array of size nvtxs storing the weight of each - vertex. If vwgt is NULL, then the vertices are considered - to have unit weight. - \param numflag is either 0 or 1 indicating that the numbering of - the vertices starts from 0 or 1, respectively. - \param options is an array of size METIS_NOPTIONS used to pass - various options impacting the of the algorithm. A NULL - value indicates use of default options. - \param perm is an array of size nvtxs such that if A and A' are - the original and permuted matrices, then A'[i] = A[perm[i]]. - \param iperm is an array of size nvtxs such that if A and A' are - the original and permuted matrices, then A[i] = A'[iperm[i]]. -*/ -/*************************************************************************/ -int METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, - idx_t *options, idx_t *perm, idx_t *iperm) -{ - int sigrval=0, renumber=0; - idx_t i, ii, j, l, nnvtxs=0; - graph_t *graph=NULL; - ctrl_t *ctrl; - idx_t *cptr, *cind, *piperm; - int numflag = 0; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - - /* set up the run time parameters */ - ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL); - if (!ctrl) { - gk_siguntrap(); - return METIS_ERROR_INPUT; - } - - /* if required, change the numbering to 0 */ - if (ctrl->numflag == 1) { - Change2CNumbering(*nvtxs, xadj, adjncy); - renumber = 1; - } - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); - - /* prune the dense columns */ - if (ctrl->pfactor > 0.0) { - piperm = imalloc(*nvtxs, "OMETIS: piperm"); - - graph = PruneGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, piperm, ctrl->pfactor); - if (graph == NULL) { - /* if there was no prunning, cleanup the pfactor */ - gk_free((void **)&piperm, LTERM); - ctrl->pfactor = 0.0; - } - else { - nnvtxs = graph->nvtxs; - ctrl->compress = 0; /* disable compression if prunning took place */ - } - } - - /* compress the graph; note that compression only happens if not prunning - has taken place. */ - if (ctrl->compress) { - cptr = imalloc(*nvtxs+1, "OMETIS: cptr"); - cind = imalloc(*nvtxs, "OMETIS: cind"); - - graph = CompressGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, cptr, cind); - if (graph == NULL) { - /* if there was no compression, cleanup the compress flag */ - gk_free((void **)&cptr, &cind, LTERM); - ctrl->compress = 0; - } - else { - nnvtxs = graph->nvtxs; - ctrl->cfactor = 1.0*(*nvtxs)/nnvtxs; - if (ctrl->cfactor > 1.5 && ctrl->nseps == 1) - ctrl->nseps = 2; - //ctrl->nseps = (idx_t)(ctrl->cfactor*ctrl->nseps); - } - } - - /* if no prunning and no compression, setup the graph in the normal way. */ - if (ctrl->pfactor == 0.0 && ctrl->compress == 0) - graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); - - ASSERT(CheckGraph(graph, ctrl->numflag, 1)); - - /* allocate workspace memory */ - AllocateWorkSpace(ctrl, graph); - - /* do the nested dissection ordering */ - if (ctrl->ccorder) - MlevelNestedDissectionCC(ctrl, graph, iperm, graph->nvtxs); - else - MlevelNestedDissection(ctrl, graph, iperm, graph->nvtxs); - - - if (ctrl->pfactor > 0.0) { /* Order any prunned vertices */ - icopy(nnvtxs, iperm, perm); /* Use perm as an auxiliary array */ - for (i=0; icompress) { /* Uncompress the ordering */ - /* construct perm from iperm */ - for (i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); - - /* clean up */ - FreeCtrl(&ctrl); - -SIGTHROW: - /* if required, change the numbering back to 1 */ - if (renumber) - Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); - - gk_siguntrap(); - gk_malloc_cleanup(0); - - return metis_rcode(sigrval); -} - - -/*************************************************************************/ -/*! This is the driver for the recursive tri-section of a graph into the - left, separator, and right partitions. The graphs correspond to the - left and right parts are further tri-sected in a recursive fashion. - The nodes in the separator are ordered at the end of the left & right - nodes. - */ -/*************************************************************************/ -void MlevelNestedDissection(ctrl_t *ctrl, graph_t *graph, idx_t *order, - idx_t lastvtx) -{ - idx_t i, j, nvtxs, nbnd; - idx_t *label, *bndind; - graph_t *lgraph, *rgraph; - - nvtxs = graph->nvtxs; - - MlevelNodeBisectionMultiple(ctrl, graph); - - IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, - printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", - graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); - - - /* Order the nodes in the separator */ - nbnd = graph->nbnd; - bndind = graph->bndind; - label = graph->label; - for (i=0; invtxs, which - will not be defined upon return from MlevelNestedDissection. */ - if (lgraph->nvtxs > MMDSWITCH && lgraph->nedges > 0) - MlevelNestedDissection(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); - else { - MMDOrder(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); - FreeGraph(&lgraph); - } - if (rgraph->nvtxs > MMDSWITCH && rgraph->nedges > 0) - MlevelNestedDissection(ctrl, rgraph, order, lastvtx); - else { - MMDOrder(ctrl, rgraph, order, lastvtx); - FreeGraph(&rgraph); - } -} - - -/*************************************************************************/ -/*! This routine is similar to its non 'CC' counterpart. The difference is - that after each tri-section, the connected components of the original - graph that result after removing the separator vertises are ordered - independently (i.e., this may lead to more than just the left and - the right subgraphs). -*/ -/*************************************************************************/ -void MlevelNestedDissectionCC(ctrl_t *ctrl, graph_t *graph, idx_t *order, - idx_t lastvtx) -{ - idx_t i, j, nvtxs, nbnd, ncmps, rnvtxs, snvtxs; - idx_t *label, *bndind; - idx_t *cptr, *cind; - graph_t **sgraphs; - - nvtxs = graph->nvtxs; - - MlevelNodeBisectionMultiple(ctrl, graph); - - IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, - printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", - graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); - - /* Order the nodes in the separator */ - nbnd = graph->nbnd; - bndind = graph->bndind; - label = graph->label; - for (i=0; idbglvl&METIS_DBG_INFO) { - if (ncmps > 2) - printf(" Bisection resulted in %"PRIDX" connected components\n", ncmps); - } - - sgraphs = SplitGraphOrderCC(ctrl, graph, ncmps, cptr, cind); - - WCOREPOP; - - /* Free the memory of the top level graph */ - FreeGraph(&graph); - - /* Go and process the subgraphs */ - for (rnvtxs=i=0; invtxs; - - if (sgraphs[i]->nvtxs > MMDSWITCH && sgraphs[i]->nedges > 0) { - MlevelNestedDissectionCC(ctrl, sgraphs[i], order, lastvtx-rnvtxs); - } - else { - MMDOrder(ctrl, sgraphs[i], order, lastvtx-rnvtxs); - FreeGraph(&sgraphs[i]); - } - rnvtxs += snvtxs; - } - - gk_free((void **)&sgraphs, LTERM); -} - - -/*************************************************************************/ -/*! This function performs multilevel node bisection (i.e., tri-section). - It performs multiple bisections and selects the best. */ -/*************************************************************************/ -void MlevelNodeBisectionMultiple(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, mincut; - idx_t *bestwhere; - - /* if the graph is small, just find a single vertex separator */ - if (ctrl->nseps == 1 || graph->nvtxs < (ctrl->compress ? 1000 : 2000)) { - MlevelNodeBisectionL2(ctrl, graph, LARGENIPARTS); - return; - } - - WCOREPUSH; - - bestwhere = iwspacemalloc(ctrl, graph->nvtxs); - - mincut = graph->tvwgt[0]; - for (i=0; inseps; i++) { - MlevelNodeBisectionL2(ctrl, graph, LARGENIPARTS); - - if (i == 0 || graph->mincut < mincut) { - mincut = graph->mincut; - if (i < ctrl->nseps-1) - icopy(graph->nvtxs, graph->where, bestwhere); - } - - if (mincut == 0) - break; - - if (i < ctrl->nseps-1) - FreeRData(graph); - } - - if (mincut != graph->mincut) { - icopy(graph->nvtxs, bestwhere, graph->where); - Compute2WayNodePartitionParams(ctrl, graph); - } - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function performs multilevel node bisection (i.e., tri-section). - It performs multiple bisections and selects the best. */ -/*************************************************************************/ -void MlevelNodeBisectionL2(ctrl_t *ctrl, graph_t *graph, idx_t niparts) -{ - idx_t i, mincut, nruns=5; - graph_t *cgraph; - idx_t *bestwhere; - - /* if the graph is small, just find a single vertex separator */ - if (graph->nvtxs < 5000) { - MlevelNodeBisectionL1(ctrl, graph, niparts); - return; - } - - WCOREPUSH; - - ctrl->CoarsenTo = gk_max(100, graph->nvtxs/30); - - cgraph = CoarsenGraphNlevels(ctrl, graph, 4); - - bestwhere = iwspacemalloc(ctrl, cgraph->nvtxs); - - mincut = graph->tvwgt[0]; - for (i=0; imincut < mincut) { - mincut = cgraph->mincut; - if (i < nruns-1) - icopy(cgraph->nvtxs, cgraph->where, bestwhere); - } - - if (mincut == 0) - break; - - if (i < nruns-1) - FreeRData(cgraph); - } - - if (mincut != cgraph->mincut) - icopy(cgraph->nvtxs, bestwhere, cgraph->where); - - WCOREPOP; - - Refine2WayNode(ctrl, graph, cgraph); - -} - - -/*************************************************************************/ -/*! The top-level routine of the actual multilevel node bisection */ -/*************************************************************************/ -void MlevelNodeBisectionL1(ctrl_t *ctrl, graph_t *graph, idx_t niparts) -{ - graph_t *cgraph; - - ctrl->CoarsenTo = graph->nvtxs/8; - if (ctrl->CoarsenTo > 100) - ctrl->CoarsenTo = 100; - else if (ctrl->CoarsenTo < 40) - ctrl->CoarsenTo = 40; - - cgraph = CoarsenGraph(ctrl, graph); - - niparts = gk_max(1, (cgraph->nvtxs <= ctrl->CoarsenTo ? niparts/2: niparts)); - /*niparts = (cgraph->nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS);*/ - InitSeparator(ctrl, cgraph, niparts); - - Refine2WayNode(ctrl, graph, cgraph); -} - - -/*************************************************************************/ -/*! This function takes a graph and a tri-section (left, right, separator) - and splits it into two graphs. - - This function relies on the fact that adjwgt is all equal to 1. -*/ -/*************************************************************************/ -void SplitGraphOrder(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, - graph_t **r_rgraph) -{ - idx_t i, ii, j, k, l, istart, iend, mypart, nvtxs, snvtxs[3], snedges[3]; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr, *bndind; - idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2]; - idx_t *rename; - idx_t *auxadjncy; - graph_t *lgraph, *rgraph; - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - label = graph->label; - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - ASSERT(bndptr != NULL); - - rename = iwspacemalloc(ctrl, nvtxs); - - snvtxs[0] = snvtxs[1] = snvtxs[2] = snedges[0] = snedges[1] = snedges[2] = 0; - for (i=0; ixadj; - svwgt[0] = lgraph->vwgt; - sadjncy[0] = lgraph->adjncy; - sadjwgt[0] = lgraph->adjwgt; - slabel[0] = lgraph->label; - - rgraph = SetupSplitGraph(graph, snvtxs[1], snedges[1]); - sxadj[1] = rgraph->xadj; - svwgt[1] = rgraph->vwgt; - sadjncy[1] = rgraph->adjncy; - sadjwgt[1] = rgraph->adjwgt; - slabel[1] = rgraph->label; - - /* Go and use bndptr to also mark the boundary nodes in the two partitions */ - for (ii=0; iinbnd; ii++) { - i = bndind[ii]; - for (j=xadj[i]; jnvtxs = snvtxs[0]; - lgraph->nedges = snedges[0]; - rgraph->nvtxs = snvtxs[1]; - rgraph->nedges = snedges[1]; - - SetupGraph_tvwgt(lgraph); - SetupGraph_tvwgt(rgraph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); - - *r_lgraph = lgraph; - *r_rgraph = rgraph; - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function takes a graph and generates a set of graphs, each of - which is a connected component in the original graph. - - This function relies on the fact that adjwgt is all equal to 1. - - \param ctrl stores run state info. - \param graph is the graph to be split. - \param ncmps is the number of connected components. - \param cptr is an array of size ncmps+1 that marks the start and end - locations of the vertices in cind that make up the respective - components (i.e., cptr, cind is in CSR format). - \param cind is an array of size equal to the number of vertices in - the original graph and stores the vertices that belong to each - connected component. - - \returns an array of subgraphs corresponding to the extracted subgraphs. -*/ -/*************************************************************************/ -graph_t **SplitGraphOrderCC(ctrl_t *ctrl, graph_t *graph, idx_t ncmps, - idx_t *cptr, idx_t *cind) -{ - idx_t i, ii, iii, j, k, l, istart, iend, mypart, nvtxs, snvtxs, snedges; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr, *bndind; - idx_t *sxadj, *svwgt, *sadjncy, *sadjwgt, *slabel; - idx_t *rename; - idx_t *auxadjncy; - graph_t **sgraphs; - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - label = graph->label; - where = graph->where; - bndptr = graph->bndptr; - bndind = graph->bndind; - ASSERT(bndptr != NULL); - - /* Go and use bndptr to also mark the boundary nodes in the two partitions */ - for (ii=0; iinbnd; ii++) { - i = bndind[ii]; - for (j=xadj[i]; jxadj; - svwgt = sgraphs[iii]->vwgt; - sadjncy = sgraphs[iii]->adjncy; - sadjwgt = sgraphs[iii]->adjwgt; - slabel = sgraphs[iii]->label; - - snvtxs = snedges = sxadj[0] = 0; - for (ii=cptr[iii]; iinvtxs = snvtxs; - sgraphs[iii]->nedges = snedges; - - SetupGraph_tvwgt(sgraphs[iii]); - } - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); - - WCOREPOP; - - return sgraphs; -} - - -/*************************************************************************/ -/*! This function uses MMD to order the graph. The vertices are numbered - from lastvtx downwards. */ -/*************************************************************************/ -void MMDOrder(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) -{ - idx_t i, j, k, nvtxs, nofsub, firstvtx; - idx_t *xadj, *adjncy, *label; - idx_t *perm, *iperm, *head, *qsize, *list, *marker; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - /* Relabel the vertices so that it starts from 1 */ - k = xadj[nvtxs]; - for (i=0; ilabel; - firstvtx = lastvtx-nvtxs; - for (i=0; iobjtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_CUT); - ctrl->rtype = METIS_RTYPE_FM; - ctrl->ncuts = GETOPTION(options, METIS_OPTION_NCUTS, 1); - ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10); - - if (ncon == 1) { - ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_GROW); - ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, PMETIS_DEFAULT_UFACTOR); - ctrl->CoarsenTo = 20; - } - else { - ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_RANDOM); - ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, MCPMETIS_DEFAULT_UFACTOR); - ctrl->CoarsenTo = 100; - } - - break; - - - case METIS_OP_KMETIS: - ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_CUT); - ctrl->iptype = METIS_IPTYPE_METISRB; - ctrl->rtype = METIS_RTYPE_GREEDY; - ctrl->ncuts = GETOPTION(options, METIS_OPTION_NCUTS, 1); - ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10); - ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, KMETIS_DEFAULT_UFACTOR); - ctrl->minconn = GETOPTION(options, METIS_OPTION_MINCONN, 0); - ctrl->contig = GETOPTION(options, METIS_OPTION_CONTIG, 0); - break; - - - case METIS_OP_OMETIS: - ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_NODE); - ctrl->rtype = GETOPTION(options, METIS_OPTION_RTYPE, METIS_RTYPE_SEP1SIDED); - ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_EDGE); - ctrl->nseps = GETOPTION(options, METIS_OPTION_NSEPS, 1); - ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10); - ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, OMETIS_DEFAULT_UFACTOR); - ctrl->compress = GETOPTION(options, METIS_OPTION_COMPRESS, 1); - ctrl->ccorder = GETOPTION(options, METIS_OPTION_CCORDER, 0); - ctrl->pfactor = 0.1*GETOPTION(options, METIS_OPTION_PFACTOR, 0); - - ctrl->CoarsenTo = 100; - break; - - default: - gk_errexit(SIGERR, "Unknown optype of %d\n", optype); - } - - /* common options */ - ctrl->ctype = GETOPTION(options, METIS_OPTION_CTYPE, METIS_CTYPE_SHEM); - ctrl->no2hop = GETOPTION(options, METIS_OPTION_NO2HOP, 0); - ctrl->seed = GETOPTION(options, METIS_OPTION_SEED, -1); - ctrl->dbglvl = GETOPTION(options, METIS_OPTION_DBGLVL, 0); - ctrl->numflag = GETOPTION(options, METIS_OPTION_NUMBERING, 0); - - /* set non-option information */ - ctrl->optype = optype; - ctrl->ncon = ncon; - ctrl->nparts = nparts; - ctrl->maxvwgt = ismalloc(ncon, 0, "SetupCtrl: maxvwgt"); - - /* setup the target partition weights */ - if (ctrl->optype != METIS_OP_OMETIS) { - ctrl->tpwgts = rmalloc(nparts*ncon, "SetupCtrl: ctrl->tpwgts"); - if (tpwgts) { - rcopy(nparts*ncon, tpwgts, ctrl->tpwgts); - } - else { - for (i=0; itpwgts[i*ncon+j] = 1.0/nparts; - } - } - } - else { /* METIS_OP_OMETIS */ - /* this is required to allow the pijbm to be defined properly for - the edge-based refinement during initial partitioning */ - ctrl->tpwgts = rsmalloc(2, .5, "SetupCtrl: ctrl->tpwgts"); - } - - - /* setup the ubfactors */ - ctrl->ubfactors = rsmalloc(ctrl->ncon, I2RUBFACTOR(ctrl->ufactor), "SetupCtrl: ubfactors"); - if (ubvec) - rcopy(ctrl->ncon, ubvec, ctrl->ubfactors); - for (i=0; incon; i++) - ctrl->ubfactors[i] += 0.0000499; - - /* Allocate memory for balance multipliers. - Note that for PMETIS/OMETIS routines the memory allocated is more - than required as balance multipliers for 2 parts is sufficient. */ - ctrl->pijbm = rmalloc(nparts*ncon, "SetupCtrl: ctrl->pijbm"); - - InitRandom(ctrl->seed); - - IFSET(ctrl->dbglvl, METIS_DBG_INFO, PrintCtrl(ctrl)); - - if (!CheckParams(ctrl)) { - FreeCtrl(&ctrl); - return NULL; - } - else { - return ctrl; - } -} - - -/*************************************************************************/ -/*! Computes the per-partition/constraint balance multipliers */ -/*************************************************************************/ -void SetupKWayBalMultipliers(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j; - - for (i=0; inparts; i++) { - for (j=0; jncon; j++) - ctrl->pijbm[i*graph->ncon+j] = graph->invtvwgt[j]/ctrl->tpwgts[i*graph->ncon+j]; - } -} - - -/*************************************************************************/ -/*! Computes the per-partition/constraint balance multipliers */ -/*************************************************************************/ -void Setup2WayBalMultipliers(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts) -{ - idx_t i, j; - - for (i=0; i<2; i++) { - for (j=0; jncon; j++) - ctrl->pijbm[i*graph->ncon+j] = graph->invtvwgt[j]/tpwgts[i*graph->ncon+j]; - } -} - - -/*************************************************************************/ -/*! This function prints the various control fields */ -/*************************************************************************/ -void PrintCtrl(ctrl_t *ctrl) -{ - idx_t i, j, modnum; - - printf(" Runtime parameters:\n"); - - printf(" Objective type: "); - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - printf("METIS_OBJTYPE_CUT\n"); - break; - case METIS_OBJTYPE_VOL: - printf("METIS_OBJTYPE_VOL\n"); - break; - case METIS_OBJTYPE_NODE: - printf("METIS_OBJTYPE_NODE\n"); - break; - default: - printf("Unknown!\n"); - } - - printf(" Coarsening type: "); - switch (ctrl->ctype) { - case METIS_CTYPE_RM: - printf("METIS_CTYPE_RM\n"); - break; - case METIS_CTYPE_SHEM: - printf("METIS_CTYPE_SHEM\n"); - break; - default: - printf("Unknown!\n"); - } - - printf(" Initial partitioning type: "); - switch (ctrl->iptype) { - case METIS_IPTYPE_GROW: - printf("METIS_IPTYPE_GROW\n"); - break; - case METIS_IPTYPE_RANDOM: - printf("METIS_IPTYPE_RANDOM\n"); - break; - case METIS_IPTYPE_EDGE: - printf("METIS_IPTYPE_EDGE\n"); - break; - case METIS_IPTYPE_NODE: - printf("METIS_IPTYPE_NODE\n"); - break; - case METIS_IPTYPE_METISRB: - printf("METIS_IPTYPE_METISRB\n"); - break; - default: - printf("Unknown!\n"); - } - - printf(" Refinement type: "); - switch (ctrl->rtype) { - case METIS_RTYPE_FM: - printf("METIS_RTYPE_FM\n"); - break; - case METIS_RTYPE_GREEDY: - printf("METIS_RTYPE_GREEDY\n"); - break; - case METIS_RTYPE_SEP2SIDED: - printf("METIS_RTYPE_SEP2SIDED\n"); - break; - case METIS_RTYPE_SEP1SIDED: - printf("METIS_RTYPE_SEP1SIDED\n"); - break; - default: - printf("Unknown!\n"); - } - - printf(" Perform a 2-hop matching: %s\n", (ctrl->no2hop ? "Yes" : "No")); - - printf(" Number of balancing constraints: %"PRIDX"\n", ctrl->ncon); - printf(" Number of refinement iterations: %"PRIDX"\n", ctrl->niter); - printf(" Random number seed: %"PRIDX"\n", ctrl->seed); - - if (ctrl->optype == METIS_OP_OMETIS) { - printf(" Number of separators: %"PRIDX"\n", ctrl->nseps); - printf(" Compress graph prior to ordering: %s\n", (ctrl->compress ? "Yes" : "No")); - printf(" Detect & order connected components separately: %s\n", (ctrl->ccorder ? "Yes" : "No")); - printf(" Prunning factor for high degree vertices: %"PRREAL"\n", ctrl->pfactor); - } - else { - printf(" Number of partitions: %"PRIDX"\n", ctrl->nparts); - printf(" Number of cuts: %"PRIDX"\n", ctrl->ncuts); - printf(" User-supplied ufactor: %"PRIDX"\n", ctrl->ufactor); - - if (ctrl->optype == METIS_OP_KMETIS) { - printf(" Minimize connectivity: %s\n", (ctrl->minconn ? "Yes" : "No")); - printf(" Create contigous partitions: %s\n", (ctrl->contig ? "Yes" : "No")); - } - - modnum = (ctrl->ncon==1 ? 5 : (ctrl->ncon==2 ? 3 : (ctrl->ncon==3 ? 2 : 1))); - printf(" Target partition weights: "); - for (i=0; inparts; i++) { - if (i%modnum == 0) - printf("\n "); - printf("%4"PRIDX"=[", i); - for (j=0; jncon; j++) - printf("%s%.2e", (j==0 ? "" : " "), (double)ctrl->tpwgts[i*ctrl->ncon+j]); - printf("]"); - } - printf("\n"); - } - - printf(" Allowed maximum load imbalance: "); - for (i=0; incon; i++) - printf("%.3"PRREAL" ", ctrl->ubfactors[i]); - printf("\n"); - - printf("\n"); -} - - -/*************************************************************************/ -/*! This function checks the validity of user-supplied parameters */ -/*************************************************************************/ -int CheckParams(ctrl_t *ctrl) -{ - idx_t i, j; - real_t sum; - mdbglvl_et dbglvl=METIS_DBG_INFO; - - switch (ctrl->optype) { - case METIS_OP_PMETIS: - if (ctrl->objtype != METIS_OBJTYPE_CUT) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n")); - return 0; - } - if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n")); - return 0; - } - if (ctrl->iptype != METIS_IPTYPE_GROW && ctrl->iptype != METIS_IPTYPE_RANDOM) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n")); - return 0; - } - if (ctrl->rtype != METIS_RTYPE_FM) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n")); - return 0; - } - if (ctrl->ncuts <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncuts.\n")); - return 0; - } - if (ctrl->niter <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n")); - return 0; - } - if (ctrl->ufactor <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n")); - return 0; - } - if (ctrl->numflag != 0 && ctrl->numflag != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n")); - return 0; - } - if (ctrl->nparts <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n")); - return 0; - } - if (ctrl->ncon <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n")); - return 0; - } - - for (i=0; incon; i++) { - sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon); - if (sum < 0.99 || sum > 1.01) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect sum of %"PRREAL" for tpwgts for constraint %"PRIDX".\n", sum, i)); - return 0; - } - } - for (i=0; incon; i++) { - for (j=0; jnparts; j++) { - if (ctrl->tpwgts[j*ctrl->ncon+i] <= 0.0) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect tpwgts for partition %"PRIDX" and constraint %"PRIDX".\n", j, i)); - return 0; - } - } - } - - for (i=0; incon; i++) { - if (ctrl->ubfactors[i] <= 1.0) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i)); - return 0; - } - } - - break; - - case METIS_OP_KMETIS: - if (ctrl->objtype != METIS_OBJTYPE_CUT && ctrl->objtype != METIS_OBJTYPE_VOL) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n")); - return 0; - } - if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n")); - return 0; - } - if (ctrl->iptype != METIS_IPTYPE_METISRB) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n")); - return 0; - } - if (ctrl->rtype != METIS_RTYPE_GREEDY) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n")); - return 0; - } - if (ctrl->ncuts <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncuts.\n")); - return 0; - } - if (ctrl->niter <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n")); - return 0; - } - if (ctrl->ufactor <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n")); - return 0; - } - if (ctrl->numflag != 0 && ctrl->numflag != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n")); - return 0; - } - if (ctrl->nparts <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n")); - return 0; - } - if (ctrl->ncon <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n")); - return 0; - } - if (ctrl->contig != 0 && ctrl->contig != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect contig.\n")); - return 0; - } - if (ctrl->minconn != 0 && ctrl->minconn != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect minconn.\n")); - return 0; - } - - for (i=0; incon; i++) { - sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon); - if (sum < 0.99 || sum > 1.01) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect sum of %"PRREAL" for tpwgts for constraint %"PRIDX".\n", sum, i)); - return 0; - } - } - for (i=0; incon; i++) { - for (j=0; jnparts; j++) { - if (ctrl->tpwgts[j*ctrl->ncon+i] <= 0.0) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect tpwgts for partition %"PRIDX" and constraint %"PRIDX".\n", j, i)); - return 0; - } - } - } - - for (i=0; incon; i++) { - if (ctrl->ubfactors[i] <= 1.0) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i)); - return 0; - } - } - - break; - - - - case METIS_OP_OMETIS: - if (ctrl->objtype != METIS_OBJTYPE_NODE) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n")); - return 0; - } - if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n")); - return 0; - } - if (ctrl->iptype != METIS_IPTYPE_EDGE && ctrl->iptype != METIS_IPTYPE_NODE) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n")); - return 0; - } - if (ctrl->rtype != METIS_RTYPE_SEP1SIDED && ctrl->rtype != METIS_RTYPE_SEP2SIDED) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n")); - return 0; - } - if (ctrl->nseps <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nseps.\n")); - return 0; - } - if (ctrl->niter <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n")); - return 0; - } - if (ctrl->ufactor <= 0) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n")); - return 0; - } - if (ctrl->numflag != 0 && ctrl->numflag != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n")); - return 0; - } - if (ctrl->nparts != 3) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n")); - return 0; - } - if (ctrl->ncon != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n")); - return 0; - } - if (ctrl->compress != 0 && ctrl->compress != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect compress.\n")); - return 0; - } - if (ctrl->ccorder != 0 && ctrl->ccorder != 1) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ccorder.\n")); - return 0; - } - if (ctrl->pfactor < 0.0 ) { - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect pfactor.\n")); - return 0; - } - - for (i=0; incon; i++) { - if (ctrl->ubfactors[i] <= 1.0) { - IFSET(dbglvl, METIS_DBG_INFO, - printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i)); - return 0; - } - } - - break; - - default: - IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect optype\n")); - return 0; - } - - return 1; -} - - -/*************************************************************************/ -/*! This function frees the memory associated with a ctrl_t */ -/*************************************************************************/ -void FreeCtrl(ctrl_t **r_ctrl) -{ - ctrl_t *ctrl = *r_ctrl; - - FreeWorkSpace(ctrl); - - gk_free((void **)&ctrl->tpwgts, &ctrl->pijbm, - &ctrl->ubfactors, &ctrl->maxvwgt, &ctrl, LTERM); - - *r_ctrl = NULL; -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/parmetis.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/parmetis.c deleted file mode 100644 index 631d811bc3f..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/parmetis.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * parmetis.c - * - * This file contains top level routines that are used by ParMETIS - * - * Started 10/14/97 - * George - * - * $Id: parmetis.c 10481 2011-07-05 18:01:23Z karypis $ - * - */ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function is the entry point for the node ND code for ParMETIS. - The difference between this routine and the standard METIS_NodeND are - the following - - - It performs at least log2(npes) levels of nested dissection. - - It stores the size of the log2(npes) top-level separators in the - sizes array. -*/ -/*************************************************************************/ -int METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, - idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm, idx_t *sizes) -{ - idx_t i, ii, j, l, nnvtxs=0; - graph_t *graph; - ctrl_t *ctrl; - idx_t *cptr, *cind; - - ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL); - if (!ctrl) return METIS_ERROR_INPUT; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); - - /* compress the graph; not that compression only happens if not prunning - has taken place. */ - if (ctrl->compress) { - cptr = imalloc(nvtxs+1, "OMETIS: cptr"); - cind = imalloc(nvtxs, "OMETIS: cind"); - - graph = CompressGraph(ctrl, nvtxs, xadj, adjncy, vwgt, cptr, cind); - if (graph == NULL) { - /* if there was no compression, cleanup the compress flag */ - gk_free((void **)&cptr, &cind, LTERM); - ctrl->compress = 0; - } - else { - nnvtxs = graph->nvtxs; - } - } - - /* if no compression, setup the graph in the normal way. */ - if (ctrl->compress == 0) - graph = SetupGraph(ctrl, nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); - - - /* allocate workspace memory */ - AllocateWorkSpace(ctrl, graph); - - - /* do the nested dissection ordering */ - iset(2*npes-1, 0, sizes); - MlevelNestedDissectionP(ctrl, graph, iperm, graph->nvtxs, npes, 0, sizes); - - - /* Uncompress the ordering */ - if (ctrl->compress) { - /* construct perm from iperm */ - for (i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); - - /* clean up */ - FreeCtrl(&ctrl); - - return METIS_OK; -} - - -/*************************************************************************/ -/*! This function is similar to MlevelNestedDissection with the difference - that it also records separator sizes for the top log2(npes) levels */ -/**************************************************************************/ -void MlevelNestedDissectionP(ctrl_t *ctrl, graph_t *graph, idx_t *order, - idx_t lastvtx, idx_t npes, idx_t cpos, idx_t *sizes) -{ - idx_t i, j, nvtxs, nbnd; - idx_t *label, *bndind; - graph_t *lgraph, *rgraph; - - nvtxs = graph->nvtxs; - - if (nvtxs == 0) { - FreeGraph(&graph); - return; - } - - MlevelNodeBisectionMultiple(ctrl, graph); - - IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, - printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", - graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); - - if (cpos < npes-1) { - sizes[2*npes-2-cpos] = graph->pwgts[2]; - sizes[2*npes-2-(2*cpos+1)] = graph->pwgts[1]; - sizes[2*npes-2-(2*cpos+2)] = graph->pwgts[0]; - } - - /* Order the nodes in the separator */ - nbnd = graph->nbnd; - bndind = graph->bndind; - label = graph->label; - for (i=0; invtxs > MMDSWITCH || 2*cpos+2 < npes-1) && lgraph->nedges > 0) - MlevelNestedDissectionP(ctrl, lgraph, order, lastvtx-rgraph->nvtxs, npes, 2*cpos+2, sizes); - else { - MMDOrder(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); - FreeGraph(&lgraph); - } - if ((rgraph->nvtxs > MMDSWITCH || 2*cpos+1 < npes-1) && rgraph->nedges > 0) - MlevelNestedDissectionP(ctrl, rgraph, order, lastvtx, npes, 2*cpos+1, sizes); - else { - MMDOrder(ctrl, rgraph, order, lastvtx); - FreeGraph(&rgraph); - } -} - - -/*************************************************************************/ -/*! This function bisects a graph by computing a vertex separator */ -/**************************************************************************/ -int METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *options, idx_t *r_sepsize, idx_t *part) -{ - idx_t i, j; - graph_t *graph; - ctrl_t *ctrl; - - if ((ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL)) == NULL) - return METIS_ERROR_INPUT; - - InitRandom(ctrl->seed); - - graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); - - AllocateWorkSpace(ctrl, graph); - - /*============================================================ - * Perform the bisection - *============================================================*/ - ctrl->CoarsenTo = 100; - - MlevelNodeBisectionMultiple(ctrl, graph); - - *r_sepsize = graph->pwgts[2]; - icopy(*nvtxs, graph->where, part); - - FreeGraph(&graph); - - FreeCtrl(&ctrl); - - return METIS_OK; -} - - -/*************************************************************************/ -/*! This function is the entry point of a node-based separator refinement - of the nodes with an hmarker[] of 0. */ -/*************************************************************************/ -int METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy, - idx_t *where, idx_t *hmarker, real_t ubfactor) -{ - graph_t *graph; - ctrl_t *ctrl; - - /* set up the run time parameters */ - ctrl = SetupCtrl(METIS_OP_OMETIS, NULL, 1, 3, NULL, NULL); - if (!ctrl) return METIS_ERROR_INPUT; - - /* set up the graph */ - graph = SetupGraph(ctrl, nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); - - /* allocate workspace memory */ - AllocateWorkSpace(ctrl, graph); - - /* set up the memory and the input partition */ - Allocate2WayNodePartitionMemory(ctrl, graph); - icopy(nvtxs, where, graph->where); - - Compute2WayNodePartitionParams(ctrl, graph); - - FM_2WayNodeRefine1SidedP(ctrl, graph, hmarker, ubfactor, 10); - /* FM_2WayNodeRefine2SidedP(ctrl, graph, hmarker, ubfactor, 10); */ - - icopy(nvtxs, graph->where, where); - - FreeGraph(&graph); - FreeCtrl(&ctrl); - - return METIS_OK; -} - - -/*************************************************************************/ -/*! This function performs a node-based 1-sided FM refinement that moves - only nodes whose hmarker[] == -1. It is used by Parmetis. */ -/*************************************************************************/ -void FM_2WayNodeRefine1SidedP(ctrl_t *ctrl, graph_t *graph, - idx_t *hmarker, real_t ubfactor, idx_t npasses) -{ - idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind, nbad, qsize; - idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; - idx_t *mptr, *mind, *swaps, *inqueue; - rpq_t *queue; - nrinfo_t *rinfo; - idx_t higain, oldgain, mincut, initcut, mincutorder; - idx_t pass, from, to, limit; - idx_t badmaxpwgt, mindiff, newdiff; - - WCOREPUSH; - - ASSERT(graph->mincut == graph->pwgts[2]); - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - where = graph->where; - pwgts = graph->pwgts; - rinfo = graph->nrinfo; - - queue = rpqCreate(nvtxs); - - inqueue = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - swaps = iwspacemalloc(ctrl, nvtxs); - mptr = iwspacemalloc(ctrl, nvtxs+1); - mind = iwspacemalloc(ctrl, 2*nvtxs); - - badmaxpwgt = (idx_t)(ubfactor*gk_max(pwgts[0], pwgts[1])); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions-N1: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"] " - "MaxPwgt[%6"PRIDX"]. ISep: %6"PRIDX"\n", - pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, badmaxpwgt, - graph->mincut)); - - to = (pwgts[0] < pwgts[1] ? 1 : 0); - for (pass=0; passmincut; - nbnd = graph->nbnd; - - /* use the swaps array in place of the traditional perm array to save memory */ - irandArrayPermute(nbnd, swaps, nbnd, 1); - for (ii=0; ii= 2*nvtxs-1) - break; - - inqueue[higain] = -1; - - if (pwgts[to]+vwgt[higain] > badmaxpwgt) { /* Skip this vertex */ - if (nbad++ > limit) - break; - else { - nswaps--; - continue; - } - } - - pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[from]); - - newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[from]-rinfo[higain].edegrees[from])); - if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { - mincut = pwgts[2]; - mincutorder = nswaps; - mindiff = newdiff; - nbad = 0; - } - else { - if (nbad++ > limit) { - pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[from]); - break; /* No further improvement, break out */ - } - } - - BNDDelete(nbnd, bndind, bndptr, higain); - pwgts[to] += vwgt[higain]; - where[higain] = to; - swaps[nswaps] = higain; - - - /********************************************************** - * Update the degrees of the affected nodes - ***********************************************************/ - for (j=xadj[higain]; jdbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"] [%3"PRIDX" %2"PRIDX"]\n", - higain, to, (vwgt[higain]-rinfo[higain].edegrees[from]), - vwgt[higain], pwgts[0], pwgts[1], pwgts[2], nswaps, limit)); - - } - - - /**************************************************************** - * Roll back computation - *****************************************************************/ - for (nswaps--; nswaps>mincutorder; nswaps--) { - higain = swaps[nswaps]; - - ASSERT(CheckNodePartitionParams(graph)); - ASSERT(where[higain] == to); - - INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); - where[higain] = 2; - BNDInsert(nbnd, bndind, bndptr, higain); - - edegrees = rinfo[higain].edegrees; - edegrees[0] = edegrees[1] = 0; - for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, - printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX", QSIZE: %6"PRIDX"\n", - mincut, mincutorder, pwgts[0], pwgts[1], nbnd, qsize)); - - graph->mincut = mincut; - graph->nbnd = nbnd; - - if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut)) - break; - } - - rpqDestroy(queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function performs a node-based (two-sided) FM refinement that - moves only nodes whose hmarker[] == -1. It is used by Parmetis. */ -/*************************************************************************/ -void FM_2WayNodeRefine2SidedP(ctrl_t *ctrl, graph_t *graph, - idx_t *hmarker, real_t ubfactor, idx_t npasses) -{ - idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind; - idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; - idx_t *mptr, *mind, *moved, *swaps; - rpq_t *queues[2]; - nrinfo_t *rinfo; - idx_t higain, oldgain, mincut, initcut, mincutorder; - idx_t pass, to, other, limit; - idx_t badmaxpwgt, mindiff, newdiff; - idx_t u[2], g[2]; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - where = graph->where; - pwgts = graph->pwgts; - rinfo = graph->nrinfo; - - queues[0] = rpqCreate(nvtxs); - queues[1] = rpqCreate(nvtxs); - - moved = iwspacemalloc(ctrl, nvtxs); - swaps = iwspacemalloc(ctrl, nvtxs); - mptr = iwspacemalloc(ctrl, nvtxs+1); - mind = iwspacemalloc(ctrl, 2*nvtxs); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); - - badmaxpwgt = (idx_t)(ubfactor*gk_max(pwgts[0], pwgts[1])); - - for (pass=0; passmincut; - nbnd = graph->nbnd; - - /* use the swaps array in place of the traditional perm array to save memory */ - irandArrayPermute(nbnd, swaps, nbnd, 1); - for (ii=0; ii g[1] ? 0 : (g[0] < g[1] ? 1 : pass%2)); - - if (pwgts[to]+vwgt[u[to]] > badmaxpwgt) - to = (to+1)%2; - } - else if (u[0] == -1 && u[1] == -1) { - break; - } - else if (u[0] != -1 && pwgts[0]+vwgt[u[0]] <= badmaxpwgt) { - to = 0; - } - else if (u[1] != -1 && pwgts[1]+vwgt[u[1]] <= badmaxpwgt) { - to = 1; - } - else - break; - - other = (to+1)%2; - - higain = rpqGetTop(queues[to]); - - /* Delete its matching entry in the other queue */ - if (moved[higain] == -5) - rpqDelete(queues[other], higain); - - ASSERT(bndptr[higain] != -1); - - /* The following check is to ensure we break out if there is a posibility - of over-running the mind array. */ - if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1) - break; - - pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]); - - newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other])); - if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { - mincut = pwgts[2]; - mincutorder = nswaps; - mindiff = newdiff; - } - else { - if (nswaps - mincutorder > limit) { - pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]); - break; /* No further improvement, break out */ - } - } - - BNDDelete(nbnd, bndind, bndptr, higain); - pwgts[to] += vwgt[higain]; - where[higain] = to; - moved[higain] = nswaps; - swaps[nswaps] = higain; - - - /********************************************************** - * Update the degrees of the affected nodes - ***********************************************************/ - for (j=xadj[higain]; jdbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] " - "[%4"PRIDX" %4"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", - higain, to, g[to], g[other], vwgt[u[to]], vwgt[u[other]], - pwgts[0], pwgts[1], pwgts[2])); - - } - - - /**************************************************************** - * Roll back computation - *****************************************************************/ - for (nswaps--; nswaps>mincutorder; nswaps--) { - higain = swaps[nswaps]; - - ASSERT(CheckNodePartitionParams(graph)); - - to = where[higain]; - other = (to+1)%2; - INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); - where[higain] = 2; - BNDInsert(nbnd, bndind, bndptr, higain); - - edegrees = rinfo[higain].edegrees; - edegrees[0] = edegrees[1] = 0; - for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, - printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd)); - - graph->mincut = mincut; - graph->nbnd = nbnd; - - if (mincutorder == -1 || mincut >= initcut) - break; - } - - rpqDestroy(queues[0]); - rpqDestroy(queues[1]); - - WCOREPOP; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/pmetis.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/pmetis.c deleted file mode 100644 index d32e84921fd..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/pmetis.c +++ /dev/null @@ -1,387 +0,0 @@ -/** -\file -\brief This file contains the top level routines for the multilevel recursive bisection - algorithm PMETIS. - -\date Started 7/24/1997 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version\verbatim $Id: pmetis.c 10513 2011-07-07 22:06:03Z karypis $ \endverbatim -*/ - - -#include "metislib.h" - - -/*************************************************************************/ -/*! \ingroup api - \brief Recursive partitioning routine. - - This function computes a partitioning of a graph based on multilevel - recursive bisection. It can be used to partition a graph into \e k - parts. The objective of the partitioning is to minimize the edgecut - subject to one or more balancing constraints. - - \param[in] nvtxs is the number of vertices in the graph. - - \param[in] ncon is the number of balancing constraints. For the standard - partitioning problem in which each vertex is either unweighted - or has a single weight, ncon should be 1. - - \param[in] xadj is an array of size nvtxs+1 used to specify the starting - positions of the adjacency structure of the vertices in the - adjncy array. - - \param[in] adjncy is an array of size to the sum of the degrees of the - graph that stores for each vertex the set of vertices that - is adjancent to. - - \param[in] vwgt is an array of size nvtxs*ncon that stores the weights - of the vertices for each constraint. The ncon weights for the - ith vertex are stored in the ncon consecutive locations starting - at vwgt[i*ncon]. When ncon==1, a NULL value can be passed indicating - that all the vertices in the graph have the same weight. - - \param[in] adjwgt is an array of size equal to adjncy, specifying the weight - for each edge (i.e., adjwgt[j] corresponds to the weight of the - edge stored in adjncy[j]). - A NULL value can be passed indicating that all the edges in the - graph have the same weight. - - \param[in] nparts is the number of desired partitions. - - \param[in] tpwgts is an array of size nparts*ncon that specifies the - desired weight for each part and constraint. The \e{target partition - weight} for the ith part and jth constraint is specified - at tpwgts[i*ncon+j] (the numbering of i and j starts from 0). - For each constraint, the sum of the tpwgts[] entries must be - 1.0 (i.e., \f$ \sum_i tpwgts[i*ncon+j] = 1.0 \f$). - A NULL value can be passed indicating that the graph should - be equally divided among the parts. - - \param[in] ubvec is an array of size ncon that specifies the allowed - load imbalance tolerance for each constraint. - For the ith part and jth constraint the allowed weight is the - ubvec[j]*tpwgts[i*ncon+j] fraction of the jth's constraint total - weight. The load imbalances must be greater than 1.0. - A NULL value can be passed indicating that the load imbalance - tolerance for each constraint should be 1.001 (for ncon==1) - or 1.01 (for ncon>1). - - \params[in] options is the array for passing additional parameters - in order to customize the behaviour of the partitioning - algorithm. - - \params[out] edgecut stores the cut of the partitioning. - - \params[out] part is an array of size nvtxs used to store the - computed partitioning. The partition number for the ith - vertex is stored in part[i]. Based on the numflag parameter, - the numbering of the parts starts from either 0 or 1. - - - \returns - \retval METIS_OK indicates that the function returned normally. - \retval METIS_ERROR_INPUT indicates an input error. - \retval METIS_ERROR_MEMORY indicates that it could not allocate - the required memory. - -*/ -/*************************************************************************/ -int METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, - idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, - idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, - idx_t *objval, idx_t *part) -{ - int sigrval=0, renumber=0; - graph_t *graph; - ctrl_t *ctrl; - - /* set up malloc cleaning code and signal catchers */ - if (!gk_malloc_init()) - return METIS_ERROR_MEMORY; - - gk_sigtrap(); - - if ((sigrval = gk_sigcatch()) != 0) - goto SIGTHROW; - - - /* set up the run parameters */ - ctrl = SetupCtrl(METIS_OP_PMETIS, options, *ncon, *nparts, tpwgts, ubvec); - if (!ctrl) { - gk_siguntrap(); - return METIS_ERROR_INPUT; - } - - /* if required, change the numbering to 0 */ - if (ctrl->numflag == 1) { - Change2CNumbering(*nvtxs, xadj, adjncy); - renumber = 1; - } - - /* set up the graph */ - graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt); - - /* allocate workspace memory */ - AllocateWorkSpace(ctrl, graph); - - /* start the partitioning */ - IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); - - *objval = MlevelRecursiveBisection(ctrl, graph, *nparts, part, ctrl->tpwgts, 0); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); - - /* clean up */ - FreeCtrl(&ctrl); - -SIGTHROW: - /* if required, change the numbering back to 1 */ - if (renumber) - Change2FNumbering(*nvtxs, xadj, adjncy, part); - - gk_siguntrap(); - gk_malloc_cleanup(0); - - return metis_rcode(sigrval); -} - - -/*************************************************************************/ -/*! This function is the top-level driver of the recursive bisection - routine. */ -/*************************************************************************/ -idx_t MlevelRecursiveBisection(ctrl_t *ctrl, graph_t *graph, idx_t nparts, - idx_t *part, real_t *tpwgts, idx_t fpart) -{ - idx_t i, j, nvtxs, ncon, objval; - idx_t *label, *where; - graph_t *lgraph, *rgraph; - real_t wsum, *tpwgts2; - - if ((nvtxs = graph->nvtxs) == 0) { - printf("\t***Cannot bisect a graph with 0 vertices!\n" - "\t***You are trying to partition a graph into too many parts!\n"); - return 0; - } - - ncon = graph->ncon; - - /* determine the weights of the two partitions as a function of the weight of the - target partition weights */ - WCOREPUSH; - tpwgts2 = rwspacemalloc(ctrl, 2*ncon); - for (i=0; i>1), tpwgts+i, ncon); - tpwgts2[ncon+i] = 1.0 - tpwgts2[i]; - } - - /* perform the bisection */ - objval = MultilevelBisect(ctrl, graph, tpwgts2); - - WCOREPOP; - - label = graph->label; - where = graph->where; - for (i=0; i 2) - SplitGraphPart(ctrl, graph, &lgraph, &rgraph); - - /* Free the memory of the top level graph */ - FreeGraph(&graph); - - /* Scale the fractions in the tpwgts according to the true weight */ - for (i=0; i>1), tpwgts+i, ncon); - rscale((nparts>>1), 1.0/wsum, tpwgts+i, ncon); - rscale(nparts-(nparts>>1), 1.0/(1.0-wsum), tpwgts+(nparts>>1)*ncon+i, ncon); - } - - /* Do the recursive call */ - if (nparts > 3) { - objval += MlevelRecursiveBisection(ctrl, lgraph, (nparts>>1), part, - tpwgts, fpart); - objval += MlevelRecursiveBisection(ctrl, rgraph, nparts-(nparts>>1), part, - tpwgts+(nparts>>1)*ncon, fpart+(nparts>>1)); - } - else if (nparts == 3) { - FreeGraph(&lgraph); - objval += MlevelRecursiveBisection(ctrl, rgraph, nparts-(nparts>>1), part, - tpwgts+(nparts>>1)*ncon, fpart+(nparts>>1)); - } - - - return objval; -} - - -/*************************************************************************/ -/*! This function performs a multilevel bisection */ -/*************************************************************************/ -idx_t MultilevelBisect(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts) -{ - idx_t i, niparts, bestobj=0, curobj=0, *bestwhere=NULL; - graph_t *cgraph; - real_t bestbal=0.0, curbal=0.0; - - Setup2WayBalMultipliers(ctrl, graph, tpwgts); - - WCOREPUSH; - - if (ctrl->ncuts > 1) - bestwhere = iwspacemalloc(ctrl, graph->nvtxs); - - for (i=0; incuts; i++) { - cgraph = CoarsenGraph(ctrl, graph); - - niparts = (cgraph->nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS); - Init2WayPartition(ctrl, cgraph, tpwgts, niparts); - - Refine2Way(ctrl, graph, cgraph, tpwgts); - - curobj = graph->mincut; - curbal = ComputeLoadImbalanceDiff(graph, 2, ctrl->pijbm, ctrl->ubfactors); - - if (i == 0 - || (curbal <= 0.0005 && bestobj > curobj) - || (bestbal > 0.0005 && curbal < bestbal)) { - bestobj = curobj; - bestbal = curbal; - if (i < ctrl->ncuts-1) - icopy(graph->nvtxs, graph->where, bestwhere); - } - - if (bestobj == 0) - break; - - if (i < ctrl->ncuts-1) - FreeRData(graph); - } - - if (bestobj != curobj) { - icopy(graph->nvtxs, bestwhere, graph->where); - Compute2WayPartitionParams(ctrl, graph); - } - - WCOREPOP; - - return bestobj; -} - - -/*************************************************************************/ -/*! This function splits a graph into two based on its bisection */ -/*************************************************************************/ -void SplitGraphPart(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, - graph_t **r_rgraph) -{ - idx_t i, j, k, l, istart, iend, mypart, nvtxs, ncon, snvtxs[2], snedges[2]; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr; - idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2]; - idx_t *rename; - idx_t *auxadjncy, *auxadjwgt; - graph_t *lgraph, *rgraph; - - WCOREPUSH; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - label = graph->label; - where = graph->where; - bndptr = graph->bndptr; - - ASSERT(bndptr != NULL); - - rename = iwspacemalloc(ctrl, nvtxs); - - snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0; - for (i=0; ixadj; - svwgt[0] = lgraph->vwgt; - sadjncy[0] = lgraph->adjncy; - sadjwgt[0] = lgraph->adjwgt; - slabel[0] = lgraph->label; - - rgraph = SetupSplitGraph(graph, snvtxs[1], snedges[1]); - sxadj[1] = rgraph->xadj; - svwgt[1] = rgraph->vwgt; - sadjncy[1] = rgraph->adjncy; - sadjwgt[1] = rgraph->adjwgt; - slabel[1] = rgraph->label; - - snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0; - sxadj[0][0] = sxadj[1][0] = 0; - for (i=0; inedges = snedges[0]; - rgraph->nedges = snedges[1]; - - SetupGraph_tvwgt(lgraph); - SetupGraph_tvwgt(rgraph); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); - - *r_lgraph = lgraph; - *r_rgraph = rgraph; - - WCOREPOP; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/proto.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/proto.h deleted file mode 100644 index f852ff59e33..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/proto.h +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * proto.h - * - * This file contains header files - * - * Started 10/19/95 - * George - * - * $Id: proto.h 13933 2013-03-29 22:20:46Z karypis $ - * - */ - -#ifndef _LIBMETIS_PROTO_H_ -#define _LIBMETIS_PROTO_H_ - -/* auxapi.c */ - -/* balance.c */ -void Balance2Way(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts); -void Bnd2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts); -void General2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts); -void McGeneral2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts); - - -/* bucketsort.c */ -void BucketSortKeysInc(ctrl_t *ctrl, idx_t n, idx_t max, idx_t *keys, - idx_t *tperm, idx_t *perm); - - -/* checkgraph.c */ -int CheckGraph(graph_t *graph, int numflag, int verbose); -int CheckInputGraphWeights(idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *vsize, idx_t *adjwgt); -graph_t *FixGraph(graph_t *graph); - - -/* coarsen.c */ -graph_t *CoarsenGraph(ctrl_t *ctrl, graph_t *graph); -graph_t *CoarsenGraphNlevels(ctrl_t *ctrl, graph_t *graph, idx_t nlevels); -idx_t Match_RM(ctrl_t *ctrl, graph_t *graph); -idx_t Match_SHEM(ctrl_t *ctrl, graph_t *graph); -idx_t Match_2Hop(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, - idx_t cnvtxs, size_t nunmatched); -idx_t Match_2HopAny(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, - idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree); -idx_t Match_2HopAll(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, - idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree); -void PrintCGraphStats(ctrl_t *ctrl, graph_t *graph); -void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, - idx_t *match); -void CreateCoarseGraphNoMask(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, - idx_t *match); -void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, - idx_t *match, idx_t *perm); -graph_t *SetupCoarseGraph(graph_t *graph, idx_t cnvtxs, idx_t dovsize); -void ReAdjustMemory(ctrl_t *ctrl, graph_t *graph, graph_t *cgraph); - - - -/* compress.c */ -graph_t *CompressGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *cptr, idx_t *cind); -graph_t *PruneGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, - idx_t *vwgt, idx_t *iperm, real_t factor); - - -/* contig.c */ -idx_t FindPartitionInducedComponents(graph_t *graph, idx_t *where, - idx_t *cptr, idx_t *cind); -void ComputeBFSOrdering(ctrl_t *ctrl, graph_t *graph, idx_t *bfsperm); -idx_t IsConnected(graph_t *graph, idx_t report); -idx_t IsConnectedSubdomain(ctrl_t *, graph_t *, idx_t, idx_t); -idx_t FindSepInducedComponents(ctrl_t *, graph_t *, idx_t *, idx_t *); -void EliminateComponents(ctrl_t *ctrl, graph_t *graph); -void MoveGroupContigForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid, - idx_t *ptr, idx_t *ind); -void MoveGroupContigForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid, - idx_t *ptr, idx_t *ind, idx_t *vmarker, idx_t *pmarker, - idx_t *modind); - - -/* debug.c */ -idx_t ComputeCut(graph_t *graph, idx_t *where); -idx_t ComputeVolume(graph_t *, idx_t *); -idx_t ComputeMaxCut(graph_t *graph, idx_t nparts, idx_t *where); -idx_t CheckBnd(graph_t *); -idx_t CheckBnd2(graph_t *); -idx_t CheckNodeBnd(graph_t *, idx_t); -idx_t CheckRInfo(ctrl_t *ctrl, ckrinfo_t *rinfo); -idx_t CheckNodePartitionParams(graph_t *); -idx_t IsSeparable(graph_t *); -void CheckKWayVolPartitionParams(ctrl_t *ctrl, graph_t *graph); - - -/* fm.c */ -void FM_2WayRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter); -void FM_2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter); -void FM_Mc2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter); -void SelectQueue(graph_t *graph, real_t *pijbm, real_t *ubfactors, rpq_t **queues, - idx_t *from, idx_t *cnum); -void Print2WayRefineStats(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, - real_t deltabal, idx_t mincutorder); - - -/* fortran.c */ -void Change2CNumbering(idx_t, idx_t *, idx_t *); -void Change2FNumbering(idx_t, idx_t *, idx_t *, idx_t *); -void Change2FNumbering2(idx_t, idx_t *, idx_t *); -void Change2FNumberingOrder(idx_t, idx_t *, idx_t *, idx_t *, idx_t *); -void ChangeMesh2CNumbering(idx_t n, idx_t *ptr, idx_t *ind); -void ChangeMesh2FNumbering(idx_t n, idx_t *ptr, idx_t *ind, idx_t nvtxs, - idx_t *xadj, idx_t *adjncy); -void ChangeMesh2FNumbering2(idx_t ne, idx_t nn, idx_t *ptr, idx_t *ind, - idx_t *epart, idx_t *npart); - - -/* graph.c */ -graph_t *SetupGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t ncon, idx_t *xadj, - idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt); -void SetupGraph_tvwgt(graph_t *graph); -void SetupGraph_label(graph_t *graph); -graph_t *SetupSplitGraph(graph_t *graph, idx_t snvtxs, idx_t snedges); -graph_t *CreateGraph(void); -void InitGraph(graph_t *graph); -void FreeRData(graph_t *graph); -void FreeGraph(graph_t **graph); - - -/* initpart.c */ -void Init2WayPartition(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); -void InitSeparator(ctrl_t *ctrl, graph_t *graph, idx_t niparts); -void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); -void GrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); -void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); -void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); -void GrowBisectionNode(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); -void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts); - - -/* kmetis.c */ -idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part); -void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph); - - -/* kwayfm.c */ -void Greedy_KWayOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode); -void Greedy_KWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode); -void Greedy_KWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode); -void Greedy_McKWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode); -void Greedy_McKWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, - real_t ffactor, idx_t omode); -idx_t IsArticulationNode(idx_t i, idx_t *xadj, idx_t *adjncy, idx_t *where, - idx_t *bfslvl, idx_t *bfsind, idx_t *bfsmrk); -void KWayVolUpdate(ctrl_t *ctrl, graph_t *graph, idx_t v, idx_t from, - idx_t to, ipq_t *queue, idx_t *vstatus, idx_t *r_nupd, idx_t *updptr, - idx_t *updind, idx_t bndtype, idx_t *vmarker, idx_t *pmarker, - idx_t *modind); - - -/* kwayrefine.c */ -void RefineKWay(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph); -void AllocateKWayPartitionMemory(ctrl_t *ctrl, graph_t *graph); -void ComputeKWayPartitionParams(ctrl_t *ctrl, graph_t *graph); -void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph); -void ComputeKWayBoundary(ctrl_t *ctrl, graph_t *graph, idx_t bndtype); -void ComputeKWayVolGains(ctrl_t *ctrl, graph_t *graph); -int IsBalanced(ctrl_t *ctrl, graph_t *graph, real_t ffactor); - - -/* mcutil.c */ -int rvecle(idx_t n, real_t *x, real_t *y); -int rvecge(idx_t n, real_t *x, real_t *y); -int rvecsumle(idx_t n, real_t *x1, real_t *x2, real_t *y); -real_t rvecmaxdiff(idx_t n, real_t *x, real_t *y); -int ivecle(idx_t n, idx_t *x, idx_t *z); -int ivecge(idx_t n, idx_t *x, idx_t *z); -int ivecaxpylez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z); -int ivecaxpygez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z); -int BetterVBalance(idx_t ncon, real_t *itvwgt, idx_t *v_vwgt, idx_t *u1_vwgt, - idx_t *u2_vwgt); -int BetterBalance2Way(idx_t n, real_t *x, real_t *y); -int BetterBalanceKWay(idx_t ncon, idx_t *vwgt, real_t *itvwgt, idx_t a1, - idx_t *pt1, real_t *bm1, idx_t a2, idx_t *pt2, real_t *bm2); -real_t ComputeLoadImbalance(graph_t *graph, idx_t nparts, real_t *pijbm); -real_t ComputeLoadImbalanceDiff(graph_t *graph, idx_t nparts, real_t *pijbm, - real_t *ubvec); -real_t ComputeLoadImbalanceDiffVec(graph_t *graph, idx_t nparts, real_t *pijbm, - real_t *ubfactors, real_t *diffvec); -void ComputeLoadImbalanceVec(graph_t *graph, idx_t nparts, real_t *pijbm, - real_t *lbvec); - - -/* mesh.c */ -void CreateGraphDual(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t ncommon, - idx_t **r_xadj, idx_t **r_adjncy); -idx_t FindCommonElements(idx_t qid, idx_t elen, idx_t *eind, idx_t *nptr, - idx_t *nind, idx_t *eptr, idx_t ncommon, idx_t *marker, idx_t *nbrs); -void CreateGraphNodal(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t **r_xadj, - idx_t **r_adjncy); -idx_t FindCommonNodes(idx_t qid, idx_t nelmnts, idx_t *elmntids, idx_t *eptr, - idx_t *eind, idx_t *marker, idx_t *nbrs); -mesh_t *CreateMesh(void); -void InitMesh(mesh_t *mesh); -void FreeMesh(mesh_t **mesh); - - -/* meshpart.c */ -void InduceRowPartFromColumnPart(idx_t nrows, idx_t *rowptr, idx_t *rowind, - idx_t *rpart, idx_t *cpart, idx_t nparts, real_t *tpwgts); - - -/* minconn.c */ -void ComputeSubDomainGraph(ctrl_t *ctrl, graph_t *graph); -void UpdateEdgeSubDomainGraph(ctrl_t *ctrl, idx_t u, idx_t v, idx_t ewgt, - idx_t *r_maxndoms); -void PrintSubDomainGraph(graph_t *graph, idx_t nparts, idx_t *where); -void EliminateSubDomainEdges(ctrl_t *ctrl, graph_t *graph); -void MoveGroupMinConnForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, - idx_t *ind); -void MoveGroupMinConnForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, - idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind); - - -/* mincover.o */ -void MinCover(idx_t *, idx_t *, idx_t, idx_t, idx_t *, idx_t *); -idx_t MinCover_Augment(idx_t *, idx_t *, idx_t, idx_t *, idx_t *, idx_t *, idx_t); -void MinCover_Decompose(idx_t *, idx_t *, idx_t, idx_t, idx_t *, idx_t *, idx_t *); -void MinCover_ColDFS(idx_t *, idx_t *, idx_t, idx_t *, idx_t *, idx_t); -void MinCover_RowDFS(idx_t *, idx_t *, idx_t, idx_t *, idx_t *, idx_t); - - -/* mmd.c */ -void genmmd(idx_t, idx_t *, idx_t *, idx_t *, idx_t *, idx_t , idx_t *, idx_t *, idx_t *, idx_t *, idx_t, idx_t *); -void mmdelm(idx_t, idx_t *xadj, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t, idx_t); -idx_t mmdint(idx_t, idx_t *xadj, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *); -void mmdnum(idx_t, idx_t *, idx_t *, idx_t *); -void mmdupd(idx_t, idx_t, idx_t *, idx_t *, idx_t, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t *, idx_t, idx_t *tag); - - -/* ometis.c */ -void MlevelNestedDissection(ctrl_t *ctrl, graph_t *graph, idx_t *order, - idx_t lastvtx); -void MlevelNestedDissectionCC(ctrl_t *ctrl, graph_t *graph, idx_t *order, - idx_t lastvtx); -void MlevelNodeBisectionMultiple(ctrl_t *ctrl, graph_t *graph); -void MlevelNodeBisectionL2(ctrl_t *ctrl, graph_t *graph, idx_t niparts); -void MlevelNodeBisectionL1(ctrl_t *ctrl, graph_t *graph, idx_t niparts); -void SplitGraphOrder(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, - graph_t **r_rgraph); -graph_t **SplitGraphOrderCC(ctrl_t *ctrl, graph_t *graph, idx_t ncmps, - idx_t *cptr, idx_t *cind); -void MMDOrder(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx); - - -/* options.c */ -ctrl_t *SetupCtrl(moptype_et optype, idx_t *options, idx_t ncon, idx_t nparts, - real_t *tpwgts, real_t *ubvec); -void SetupKWayBalMultipliers(ctrl_t *ctrl, graph_t *graph); -void Setup2WayBalMultipliers(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts); -void PrintCtrl(ctrl_t *ctrl); -int CheckParams(ctrl_t *ctrl); -void FreeCtrl(ctrl_t **r_ctrl); - - -/* parmetis.c */ -void MlevelNestedDissectionP(ctrl_t *ctrl, graph_t *graph, idx_t *order, - idx_t lastvtx, idx_t npes, idx_t cpos, idx_t *sizes); -void FM_2WayNodeRefine1SidedP(ctrl_t *ctrl, graph_t *graph, idx_t *hmarker, - real_t ubfactor, idx_t npasses); -void FM_2WayNodeRefine2SidedP(ctrl_t *ctrl, graph_t *graph, idx_t *hmarker, - real_t ubfactor, idx_t npasses); - - -/* pmetis.c */ -idx_t MlevelRecursiveBisection(ctrl_t *ctrl, graph_t *graph, idx_t nparts, - idx_t *part, real_t *tpwgts, idx_t fpart); -idx_t MultilevelBisect(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts); -void SplitGraphPart(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, graph_t **r_rgraph); - - -/* refine.c */ -void Refine2Way(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph, real_t *rtpwgts); -void Allocate2WayPartitionMemory(ctrl_t *ctrl, graph_t *graph); -void Compute2WayPartitionParams(ctrl_t *ctrl, graph_t *graph); -void Project2WayPartition(ctrl_t *ctrl, graph_t *graph); - - -/* separator.c */ -void ConstructSeparator(ctrl_t *ctrl, graph_t *graph); -void ConstructMinCoverSeparator(ctrl_t *ctrl, graph_t *graph); - - -/* sfm.c */ -void FM_2WayNodeRefine2Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter); -void FM_2WayNodeRefine1Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter); -void FM_2WayNodeBalance(ctrl_t *ctrl, graph_t *graph); - - -/* srefine.c */ -void Refine2WayNode(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph); -void Allocate2WayNodePartitionMemory(ctrl_t *ctrl, graph_t *graph); -void Compute2WayNodePartitionParams(ctrl_t *ctrl, graph_t *graph); -void Project2WayNodePartition(ctrl_t *ctrl, graph_t *graph); - - -/* stat.c */ -void ComputePartitionInfoBipartite(graph_t *, idx_t, idx_t *); -void ComputePartitionBalance(graph_t *, idx_t, idx_t *, real_t *); -real_t ComputeElementBalance(idx_t, idx_t, idx_t *); - - -/* timing.c */ -void InitTimers(ctrl_t *); -void PrintTimers(ctrl_t *); - -/* util.c */ -idx_t iargmax_strd(size_t, idx_t *, idx_t); -idx_t iargmax_nrm(size_t n, idx_t *x, real_t *y); -idx_t iargmax2_nrm(size_t n, idx_t *x, real_t *y); -idx_t rargmax2(size_t, real_t *); -void InitRandom(idx_t); -int metis_rcode(int sigrval); - - - -/* wspace.c */ -void AllocateWorkSpace(ctrl_t *ctrl, graph_t *graph); -void AllocateRefinementWorkSpace(ctrl_t *ctrl, idx_t nbrpoolsize); -void FreeWorkSpace(ctrl_t *ctrl); -void *wspacemalloc(ctrl_t *ctrl, size_t nbytes); -void wspacepush(ctrl_t *ctrl); -void wspacepop(ctrl_t *ctrl); -idx_t *iwspacemalloc(ctrl_t *, idx_t); -real_t *rwspacemalloc(ctrl_t *, idx_t); -ikv_t *ikvwspacemalloc(ctrl_t *, idx_t); -void cnbrpoolReset(ctrl_t *ctrl); -idx_t cnbrpoolGetNext(ctrl_t *ctrl, idx_t nnbrs); -void vnbrpoolReset(ctrl_t *ctrl); -idx_t vnbrpoolGetNext(ctrl_t *ctrl, idx_t nnbrs); - - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/refine.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/refine.c deleted file mode 100644 index c08dc2ddb09..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/refine.c +++ /dev/null @@ -1,211 +0,0 @@ -/* -\file -\brief This file contains the driving routines for multilevel refinement - -\date Started 7/24/1997 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version\verbatim $Id: refine.c 10513 2011-07-07 22:06:03Z karypis $ \endverbatim -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function is the entry point of refinement */ -/*************************************************************************/ -void Refine2Way(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph, real_t *tpwgts) -{ - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); - - /* Compute the parameters of the coarsest graph */ - Compute2WayPartitionParams(ctrl, graph); - - for (;;) { - ASSERT(CheckBnd(graph)); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); - - Balance2Way(ctrl, graph, tpwgts); - - FM_2WayRefine(ctrl, graph, tpwgts, ctrl->niter); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); - - if (graph == orggraph) - break; - - graph = graph->finer; - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); - Project2WayPartition(ctrl, graph); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); - } - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); -} - - -/*************************************************************************/ -/*! This function allocates memory for 2-way edge refinement */ -/*************************************************************************/ -void Allocate2WayPartitionMemory(ctrl_t *ctrl, graph_t *graph) -{ - idx_t nvtxs, ncon; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - - graph->pwgts = imalloc(2*ncon, "Allocate2WayPartitionMemory: pwgts"); - graph->where = imalloc(nvtxs, "Allocate2WayPartitionMemory: where"); - graph->bndptr = imalloc(nvtxs, "Allocate2WayPartitionMemory: bndptr"); - graph->bndind = imalloc(nvtxs, "Allocate2WayPartitionMemory: bndind"); - graph->id = imalloc(nvtxs, "Allocate2WayPartitionMemory: id"); - graph->ed = imalloc(nvtxs, "Allocate2WayPartitionMemory: ed"); -} - - -/*************************************************************************/ -/*! This function computes the initial id/ed */ -/*************************************************************************/ -void Compute2WayPartitionParams(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, nvtxs, ncon, nbnd, mincut, istart, iend, tid, ted, me; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts; - idx_t *where, *bndptr, *bndind, *id, *ed; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - where = graph->where; - id = graph->id; - ed = graph->ed; - - pwgts = iset(2*ncon, 0, graph->pwgts); - bndptr = iset(nvtxs, -1, graph->bndptr); - bndind = graph->bndind; - - /* Compute pwgts */ - if (ncon == 1) { - for (i=0; i= 0 && where[i] <= 1); - pwgts[where[i]] += vwgt[i]; - } - ASSERT(pwgts[0]+pwgts[1] == graph->tvwgt[0]); - } - else { - for (i=0; i 0 || istart == iend) { - BNDInsert(nbnd, bndind, bndptr, i); - mincut += ted; - } - } - - graph->mincut = mincut/2; - graph->nbnd = nbnd; - -} - - -/*************************************************************************/ -/*! Projects a partition and computes the refinement params. */ -/*************************************************************************/ -void Project2WayPartition(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, istart, iend, nvtxs, nbnd, me, tid, ted; - idx_t *xadj, *adjncy, *adjwgt; - idx_t *cmap, *where, *bndptr, *bndind; - idx_t *cwhere, *cbndptr; - idx_t *id, *ed; - graph_t *cgraph; - - Allocate2WayPartitionMemory(ctrl, graph); - - cgraph = graph->coarser; - cwhere = cgraph->where; - cbndptr = cgraph->bndptr; - - nvtxs = graph->nvtxs; - cmap = graph->cmap; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; - - where = graph->where; - id = graph->id; - ed = graph->ed; - - bndptr = iset(nvtxs, -1, graph->bndptr); - bndind = graph->bndind; - - /* Project the partition and record which of these nodes came from the - coarser boundary */ - for (i=0; i 0 || istart == iend) - BNDInsert(nbnd, bndind, bndptr, i); - } - graph->mincut = cgraph->mincut; - graph->nbnd = nbnd; - - /* copy pwgts */ - icopy(2*graph->ncon, cgraph->pwgts, graph->pwgts); - - FreeGraph(&graph->coarser); - graph->coarser = NULL; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/rename.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/rename.h deleted file mode 100644 index 62b03b491b9..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/rename.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * rename.h - * - * This file contains header files - * - * Started 10/2/97 - * George - * - * $Id: rename.h 13933 2013-03-29 22:20:46Z karypis $ - * - */ - - -#ifndef _LIBMETIS_RENAME_H_ -#define _LIBMETIS_RENAME_H_ - - -/* balance.c */ -#define Balance2Way libmetis__Balance2Way -#define Bnd2WayBalance libmetis__Bnd2WayBalance -#define General2WayBalance libmetis__General2WayBalance -#define McGeneral2WayBalance libmetis__McGeneral2WayBalance - -/* bucketsort.c */ -#define BucketSortKeysInc libmetis__BucketSortKeysInc - -/* checkgraph.c */ -#define CheckGraph libmetis__CheckGraph -#define CheckInputGraphWeights libmetis__CheckInputGraphWeights -#define FixGraph libmetis__FixGraph - -/* coarsen.c */ -#define CoarsenGraph libmetis__CoarsenGraph -#define Match_RM libmetis__Match_RM -#define Match_SHEM libmetis__Match_SHEM -#define Match_2Hop libmetis__Match_2Hop -#define Match_2HopAny libmetis__Match_2HopAny -#define Match_2HopAll libmetis__Match_2HopAll -#define PrintCGraphStats libmetis__PrintCGraphStats -#define CreateCoarseGraph libmetis__CreateCoarseGraph -#define CreateCoarseGraphNoMask libmetis__CreateCoarseGraphNoMask -#define CreateCoarseGraphPerm libmetis__CreateCoarseGraphPerm -#define SetupCoarseGraph libmetis__SetupCoarseGraph -#define ReAdjustMemory libmetis__ReAdjustMemory - -/* compress.c */ -#define CompressGraph libmetis__CompressGraph -#define PruneGraph libmetis__PruneGraph - -/* contig.c */ -#define FindPartitionInducedComponents libmetis__FindPartitionInducedComponents -#define IsConnected libmetis__IsConnected -#define IsConnectedSubdomain libmetis__IsConnectedSubdomain -#define FindSepInducedComponents libmetis__FindSepInducedComponents -#define EliminateComponents libmetis__EliminateComponents -#define MoveGroupContigForCut libmetis__MoveGroupContigForCut -#define MoveGroupContigForVol libmetis__MoveGroupContigForVol - -/* debug.c */ -#define ComputeCut libmetis__ComputeCut -#define ComputeVolume libmetis__ComputeVolume -#define ComputeMaxCut libmetis__ComputeMaxCut -#define CheckBnd libmetis__CheckBnd -#define CheckBnd2 libmetis__CheckBnd2 -#define CheckNodeBnd libmetis__CheckNodeBnd -#define CheckRInfo libmetis__CheckRInfo -#define CheckNodePartitionParams libmetis__CheckNodePartitionParams -#define IsSeparable libmetis__IsSeparable -#define CheckKWayVolPartitionParams libmetis__CheckKWayVolPartitionParams - -/* fm.c */ -#define FM_2WayRefine libmetis__FM_2WayRefine -#define FM_2WayCutRefine libmetis__FM_2WayCutRefine -#define FM_Mc2WayCutRefine libmetis__FM_Mc2WayCutRefine -#define SelectQueue libmetis__SelectQueue -#define Print2WayRefineStats libmetis__Print2WayRefineStats - -/* fortran.c */ -#define Change2CNumbering libmetis__Change2CNumbering -#define Change2FNumbering libmetis__Change2FNumbering -#define Change2FNumbering2 libmetis__Change2FNumbering2 -#define Change2FNumberingOrder libmetis__Change2FNumberingOrder -#define ChangeMesh2CNumbering libmetis__ChangeMesh2CNumbering -#define ChangeMesh2FNumbering libmetis__ChangeMesh2FNumbering -#define ChangeMesh2FNumbering2 libmetis__ChangeMesh2FNumbering2 - -/* graph.c */ -#define SetupGraph libmetis__SetupGraph -#define SetupGraph_adjrsum libmetis__SetupGraph_adjrsum -#define SetupGraph_tvwgt libmetis__SetupGraph_tvwgt -#define SetupGraph_label libmetis__SetupGraph_label -#define SetupSplitGraph libmetis__SetupSplitGraph -#define CreateGraph libmetis__CreateGraph -#define InitGraph libmetis__InitGraph -#define FreeRData libmetis__FreeRData -#define FreeGraph libmetis__FreeGraph - -/* initpart.c */ -#define Init2WayPartition libmetis__Init2WayPartition -#define InitSeparator libmetis__InitSeparator -#define RandomBisection libmetis__RandomBisection -#define GrowBisection libmetis__GrowBisection -#define McRandomBisection libmetis__McRandomBisection -#define McGrowBisection libmetis__McGrowBisection -#define GrowBisectionNode libmetis__GrowBisectionNode - -/* kmetis.c */ -#define MlevelKWayPartitioning libmetis__MlevelKWayPartitioning -#define InitKWayPartitioning libmetis__InitKWayPartitioning - -/* kwayfm.c */ -#define Greedy_KWayOptimize libmetis__Greedy_KWayOptimize -#define Greedy_KWayCutOptimize libmetis__Greedy_KWayCutOptimize -#define Greedy_KWayVolOptimize libmetis__Greedy_KWayVolOptimize -#define Greedy_McKWayCutOptimize libmetis__Greedy_McKWayCutOptimize -#define Greedy_McKWayVolOptimize libmetis__Greedy_McKWayVolOptimize -#define IsArticulationNode libmetis__IsArticulationNode -#define KWayVolUpdate libmetis__KWayVolUpdate - -/* kwayrefine.c */ -#define RefineKWay libmetis__RefineKWay -#define AllocateKWayPartitionMemory libmetis__AllocateKWayPartitionMemory -#define ComputeKWayPartitionParams libmetis__ComputeKWayPartitionParams -#define ProjectKWayPartition libmetis__ProjectKWayPartition -#define ComputeKWayBoundary libmetis__ComputeKWayBoundary -#define ComputeKWayVolGains libmetis__ComputeKWayVolGains -#define IsBalanced libmetis__IsBalanced - -/* mcutil */ -#define rvecle libmetis__rvecle -#define rvecge libmetis__rvecge -#define rvecsumle libmetis__rvecsumle -#define rvecmaxdiff libmetis__rvecmaxdiff -#define ivecle libmetis__ivecle -#define ivecge libmetis__ivecge -#define ivecaxpylez libmetis__ivecaxpylez -#define ivecaxpygez libmetis__ivecaxpygez -#define BetterVBalance libmetis__BetterVBalance -#define BetterBalance2Way libmetis__BetterBalance2Way -#define BetterBalanceKWay libmetis__BetterBalanceKWay -#define ComputeLoadImbalance libmetis__ComputeLoadImbalance -#define ComputeLoadImbalanceDiff libmetis__ComputeLoadImbalanceDiff -#define ComputeLoadImbalanceDiffVec libmetis__ComputeLoadImbalanceDiffVec -#define ComputeLoadImbalanceVec libmetis__ComputeLoadImbalanceVec - -/* mesh.c */ -#define CreateGraphDual libmetis__CreateGraphDual -#define FindCommonElements libmetis__FindCommonElements -#define CreateGraphNodal libmetis__CreateGraphNodal -#define FindCommonNodes libmetis__FindCommonNodes -#define CreateMesh libmetis__CreateMesh -#define InitMesh libmetis__InitMesh -#define FreeMesh libmetis__FreeMesh - -/* meshpart.c */ -#define InduceRowPartFromColumnPart libmetis__InduceRowPartFromColumnPart - -/* minconn.c */ -#define ComputeSubDomainGraph libmetis__ComputeSubDomainGraph -#define UpdateEdgeSubDomainGraph libmetis__UpdateEdgeSubDomainGraph -#define PrintSubDomainGraph libmetis__PrintSubDomainGraph -#define EliminateSubDomainEdges libmetis__EliminateSubDomainEdges -#define MoveGroupMinConnForCut libmetis__MoveGroupMinConnForCut -#define MoveGroupMinConnForVol libmetis__MoveGroupMinConnForVol - -/* mincover.c */ -#define MinCover libmetis__MinCover -#define MinCover_Augment libmetis__MinCover_Augment -#define MinCover_Decompose libmetis__MinCover_Decompose -#define MinCover_ColDFS libmetis__MinCover_ColDFS -#define MinCover_RowDFS libmetis__MinCover_RowDFS - -/* mmd.c */ -#define genmmd libmetis__genmmd -#define mmdelm libmetis__mmdelm -#define mmdint libmetis__mmdint -#define mmdnum libmetis__mmdnum -#define mmdupd libmetis__mmdupd - - -/* ometis.c */ -#define MlevelNestedDissection libmetis__MlevelNestedDissection -#define MlevelNestedDissectionCC libmetis__MlevelNestedDissectionCC -#define MlevelNodeBisectionMultiple libmetis__MlevelNodeBisectionMultiple -#define MlevelNodeBisectionL2 libmetis__MlevelNodeBisectionL2 -#define MlevelNodeBisectionL1 libmetis__MlevelNodeBisectionL1 -#define SplitGraphOrder libmetis__SplitGraphOrder -#define SplitGraphOrderCC libmetis__SplitGraphOrderCC -#define MMDOrder libmetis__MMDOrder - -/* options.c */ -#define SetupCtrl libmetis__SetupCtrl -#define SetupKWayBalMultipliers libmetis__SetupKWayBalMultipliers -#define Setup2WayBalMultipliers libmetis__Setup2WayBalMultipliers -#define PrintCtrl libmetis__PrintCtrl -#define FreeCtrl libmetis__FreeCtrl -#define CheckParams libmetis__CheckParams - -/* parmetis.c */ -#define MlevelNestedDissectionP libmetis__MlevelNestedDissectionP -#define FM_2WayNodeRefine1SidedP libmetis__FM_2WayNodeRefine1SidedP -#define FM_2WayNodeRefine2SidedP libmetis__FM_2WayNodeRefine2SidedP - -/* pmetis.c */ -#define MlevelRecursiveBisection libmetis__MlevelRecursiveBisection -#define MultilevelBisect libmetis__MultilevelBisect -#define SplitGraphPart libmetis__SplitGraphPart - -/* refine.c */ -#define Refine2Way libmetis__Refine2Way -#define Allocate2WayPartitionMemory libmetis__Allocate2WayPartitionMemory -#define Compute2WayPartitionParams libmetis__Compute2WayPartitionParams -#define Project2WayPartition libmetis__Project2WayPartition - -/* separator.c */ -#define ConstructSeparator libmetis__ConstructSeparator -#define ConstructMinCoverSeparator libmetis__ConstructMinCoverSeparator - -/* sfm.c */ -#define FM_2WayNodeRefine2Sided libmetis__FM_2WayNodeRefine2Sided -#define FM_2WayNodeRefine1Sided libmetis__FM_2WayNodeRefine1Sided -#define FM_2WayNodeBalance libmetis__FM_2WayNodeBalance - -/* srefine.c */ -#define Refine2WayNode libmetis__Refine2WayNode -#define Allocate2WayNodePartitionMemory libmetis__Allocate2WayNodePartitionMemory -#define Compute2WayNodePartitionParams libmetis__Compute2WayNodePartitionParams -#define Project2WayNodePartition libmetis__Project2WayNodePartition - -/* stat.c */ -#define ComputePartitionInfoBipartite libmetis__ComputePartitionInfoBipartite -#define ComputePartitionBalance libmetis__ComputePartitionBalance -#define ComputeElementBalance libmetis__ComputeElementBalance - -/* timing.c */ -#define InitTimers libmetis__InitTimers -#define PrintTimers libmetis__PrintTimers - -/* util.c */ -#define iargmax_strd libmetis__iargmax_strd -#define iargmax_nrm libmetis__iargmax_nrm -#define iargmax2_nrm libmetis__iargmax2_nrm -#define rargmax2 libmetis__rargmax2 -#define InitRandom libmetis__InitRandom -#define metis_rcode libmetis__metis_rcode - -/* wspace.c */ -#define AllocateWorkSpace libmetis__AllocateWorkSpace -#define AllocateRefinementWorkSpace libmetis__AllocateRefinementWorkSpace -#define FreeWorkSpace libmetis__FreeWorkSpace -#define wspacemalloc libmetis__wspacemalloc -#define wspacepush libmetis__wspacepush -#define wspacepop libmetis__wspacepop -#define iwspacemalloc libmetis__iwspacemalloc -#define rwspacemalloc libmetis__rwspacemalloc -#define ikvwspacemalloc libmetis__ikvwspacemalloc -#define cnbrpoolReset libmetis__cnbrpoolReset -#define cnbrpoolGetNext libmetis__cnbrpoolGetNext -#define vnbrpoolReset libmetis__vnbrpoolReset -#define vnbrpoolGetNext libmetis__vnbrpoolGetNext - -#endif - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/separator.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/separator.c deleted file mode 100644 index 72dae9b643a..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/separator.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * separator.c - * - * This file contains code for separator extraction - * - * Started 8/1/97 - * George - * - * $Id: separator.c 10481 2011-07-05 18:01:23Z karypis $ - * - */ - -#include "metislib.h" - -/************************************************************************* -* This function takes a bisection and constructs a minimum weight vertex -* separator out of it. It uses the node-based separator refinement for it. -**************************************************************************/ -void ConstructSeparator(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, k, nvtxs, nbnd; - idx_t *xadj, *where, *bndind; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - nbnd = graph->nbnd; - bndind = graph->bndind; - - where = icopy(nvtxs, graph->where, iwspacemalloc(ctrl, nvtxs)); - - /* Put the nodes in the boundary into the separator */ - for (i=0; i 0) /* Ignore islands */ - where[j] = 2; - } - - FreeRData(graph); - - Allocate2WayNodePartitionMemory(ctrl, graph); - icopy(nvtxs, where, graph->where); - - WCOREPOP; - - ASSERT(IsSeparable(graph)); - - Compute2WayNodePartitionParams(ctrl, graph); - - ASSERT(CheckNodePartitionParams(graph)); - - FM_2WayNodeRefine2Sided(ctrl, graph, 1); - FM_2WayNodeRefine1Sided(ctrl, graph, 4); - - ASSERT(IsSeparable(graph)); - -} - - - -/************************************************************************* -* This function takes a bisection and constructs a minimum weight vertex -* separator out of it. It uses an unweighted minimum-cover algorithm -* followed by node-based separator refinement. -**************************************************************************/ -void ConstructMinCoverSeparator(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, jj, k, l, nvtxs, nbnd, bnvtxs[3], bnedges[2], csize; - idx_t *xadj, *adjncy, *bxadj, *badjncy; - idx_t *where, *bndind, *bndptr, *vmap, *ivmap, *cover; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - - nbnd = graph->nbnd; - bndind = graph->bndind; - bndptr = graph->bndptr; - where = graph->where; - - vmap = iwspacemalloc(ctrl, nvtxs); - ivmap = iwspacemalloc(ctrl, nbnd); - cover = iwspacemalloc(ctrl, nbnd); - - if (nbnd > 0) { - /* Go through the boundary and determine the sizes of the bipartite graph */ - bnvtxs[0] = bnvtxs[1] = bnedges[0] = bnedges[1] = 0; - for (i=0; i 0) { - bnvtxs[k]++; - bnedges[k] += xadj[j+1]-xadj[j]; - } - } - - bnvtxs[2] = bnvtxs[0]+bnvtxs[1]; - bnvtxs[1] = bnvtxs[0]; - bnvtxs[0] = 0; - - bxadj = iwspacemalloc(ctrl, bnvtxs[2]+1); - badjncy = iwspacemalloc(ctrl, bnedges[0]+bnedges[1]+1); - - /* Construct the ivmap and vmap */ - ASSERT(iset(nvtxs, -1, vmap) == vmap); - for (i=0; i 0) { - vmap[j] = bnvtxs[k]; - ivmap[bnvtxs[k]++] = j; - } - } - - /* OK, go through and put the vertices of each part starting from 0 */ - bnvtxs[1] = bnvtxs[0]; - bnvtxs[0] = 0; - bxadj[0] = l = 0; - for (k=0; k<2; k++) { - for (ii=0; iibndptr[jj])); - badjncy[l++] = vmap[jj]; - } - } - bxadj[++bnvtxs[k]] = l; - } - } - } - - ASSERT(l <= bnedges[0]+bnedges[1]); - - MinCover(bxadj, badjncy, bnvtxs[0], bnvtxs[1], cover, &csize); - - IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, - printf("Nvtxs: %6"PRIDX", [%5"PRIDX" %5"PRIDX"], Cut: %6"PRIDX", SS: [%6"PRIDX" %6"PRIDX"], Cover: %6"PRIDX"\n", nvtxs, graph->pwgts[0], graph->pwgts[1], graph->mincut, bnvtxs[0], bnvtxs[1]-bnvtxs[0], csize)); - - for (i=0; idbglvl, METIS_DBG_SEPINFO, - printf("Nvtxs: %6"PRIDX", [%5"PRIDX" %5"PRIDX"], Cut: %6"PRIDX", SS: [%6"PRIDX" %6"PRIDX"], Cover: %6"PRIDX"\n", nvtxs, graph->pwgts[0], graph->pwgts[1], graph->mincut, (idx_t)0, (idx_t)0, (idx_t)0)); - } - - /* Prepare to refine the vertex separator */ - icopy(nvtxs, graph->where, vmap); - - FreeRData(graph); - - Allocate2WayNodePartitionMemory(ctrl, graph); - icopy(nvtxs, vmap, graph->where); - - WCOREPOP; - - Compute2WayNodePartitionParams(ctrl, graph); - - ASSERT(CheckNodePartitionParams(graph)); - - FM_2WayNodeRefine1Sided(ctrl, graph, ctrl->niter); - - ASSERT(IsSeparable(graph)); -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/sfm.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/sfm.c deleted file mode 100644 index d4181738028..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/sfm.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * sfm.c - * - * This file contains code that implementes an FM-based separator refinement - * - * Started 8/1/97 - * George - * - * $Id: sfm.c 10874 2011-10-17 23:13:00Z karypis $ - * - */ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function performs a node-based FM refinement */ -/**************************************************************************/ -void FM_2WayNodeRefine2Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter) -{ - idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind; - idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; - idx_t *mptr, *mind, *moved, *swaps; - rpq_t *queues[2]; - nrinfo_t *rinfo; - idx_t higain, oldgain, mincut, initcut, mincutorder; - idx_t pass, to, other, limit; - idx_t badmaxpwgt, mindiff, newdiff; - idx_t u[2], g[2]; - real_t mult; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - where = graph->where; - pwgts = graph->pwgts; - rinfo = graph->nrinfo; - - queues[0] = rpqCreate(nvtxs); - queues[1] = rpqCreate(nvtxs); - - moved = iwspacemalloc(ctrl, nvtxs); - swaps = iwspacemalloc(ctrl, nvtxs); - mptr = iwspacemalloc(ctrl, nvtxs+1); - mind = iwspacemalloc(ctrl, 2*nvtxs); - - mult = 0.5*ctrl->ubfactors[0]; - badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]+pwgts[2])); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions-N2: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); - - for (pass=0; passmincut; - nbnd = graph->nbnd; - - /* use the swaps array in place of the traditional perm array to save memory */ - irandArrayPermute(nbnd, swaps, nbnd, 1); - for (ii=0; iicompress ? gk_min(5*nbnd, 400) : gk_min(2*nbnd, 300)); - - /****************************************************** - * Get into the FM loop - *******************************************************/ - mptr[0] = nmind = 0; - mindiff = iabs(pwgts[0]-pwgts[1]); - to = (pwgts[0] < pwgts[1] ? 0 : 1); - for (nswaps=0; nswaps g[1] ? 0 : (g[0] < g[1] ? 1 : pass%2)); - - if (pwgts[to]+vwgt[u[to]] > badmaxpwgt) - to = (to+1)%2; - } - else if (u[0] == -1 && u[1] == -1) { - break; - } - else if (u[0] != -1 && pwgts[0]+vwgt[u[0]] <= badmaxpwgt) { - to = 0; - } - else if (u[1] != -1 && pwgts[1]+vwgt[u[1]] <= badmaxpwgt) { - to = 1; - } - else - break; - - other = (to+1)%2; - - higain = rpqGetTop(queues[to]); - if (moved[higain] == -1) /* Delete if it was in the separator originally */ - rpqDelete(queues[other], higain); - - ASSERT(bndptr[higain] != -1); - - /* The following check is to ensure we break out if there is a posibility - of over-running the mind array. */ - if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1) - break; - - pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]); - - newdiff = iabs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other])); - if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { - mincut = pwgts[2]; - mincutorder = nswaps; - mindiff = newdiff; - } - else { - if (nswaps - mincutorder > 2*limit || - (nswaps - mincutorder > limit && pwgts[2] > 1.10*mincut)) { - pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]); - break; /* No further improvement, break out */ - } - } - - BNDDelete(nbnd, bndind, bndptr, higain); - pwgts[to] += vwgt[higain]; - where[higain] = to; - moved[higain] = nswaps; - swaps[nswaps] = higain; - - - /********************************************************** - * Update the degrees of the affected nodes - ***********************************************************/ - for (j=xadj[higain]; jdbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] [%4"PRIDX" %4"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, g[to], g[other], vwgt[u[to]], vwgt[u[other]], pwgts[0], pwgts[1], pwgts[2])); - - } - - - /**************************************************************** - * Roll back computation - *****************************************************************/ - for (nswaps--; nswaps>mincutorder; nswaps--) { - higain = swaps[nswaps]; - - ASSERT(CheckNodePartitionParams(graph)); - - to = where[higain]; - other = (to+1)%2; - INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); - where[higain] = 2; - BNDInsert(nbnd, bndind, bndptr, higain); - - edegrees = rinfo[higain].edegrees; - edegrees[0] = edegrees[1] = 0; - for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, - printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd)); - - graph->mincut = mincut; - graph->nbnd = nbnd; - - if (mincutorder == -1 || mincut >= initcut) - break; - } - - rpqDestroy(queues[0]); - rpqDestroy(queues[1]); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function performs a node-based FM refinement. - Each refinement iteration is split into two sub-iterations. - In each sub-iteration only moves to one of the left/right partitions - is allowed; hence, it is one-sided. -*/ -/**************************************************************************/ -void FM_2WayNodeRefine1Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter) -{ - idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind, iend; - idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; - idx_t *mptr, *mind, *swaps; - rpq_t *queue; - nrinfo_t *rinfo; - idx_t higain, mincut, initcut, mincutorder; - idx_t pass, to, other, limit; - idx_t badmaxpwgt, mindiff, newdiff; - real_t mult; - - WCOREPUSH; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - where = graph->where; - pwgts = graph->pwgts; - rinfo = graph->nrinfo; - - queue = rpqCreate(nvtxs); - - swaps = iwspacemalloc(ctrl, nvtxs); - mptr = iwspacemalloc(ctrl, nvtxs+1); - mind = iwspacemalloc(ctrl, 2*nvtxs); - - mult = 0.5*ctrl->ubfactors[0]; - badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]+pwgts[2])); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions-N1: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); - - to = (pwgts[0] < pwgts[1] ? 1 : 0); - for (pass=0; pass<2*niter; pass++) { /* the 2*niter is for the two sides */ - other = to; - to = (to+1)%2; - - rpqReset(queue); - - mincutorder = -1; - initcut = mincut = graph->mincut; - nbnd = graph->nbnd; - - /* use the swaps array in place of the traditional perm array to save memory */ - irandArrayPermute(nbnd, swaps, nbnd, 1); - for (ii=0; iicompress ? gk_min(5*nbnd, 500) : gk_min(3*nbnd, 300)); - - /****************************************************** - * Get into the FM loop - *******************************************************/ - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr)); - mptr[0] = nmind = 0; - mindiff = iabs(pwgts[0]-pwgts[1]); - for (nswaps=0; nswaps= 2*nvtxs-1) - break; - - if (pwgts[to]+vwgt[higain] > badmaxpwgt) - break; /* No point going any further. Balance will be bad */ - - pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]); - - newdiff = iabs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other])); - if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { - mincut = pwgts[2]; - mincutorder = nswaps; - mindiff = newdiff; - } - else { - if (nswaps - mincutorder > 3*limit || - (nswaps - mincutorder > limit && pwgts[2] > 1.10*mincut)) { - pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]); - break; /* No further improvement, break out */ - } - } - - BNDDelete(nbnd, bndind, bndptr, higain); - pwgts[to] += vwgt[higain]; - where[higain] = to; - swaps[nswaps] = higain; - - - /********************************************************** - * Update the degrees of the affected nodes - ***********************************************************/ - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux1Tmr)); - for (j=xadj[higain]; jdbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux1Tmr)); - - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"] [%3"PRIDX" %2"PRIDX"]\n", - higain, to, (vwgt[higain]-rinfo[higain].edegrees[other]), vwgt[higain], - pwgts[0], pwgts[1], pwgts[2], nswaps, limit)); - } - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr)); - - - /**************************************************************** - * Roll back computation - *****************************************************************/ - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux2Tmr)); - for (nswaps--; nswaps>mincutorder; nswaps--) { - higain = swaps[nswaps]; - - ASSERT(CheckNodePartitionParams(graph)); - ASSERT(where[higain] == to); - - INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); - where[higain] = 2; - BNDInsert(nbnd, bndind, bndptr, higain); - - edegrees = rinfo[higain].edegrees; - edegrees[0] = edegrees[1] = 0; - for (j=xadj[higain]; jdbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux2Tmr)); - - ASSERT(mincut == pwgts[2]); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd)); - - graph->mincut = mincut; - graph->nbnd = nbnd; - - if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut)) - break; - } - - rpqDestroy(queue); - - WCOREPOP; -} - - -/*************************************************************************/ -/*! This function balances the left/right partitions of a separator - tri-section */ -/*************************************************************************/ -void FM_2WayNodeBalance(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, gain; - idx_t badmaxpwgt, higain, oldgain, pass, to, other; - idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; - idx_t *perm, *moved; - rpq_t *queue; - nrinfo_t *rinfo; - real_t mult; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - - bndind = graph->bndind; - bndptr = graph->bndptr; - where = graph->where; - pwgts = graph->pwgts; - rinfo = graph->nrinfo; - - mult = 0.5*ctrl->ubfactors[0]; - - badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1])); - if (gk_max(pwgts[0], pwgts[1]) < badmaxpwgt) - return; - if (iabs(pwgts[0]-pwgts[1]) < 3*graph->tvwgt[0]/nvtxs) - return; - - WCOREPUSH; - - to = (pwgts[0] < pwgts[1] ? 0 : 1); - other = (to+1)%2; - - queue = rpqCreate(nvtxs); - - perm = iwspacemalloc(ctrl, nvtxs); - moved = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); - - IFSET(ctrl->dbglvl, METIS_DBG_REFINE, - printf("Partitions: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX" [B]\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); - - nbnd = graph->nbnd; - irandArrayPermute(nbnd, perm, nbnd, 1); - for (ii=0; ii pwgts[other]) - break; - - /* break if balance is achieved and no +ve or zero gain */ - if (gain < 0 && pwgts[other] < badmaxpwgt) - break; - - /* skip this vertex if it will violate balance on the other side */ - if (pwgts[to]+vwgt[higain] > badmaxpwgt) - continue; - - ASSERT(bndptr[higain] != -1); - - pwgts[2] -= gain; - - BNDDelete(nbnd, bndind, bndptr, higain); - pwgts[to] += vwgt[higain]; - where[higain] = to; - - IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, - printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %3"PRIDX", \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, vwgt[higain]-rinfo[higain].edegrees[other], pwgts[0], pwgts[1], pwgts[2])); - - - /********************************************************** - * Update the degrees of the affected nodes - ***********************************************************/ - for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, - printf("\tBalanced sep: %6"PRIDX" at %4"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", pwgts[2], nswaps, pwgts[0], pwgts[1], nbnd)); - - graph->mincut = pwgts[2]; - graph->nbnd = nbnd; - - rpqDestroy(queue); - - WCOREPOP; -} - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/srefine.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/srefine.c deleted file mode 100644 index 603f782ad4e..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/srefine.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * srefine.c - * - * This file contains code for the separator refinement algortihms - * - * Started 8/1/97 - * George - * - * $Id: srefine.c 10515 2011-07-08 15:46:18Z karypis $ - * - */ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function is the entry point of the separator refinement. - It does not perform any refinement on graph, but it starts by first - projecting it to the next level finer graph and proceeds from there. */ -/*************************************************************************/ -void Refine2WayNode(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph) -{ - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); - - if (graph == orggraph) { - Compute2WayNodePartitionParams(ctrl, graph); - } - else { - do { - graph = graph->finer; - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); - Project2WayNodePartition(ctrl, graph); - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); - FM_2WayNodeBalance(ctrl, graph); - - ASSERT(CheckNodePartitionParams(graph)); - - switch (ctrl->rtype) { - case METIS_RTYPE_SEP2SIDED: - FM_2WayNodeRefine2Sided(ctrl, graph, ctrl->niter); - break; - case METIS_RTYPE_SEP1SIDED: - FM_2WayNodeRefine1Sided(ctrl, graph, ctrl->niter); - break; - default: - gk_errexit(SIGERR, "Unknown rtype of %d\n", ctrl->rtype); - } - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); - - } while (graph != orggraph); - } - - IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); -} - - -/*************************************************************************/ -/*! This function allocates memory for 2-way node-based refinement */ -/**************************************************************************/ -void Allocate2WayNodePartitionMemory(ctrl_t *ctrl, graph_t *graph) -{ - idx_t nvtxs; - - nvtxs = graph->nvtxs; - - graph->pwgts = imalloc(3, "Allocate2WayNodePartitionMemory: pwgts"); - graph->where = imalloc(nvtxs, "Allocate2WayNodePartitionMemory: where"); - graph->bndptr = imalloc(nvtxs, "Allocate2WayNodePartitionMemory: bndptr"); - graph->bndind = imalloc(nvtxs, "Allocate2WayNodePartitionMemory: bndind"); - graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "Allocate2WayNodePartitionMemory: nrinfo"); -} - - -/*************************************************************************/ -/*! This function computes the edegrees[] to the left & right sides */ -/*************************************************************************/ -void Compute2WayNodePartitionParams(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, nvtxs, nbnd; - idx_t *xadj, *adjncy, *vwgt; - idx_t *where, *pwgts, *bndind, *bndptr, *edegrees; - nrinfo_t *rinfo; - idx_t me, other; - - nvtxs = graph->nvtxs; - xadj = graph->xadj; - vwgt = graph->vwgt; - adjncy = graph->adjncy; - - where = graph->where; - rinfo = graph->nrinfo; - pwgts = iset(3, 0, graph->pwgts); - bndind = graph->bndind; - bndptr = iset(nvtxs, -1, graph->bndptr); - - - /*------------------------------------------------------------ - / Compute now the separator external degrees - /------------------------------------------------------------*/ - nbnd = 0; - for (i=0; i=0 && me <= 2); - - if (me == 2) { /* If it is on the separator do some computations */ - BNDInsert(nbnd, bndind, bndptr, i); - - edegrees = rinfo[i].edegrees; - edegrees[0] = edegrees[1] = 0; - - for (j=xadj[i]; jmincut = pwgts[2]; - graph->nbnd = nbnd; -} - - -/*************************************************************************/ -/*! This function projects the node-based bisection */ -/*************************************************************************/ -void Project2WayNodePartition(ctrl_t *ctrl, graph_t *graph) -{ - idx_t i, j, nvtxs; - idx_t *cmap, *where, *cwhere; - graph_t *cgraph; - - cgraph = graph->coarser; - cwhere = cgraph->where; - - nvtxs = graph->nvtxs; - cmap = graph->cmap; - - Allocate2WayNodePartitionMemory(ctrl, graph); - where = graph->where; - - /* Project the partition */ - for (i=0; i= 0 && where[i] <= 2, ("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", - i, cmap[i], where[i], cwhere[cmap[i]])); - } - - FreeGraph(&graph->coarser); - graph->coarser = NULL; - - Compute2WayNodePartitionParams(ctrl, graph); -} diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/stat.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/stat.c deleted file mode 100644 index f19791b5356..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/stat.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * stat.c - * - * This file computes various statistics - * - * Started 7/25/97 - * George - * - * $Id: stat.c 9942 2011-05-17 22:09:52Z karypis $ - * - */ - -#include "metislib.h" - - -/************************************************************************* -* This function computes cuts and balance information -**************************************************************************/ -void ComputePartitionInfoBipartite(graph_t *graph, idx_t nparts, idx_t *where) -{ - idx_t i, j, k, nvtxs, ncon, mustfree=0; - idx_t *xadj, *adjncy, *vwgt, *vsize, *adjwgt, *kpwgts, *tmpptr; - idx_t *padjncy, *padjwgt, *padjcut; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - xadj = graph->xadj; - adjncy = graph->adjncy; - vwgt = graph->vwgt; - vsize = graph->vsize; - adjwgt = graph->adjwgt; - - if (vwgt == NULL) { - vwgt = graph->vwgt = ismalloc(nvtxs, 1, "vwgt"); - mustfree = 1; - } - if (adjwgt == NULL) { - adjwgt = graph->adjwgt = ismalloc(xadj[nvtxs], 1, "adjwgt"); - mustfree += 2; - } - - printf("%"PRIDX"-way Cut: %5"PRIDX", Vol: %5"PRIDX", ", nparts, ComputeCut(graph, where), ComputeVolume(graph, where)); - - /* Compute balance information */ - kpwgts = ismalloc(ncon*nparts, 0, "ComputePartitionInfo: kpwgts"); - - for (i=0; ivwgt = NULL; - } - if (mustfree == 2 || mustfree == 3) { - gk_free((void **)&adjwgt, LTERM); - graph->adjwgt = NULL; - } - - gk_free((void **)&kpwgts, &padjncy, &padjwgt, &padjcut, LTERM); -} - - -/************************************************************************* -* This function computes the balance of the partitioning -**************************************************************************/ -void ComputePartitionBalance(graph_t *graph, idx_t nparts, idx_t *where, real_t *ubvec) -{ - idx_t i, j, nvtxs, ncon; - idx_t *kpwgts, *vwgt; - real_t balance; - - nvtxs = graph->nvtxs; - ncon = graph->ncon; - vwgt = graph->vwgt; - - kpwgts = ismalloc(nparts, 0, "ComputePartitionInfo: kpwgts"); - - if (vwgt == NULL) { - for (i=0; invtxs; i++) - kpwgts[where[i]] += vwgt[i*ncon+j]; - - ubvec[j] = 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1)); - } - } - - gk_free((void **)&kpwgts, LTERM); - -} - - -/************************************************************************* -* This function computes the balance of the element partitioning -**************************************************************************/ -real_t ComputeElementBalance(idx_t ne, idx_t nparts, idx_t *where) -{ - idx_t i; - idx_t *kpwgts; - real_t balance; - - kpwgts = ismalloc(nparts, 0, "ComputeElementBalance: kpwgts"); - - for (i=0; i -#ifdef __STDC__ -#include -#else -#include -#endif -#include -#include -#include -#include -#include - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/struct.h b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/struct.h deleted file mode 100644 index 5fc8588df6c..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/struct.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * struct.h - * - * This file contains data structures for ILU routines. - * - * Started 9/26/95 - * George - * - * $Id: struct.h 13900 2013-03-24 15:27:07Z karypis $ - */ - -#ifndef _LIBMETIS_STRUCT_H_ -#define _LIBMETIS_STRUCT_H_ - - - -/*************************************************************************/ -/*! This data structure stores cut-based k-way refinement info about an - adjacent subdomain for a given vertex. */ -/*************************************************************************/ -typedef struct cnbr_t { - idx_t pid; /*!< The partition ID */ - idx_t ed; /*!< The sum of the weights of the adjacent edges - that are incident on pid */ -} cnbr_t; - - -/*************************************************************************/ -/*! The following data structure stores holds information on degrees for k-way - partition */ -/*************************************************************************/ -typedef struct ckrinfo_t { - idx_t id; /*!< The internal degree of a vertex (sum of weights) */ - idx_t ed; /*!< The total external degree of a vertex */ - idx_t nnbrs; /*!< The number of neighboring subdomains */ - idx_t inbr; /*!< The index in the cnbr_t array where the nnbrs list - of neighbors is stored */ -} ckrinfo_t; - - -/*************************************************************************/ -/*! This data structure stores volume-based k-way refinement info about an - adjacent subdomain for a given vertex. */ -/*************************************************************************/ -typedef struct vnbr_t { - idx_t pid; /*!< The partition ID */ - idx_t ned; /*!< The number of the adjacent edges - that are incident on pid */ - idx_t gv; /*!< The gain in volume achieved by moving the - vertex to pid */ -} vnbr_t; - - -/*************************************************************************/ -/*! The following data structure holds information on degrees for k-way - vol-based partition */ -/*************************************************************************/ -typedef struct vkrinfo_t { - idx_t nid; /*!< The internal degree of a vertex (count of edges) */ - idx_t ned; /*!< The total external degree of a vertex (count of edges) */ - idx_t gv; /*!< The volume gain of moving that vertex */ - idx_t nnbrs; /*!< The number of neighboring subdomains */ - idx_t inbr; /*!< The index in the vnbr_t array where the nnbrs list - of neighbors is stored */ -} vkrinfo_t; - - -/*************************************************************************/ -/*! The following data structure holds information on degrees for k-way - partition */ -/*************************************************************************/ -typedef struct nrinfo_t { - idx_t edegrees[2]; -} nrinfo_t; - - -/*************************************************************************/ -/*! This data structure holds a graph */ -/*************************************************************************/ -typedef struct graph_t { - idx_t nvtxs, nedges; /* The # of vertices and edges in the graph */ - idx_t ncon; /* The # of constrains */ - idx_t *xadj; /* Pointers to the locally stored vertices */ - idx_t *vwgt; /* Vertex weights */ - idx_t *vsize; /* Vertex sizes for min-volume formulation */ - idx_t *adjncy; /* Array that stores the adjacency lists of nvtxs */ - idx_t *adjwgt; /* Array that stores the weights of the adjacency lists */ - - idx_t *tvwgt; /* The sum of the vertex weights in the graph */ - real_t *invtvwgt; /* The inverse of the sum of the vertex weights in the graph */ - - - /* These are to keep track control if the corresponding fields correspond to - application or library memory */ - int free_xadj, free_vwgt, free_vsize, free_adjncy, free_adjwgt; - - idx_t *label; - - idx_t *cmap; - - /* Partition parameters */ - idx_t mincut, minvol; - idx_t *where, *pwgts; - idx_t nbnd; - idx_t *bndptr, *bndind; - - /* Bisection refinement parameters */ - idx_t *id, *ed; - - /* K-way refinement parameters */ - ckrinfo_t *ckrinfo; /*!< The per-vertex cut-based refinement info */ - vkrinfo_t *vkrinfo; /*!< The per-vertex volume-based refinement info */ - - /* Node refinement information */ - nrinfo_t *nrinfo; - - struct graph_t *coarser, *finer; -} graph_t; - - -/*************************************************************************/ -/*! This data structure holds a mesh */ -/*************************************************************************/ -typedef struct mesh_t { - idx_t ne, nn; /*!< The # of elements and nodes in the mesh */ - idx_t ncon; /*!< The number of element balancing constraints (element weights) */ - - idx_t *eptr, *eind; /*!< The CSR-structure storing the nodes in the elements */ - idx_t *ewgt; /*!< The weights of the elements */ -} mesh_t; - - - -/*************************************************************************/ -/*! The following structure stores information used by Metis */ -/*************************************************************************/ -typedef struct ctrl_t { - moptype_et optype; /* Type of operation */ - mobjtype_et objtype; /* Type of refinement objective */ - mdbglvl_et dbglvl; /* Controls the debuging output of the program */ - mctype_et ctype; /* The type of coarsening */ - miptype_et iptype; /* The type of initial partitioning */ - mrtype_et rtype; /* The type of refinement */ - - idx_t CoarsenTo; /* The # of vertices in the coarsest graph */ - idx_t nIparts; /* The number of initial partitions to compute */ - idx_t no2hop; /* Indicates if 2-hop matching will be used */ - idx_t minconn; /* Indicates if the subdomain connectivity will be minimized */ - idx_t contig; /* Indicates if contigous partitions are required */ - idx_t nseps; /* The number of separators to be found during multiple bisections */ - idx_t ufactor; /* The user-supplied load imbalance factor */ - idx_t compress; /* If the graph will be compressed prior to ordering */ - idx_t ccorder; /* If connected components will be ordered separately */ - idx_t seed; /* The seed for the random number generator */ - idx_t ncuts; /* The number of different partitionings to compute */ - idx_t niter; /* The number of iterations during each refinement */ - idx_t numflag; /* The user-supplied numflag for the graph */ - idx_t *maxvwgt; /* The maximum allowed weight for a vertex */ - - idx_t ncon; /*!< The number of balancing constraints */ - idx_t nparts; /*!< The number of partitions */ - - real_t pfactor; /* .1*(user-supplied prunning factor) */ - - real_t *ubfactors; /*!< The per-constraint ubfactors */ - - real_t *tpwgts; /*!< The target partition weights */ - real_t *pijbm; /*!< The nparts*ncon multiplies for the ith partition - and jth constraint for obtaining the balance */ - - real_t cfactor; /*!< The achieved compression factor */ - - /* Various Timers */ - double TotalTmr, InitPartTmr, MatchTmr, ContractTmr, CoarsenTmr, UncoarsenTmr, - RefTmr, ProjectTmr, SplitTmr, Aux1Tmr, Aux2Tmr, Aux3Tmr; - - /* Workspace information */ - gk_mcore_t *mcore; /*!< The persistent memory core for within function - mallocs/frees */ - - /* These are for use by the k-way refinement routines */ - size_t nbrpoolsize; /*!< The number of {c,v}nbr_t entries that have been allocated */ - size_t nbrpoolcpos; /*!< The position of the first free entry in the array */ - size_t nbrpoolreallocs; /*!< The number of times the pool was resized */ - - cnbr_t *cnbrpool; /*!< The pool of cnbr_t entries to be used during refinement. - The size and current position of the pool is controlled - by nnbrs & cnbrs */ - vnbr_t *vnbrpool; /*!< The pool of vnbr_t entries to be used during refinement. - The size and current position of the pool is controlled - by nnbrs & cnbrs */ - - /* The subdomain graph, in sparse format */ - idx_t *maxnads; /* The maximum allocated number of adjacent domains */ - idx_t *nads; /* The number of adjacent domains */ - idx_t **adids; /* The IDs of the adjacent domains */ - idx_t **adwgts; /* The edge-weight to the adjacent domains */ - idx_t *pvec1, *pvec2; /* Auxiliar nparts-size vectors for efficiency */ - -} ctrl_t; - - - -#endif diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/timing.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/timing.c deleted file mode 100644 index 9d6e05cf1c8..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/timing.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * timing.c - * - * This file contains routines that deal with timing Metis - * - * Started 7/24/97 - * George - * - * $Id: timing.c 13936 2013-03-30 03:59:09Z karypis $ - * - */ - -#include "metislib.h" - - -/************************************************************************* -* This function clears the timers -**************************************************************************/ -void InitTimers(ctrl_t *ctrl) -{ - gk_clearcputimer(ctrl->TotalTmr); - gk_clearcputimer(ctrl->InitPartTmr); - gk_clearcputimer(ctrl->MatchTmr); - gk_clearcputimer(ctrl->ContractTmr); - gk_clearcputimer(ctrl->CoarsenTmr); - gk_clearcputimer(ctrl->UncoarsenTmr); - gk_clearcputimer(ctrl->RefTmr); - gk_clearcputimer(ctrl->ProjectTmr); - gk_clearcputimer(ctrl->SplitTmr); - gk_clearcputimer(ctrl->Aux1Tmr); - gk_clearcputimer(ctrl->Aux2Tmr); - gk_clearcputimer(ctrl->Aux3Tmr); -} - - - -/************************************************************************* -* This function prints the various timers -**************************************************************************/ -void PrintTimers(ctrl_t *ctrl) -{ - printf("\nTiming Information -------------------------------------------------"); - printf("\n Multilevel: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->TotalTmr)); - printf("\n Coarsening: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->CoarsenTmr)); - printf("\n Matching: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->MatchTmr)); - printf("\n Contract: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->ContractTmr)); - printf("\n Initial Partition: \t %7.3"PRREAL"", gk_getcputimer(ctrl->InitPartTmr)); - printf("\n Uncoarsening: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->UncoarsenTmr)); - printf("\n Refinement: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->RefTmr)); - printf("\n Projection: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->ProjectTmr)); - printf("\n Splitting: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->SplitTmr)); -/* - printf("\n Aux1Tmr: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->Aux1Tmr)); - printf("\n Aux2Tmr: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->Aux2Tmr)); - printf("\n Aux3Tmr: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->Aux3Tmr)); -*/ - printf("\n********************************************************************\n"); -} - - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/util.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/util.c deleted file mode 100644 index 7fbc46726ef..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/util.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 1997, Regents of the University of Minnesota - * - * util.c - * - * This function contains various utility routines - * - * Started 9/28/95 - * George - * - * $Id: util.c 10495 2011-07-06 16:04:45Z karypis $ - */ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function initializes the random number generator - */ -/*************************************************************************/ -void InitRandom(idx_t seed) -{ - isrand((seed == -1 ? 4321 : seed)); -} - - -/*************************************************************************/ -/*! Returns the highest weight index of x[i]*y[i] - */ -/*************************************************************************/ -idx_t iargmax_nrm(size_t n, idx_t *x, real_t *y) -{ - idx_t i, max=0; - - for (i=1; i x[max]*y[max] ? i : max); - - return max; -} - - -/*************************************************************************/ -/*! These functions return the index of the maximum element in a vector - */ -/*************************************************************************/ -idx_t iargmax_strd(size_t n, idx_t *x, idx_t incx) -{ - size_t i, max=0; - - n *= incx; - for (i=incx; i x[max] ? i : max); - - return max/incx; -} - - -/*************************************************************************/ -/*! These functions return the index of the almost maximum element in a - vector - */ -/*************************************************************************/ -idx_t rargmax2(size_t n, real_t *x) -{ - size_t i, max1, max2; - - if (x[0] > x[1]) { - max1 = 0; - max2 = 1; - } - else { - max1 = 1; - max2 = 0; - } - - for (i=2; i x[max1]) { - max2 = max1; - max1 = i; - } - else if (x[i] > x[max2]) - max2 = i; - } - - return max2; -} - - -/*************************************************************************/ -/*! These functions return the index of the second largest elements in the - vector formed by x.y where '.' is element-wise multiplication */ -/*************************************************************************/ -idx_t iargmax2_nrm(size_t n, idx_t *x, real_t *y) -{ - size_t i, max1, max2; - - if (x[0]*y[0] > x[1]*y[1]) { - max1 = 0; - max2 = 1; - } - else { - max1 = 1; - max2 = 0; - } - - for (i=2; i x[max1]*y[max1]) { - max2 = max1; - max1 = i; - } - else if (x[i]*y[i] > x[max2]*y[max2]) - max2 = i; - } - - return max2; -} - - -/*************************************************************************/ -/*! converts a signal code into a Metis return code - */ -/*************************************************************************/ -int metis_rcode(int sigrval) -{ - switch (sigrval) { - case 0: - return METIS_OK; - break; - case SIGMEM: - return METIS_ERROR_MEMORY; - break; - default: - return METIS_ERROR; - break; - } -} - - diff --git a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/wspace.c b/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/wspace.c deleted file mode 100644 index a474c3cb6d4..00000000000 --- a/Sofa/Component/LinearSolver/Direct/extlibs/metis-5.1.0/libmetis/wspace.c +++ /dev/null @@ -1,214 +0,0 @@ -/*! -\file -\brief Functions dealing with memory allocation and workspace management - -\date Started 2/24/96 -\author George -\author Copyright 1997-2009, Regents of the University of Minnesota -\version $Id: wspace.c 10492 2011-07-06 09:28:42Z karypis $ -*/ - -#include "metislib.h" - - -/*************************************************************************/ -/*! This function allocates memory for the workspace */ -/*************************************************************************/ -void AllocateWorkSpace(ctrl_t *ctrl, graph_t *graph) -{ - size_t coresize; - - switch (ctrl->optype) { - case METIS_OP_PMETIS: - coresize = 3*(graph->nvtxs+1)*sizeof(idx_t) + - 5*(ctrl->nparts+1)*graph->ncon*sizeof(idx_t) + - 5*(ctrl->nparts+1)*graph->ncon*sizeof(real_t); - break; - default: - coresize = 4*(graph->nvtxs+1)*sizeof(idx_t) + - 5*(ctrl->nparts+1)*graph->ncon*sizeof(idx_t) + - 5*(ctrl->nparts+1)*graph->ncon*sizeof(real_t); - } - /*coresize = 0;*/ - ctrl->mcore = gk_mcoreCreate(coresize); - - ctrl->nbrpoolsize = 0; - ctrl->nbrpoolcpos = 0; -} - - -/*************************************************************************/ -/*! This function allocates refinement-specific memory for the workspace */ -/*************************************************************************/ -void AllocateRefinementWorkSpace(ctrl_t *ctrl, idx_t nbrpoolsize) -{ - ctrl->nbrpoolsize = nbrpoolsize; - ctrl->nbrpoolcpos = 0; - ctrl->nbrpoolreallocs = 0; - - switch (ctrl->objtype) { - case METIS_OBJTYPE_CUT: - ctrl->cnbrpool = (cnbr_t *)gk_malloc(ctrl->nbrpoolsize*sizeof(cnbr_t), - "AllocateRefinementWorkSpace: cnbrpool"); - break; - - case METIS_OBJTYPE_VOL: - ctrl->vnbrpool = (vnbr_t *)gk_malloc(ctrl->nbrpoolsize*sizeof(vnbr_t), - "AllocateRefinementWorkSpace: vnbrpool"); - break; - - default: - gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); - } - - - /* Allocate the memory for the sparse subdomain graph */ - if (ctrl->minconn) { - ctrl->pvec1 = imalloc(ctrl->nparts+1, "AllocateRefinementWorkSpace: pvec1"); - ctrl->pvec2 = imalloc(ctrl->nparts+1, "AllocateRefinementWorkSpace: pvec2"); - ctrl->maxnads = ismalloc(ctrl->nparts, INIT_MAXNAD, "AllocateRefinementWorkSpace: maxnads"); - ctrl->nads = imalloc(ctrl->nparts, "AllocateRefinementWorkSpace: nads"); - ctrl->adids = iAllocMatrix(ctrl->nparts, INIT_MAXNAD, 0, "AllocateRefinementWorkSpace: adids"); - ctrl->adwgts = iAllocMatrix(ctrl->nparts, INIT_MAXNAD, 0, "AllocateRefinementWorkSpace: adwgts"); - } -} - - -/*************************************************************************/ -/*! This function frees the workspace */ -/*************************************************************************/ -void FreeWorkSpace(ctrl_t *ctrl) -{ - gk_mcoreDestroy(&ctrl->mcore, ctrl->dbglvl&METIS_DBG_INFO); - - IFSET(ctrl->dbglvl, METIS_DBG_INFO, - printf(" nbrpool statistics\n" - " nbrpoolsize: %12zu nbrpoolcpos: %12zu\n" - " nbrpoolreallocs: %12zu\n\n", - ctrl->nbrpoolsize, ctrl->nbrpoolcpos, - ctrl->nbrpoolreallocs)); - - gk_free((void **)&ctrl->cnbrpool, &ctrl->vnbrpool, LTERM); - ctrl->nbrpoolsize = 0; - ctrl->nbrpoolcpos = 0; - - if (ctrl->minconn) { - iFreeMatrix(&(ctrl->adids), ctrl->nparts, INIT_MAXNAD); - iFreeMatrix(&(ctrl->adwgts), ctrl->nparts, INIT_MAXNAD); - - gk_free((void **)&ctrl->pvec1, &ctrl->pvec2, - &ctrl->maxnads, &ctrl->nads, LTERM); - } -} - - -/*************************************************************************/ -/*! This function allocate space from the workspace/heap */ -/*************************************************************************/ -void *wspacemalloc(ctrl_t *ctrl, size_t nbytes) -{ - return gk_mcoreMalloc(ctrl->mcore, nbytes); -} - - -/*************************************************************************/ -/*! This function sets a marker in the stack of malloc ops to be used - subsequently for freeing purposes */ -/*************************************************************************/ -void wspacepush(ctrl_t *ctrl) -{ - gk_mcorePush(ctrl->mcore); -} - - -/*************************************************************************/ -/*! This function frees all mops since the last push */ -/*************************************************************************/ -void wspacepop(ctrl_t *ctrl) -{ - gk_mcorePop(ctrl->mcore); -} - - -/*************************************************************************/ -/*! This function allocate space from the core */ -/*************************************************************************/ -idx_t *iwspacemalloc(ctrl_t *ctrl, idx_t n) -{ - return (idx_t *)wspacemalloc(ctrl, n*sizeof(idx_t)); -} - - -/*************************************************************************/ -/*! This function allocate space from the core */ -/*************************************************************************/ -real_t *rwspacemalloc(ctrl_t *ctrl, idx_t n) -{ - return (real_t *)wspacemalloc(ctrl, n*sizeof(real_t)); -} - - -/*************************************************************************/ -/*! This function allocate space from the core */ -/*************************************************************************/ -ikv_t *ikvwspacemalloc(ctrl_t *ctrl, idx_t n) -{ - return (ikv_t *)wspacemalloc(ctrl, n*sizeof(ikv_t)); -} - - -/*************************************************************************/ -/*! This function resets the cnbrpool */ -/*************************************************************************/ -void cnbrpoolReset(ctrl_t *ctrl) -{ - ctrl->nbrpoolcpos = 0; -} - - -/*************************************************************************/ -/*! This function gets the next free index from cnbrpool */ -/*************************************************************************/ -idx_t cnbrpoolGetNext(ctrl_t *ctrl, idx_t nnbrs) -{ - ctrl->nbrpoolcpos += nnbrs; - - if (ctrl->nbrpoolcpos > ctrl->nbrpoolsize) { - ctrl->nbrpoolsize += gk_max(10*nnbrs, ctrl->nbrpoolsize/2); - - ctrl->cnbrpool = (cnbr_t *)gk_realloc(ctrl->cnbrpool, - ctrl->nbrpoolsize*sizeof(cnbr_t), "cnbrpoolGet: cnbrpool"); - ctrl->nbrpoolreallocs++; - } - - return ctrl->nbrpoolcpos - nnbrs; -} - - -/*************************************************************************/ -/*! This function resets the vnbrpool */ -/*************************************************************************/ -void vnbrpoolReset(ctrl_t *ctrl) -{ - ctrl->nbrpoolcpos = 0; -} - - -/*************************************************************************/ -/*! This function gets the next free index from vnbrpool */ -/*************************************************************************/ -idx_t vnbrpoolGetNext(ctrl_t *ctrl, idx_t nnbrs) -{ - ctrl->nbrpoolcpos += nnbrs; - - if (ctrl->nbrpoolcpos > ctrl->nbrpoolsize) { - ctrl->nbrpoolsize += gk_max(10*nnbrs, ctrl->nbrpoolsize/2); - - ctrl->vnbrpool = (vnbr_t *)gk_realloc(ctrl->vnbrpool, - ctrl->nbrpoolsize*sizeof(vnbr_t), "vnbrpoolGet: vnbrpool"); - ctrl->nbrpoolreallocs++; - } - - return ctrl->nbrpoolcpos - nnbrs; -} - diff --git a/Sofa/Component/LinearSolver/Direct/tests/CMakeLists.txt b/Sofa/Component/LinearSolver/Direct/tests/CMakeLists.txt index 2fd498d0d28..660db21e75a 100644 --- a/Sofa/Component/LinearSolver/Direct/tests/CMakeLists.txt +++ b/Sofa/Component/LinearSolver/Direct/tests/CMakeLists.txt @@ -10,4 +10,5 @@ add_executable(${PROJECT_NAME} ${SOURCE_FILES}) # dependencies are managed directly in the target_link_libraries pass target_link_libraries(${PROJECT_NAME} Sofa.Testing Sofa.Component.LinearSolver.Direct + metis ) diff --git a/Sofa/Component/LinearSolver/Iterative/src/sofa/component/linearsolver/iterative/MatrixLinearSolver.inl b/Sofa/Component/LinearSolver/Iterative/src/sofa/component/linearsolver/iterative/MatrixLinearSolver.inl index e4e87e3b355..39297dbb067 100644 --- a/Sofa/Component/LinearSolver/Iterative/src/sofa/component/linearsolver/iterative/MatrixLinearSolver.inl +++ b/Sofa/Component/LinearSolver/Iterative/src/sofa/component/linearsolver/iterative/MatrixLinearSolver.inl @@ -45,14 +45,14 @@ using namespace sofa::component::linearsystem; template MatrixLinearSolver::MatrixLinearSolver() : Inherit() + , d_parallelInverseProduct(initData(&d_parallelInverseProduct, false, + "parallelInverseProduct", "Parallelize the computation of the product J*M^{-1}*J^T " + "where M is the matrix of the linear system and J is any " + "matrix with compatible dimensions")) , invertData() , linearSystem() , currentMFactor(), currentBFactor(), currentKFactor() , l_linearSystem(initLink("linearSystem", "The linear system to solve")) - , d_parallelInverseProduct(initData(&d_parallelInverseProduct, false, - "parallelInverseProduct", "Parallelize the computation of the product J*M^{-1}*J^T " - "where M is the matrix of the linear system and J is any " - "matrix with compatible dimensions")) { this->addUpdateCallback("parallelInverseProduct", {&d_parallelInverseProduct}, [this](const core::DataTracker& tracker) -> sofa::core::objectmodel::ComponentState diff --git a/Sofa/Component/LinearSolver/Preconditioner/CMakeLists.txt b/Sofa/Component/LinearSolver/Preconditioner/CMakeLists.txt index 77acb227add..e8183f8cfd6 100644 --- a/Sofa/Component/LinearSolver/Preconditioner/CMakeLists.txt +++ b/Sofa/Component/LinearSolver/Preconditioner/CMakeLists.txt @@ -36,8 +36,22 @@ sofa_find_package(Sofa.Component.ODESolver.Backward REQUIRED) sofa_find_package(Sofa.Component.LinearSolver.Iterative REQUIRED) sofa_find_package(Sofa.Component.LinearSolver.Direct REQUIRED) +find_package(metis 5.1.0 EXACT QUIET) +if(NOT metis_FOUND AND SOFA_ALLOW_FETCH_DEPENDENCIES) + message("Sofa.Component.LinearSolver.Direct: DEPENDENCY metis NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is ON, fetching metis...") + include(FetchContent) + FetchContent_Declare(metis + GIT_REPOSITORY https://github.com/sofa-framework/METIS + GIT_TAG v5.1.0-ModernInstall + ) + FetchContent_MakeAvailable(metis) +elseif (NOT metis_FOUND) + message(FATAL_ERROR "Sofa.Component.LinearSolver.Direct: DEPENDENCY metis NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is OFF and thus cannot be fetched. Install metis (version=5.1.0), or enable SOFA_ALLOW_FETCH_DEPENDENCIES to fix this issue.") +endif() + add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${WRAPPER_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Simulation.Core Sofa.Component.ODESolver.Backward Sofa.Component.LinearSolver.Iterative Sofa.Component.LinearSolver.Direct) +target_link_libraries(${PROJECT_NAME} PRIVATE metis) sofa_create_package_with_targets( PACKAGE_NAME ${PROJECT_NAME} diff --git a/Sofa/Component/LinearSystem/src/sofa/component/linearsystem/matrixaccumulators/ConstantLocalMatrix.h b/Sofa/Component/LinearSystem/src/sofa/component/linearsystem/matrixaccumulators/ConstantLocalMatrix.h index cdb9a88978c..4442e1bd00d 100644 --- a/Sofa/Component/LinearSystem/src/sofa/component/linearsystem/matrixaccumulators/ConstantLocalMatrix.h +++ b/Sofa/Component/LinearSystem/src/sofa/component/linearsystem/matrixaccumulators/ConstantLocalMatrix.h @@ -52,6 +52,8 @@ class ConstantLocalMatrix : public virtual AssemblingMatrixAccumulator template void ConstantLocalMatrix::add(const core::matrixaccumulator::no_check_policy&, sofa::SignedIndex row, sofa::SignedIndex col, float value) { + SOFA_UNUSED(row); + SOFA_UNUSED(col); static_cast(this->m_globalMatrix)->colsValue[insertionOrderList[currentId++]] += this->m_cachedFactor * value; } @@ -59,6 +61,8 @@ void ConstantLocalMatrix::add(const core::matrixaccumulator::no_chec template void ConstantLocalMatrix::add(const core::matrixaccumulator::no_check_policy&, sofa::SignedIndex row, sofa::SignedIndex col, double value) { + SOFA_UNUSED(row); + SOFA_UNUSED(col); static_cast(this->m_globalMatrix)->colsValue[insertionOrderList[currentId++]] += this->m_cachedFactor * value; } diff --git a/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp b/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp index a1e0825af21..bf951a8e182 100644 --- a/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp +++ b/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp @@ -250,9 +250,23 @@ template dfdx(10, 20) += 0.; } - void addForce(const sofa::core::MechanicalParams*, typename Inherit1::DataVecDeriv& f, const typename Inherit1::DataVecCoord& x, const typename Inherit1::DataVecDeriv& v) override {} - void addDForce(const sofa::core::MechanicalParams* mparams, typename Inherit1::DataVecDeriv& df, const typename Inherit1::DataVecDeriv& dx ) override {} - SReal getPotentialEnergy(const sofa::core::MechanicalParams*, const typename Inherit1::DataVecCoord& x) const override { return 0._sreal; } + void addForce(const sofa::core::MechanicalParams*, typename Inherit1::DataVecDeriv& f, const typename Inherit1::DataVecCoord& x, const typename Inherit1::DataVecDeriv& v) override + { + SOFA_UNUSED(f); + SOFA_UNUSED(x); + SOFA_UNUSED(v); + } + void addDForce(const sofa::core::MechanicalParams* mparams, typename Inherit1::DataVecDeriv& df, const typename Inherit1::DataVecDeriv& dx ) override + { + SOFA_UNUSED(mparams); + SOFA_UNUSED(df); + SOFA_UNUSED(dx); + } + SReal getPotentialEnergy(const sofa::core::MechanicalParams*, const typename Inherit1::DataVecCoord& x) const override + { + SOFA_UNUSED(x); + return 0._sreal; + } }; /// Empty matrix class with the interface of a BaseMatrix @@ -273,26 +287,42 @@ class EmptyMatrix : public sofa::linearalgebra::BaseMatrix } SReal element(Index i, Index j) const override { + SOFA_UNUSED(i); + SOFA_UNUSED(j); return {}; } void resize(Index nbRow, Index nbCol) override { + SOFA_UNUSED(nbRow); + SOFA_UNUSED(nbCol); } void clear() override { } void set(Index i, Index j, double v) override { + SOFA_UNUSED(i); + SOFA_UNUSED(j); + SOFA_UNUSED(v); } void add(Index row, Index col, double v) override { + SOFA_UNUSED(row); + SOFA_UNUSED(col); + SOFA_UNUSED(v); //add method is empty to prevent crashes in tests } void add(Index row, Index col, const sofa::type::Mat3x3d& _M) override { + SOFA_UNUSED(row); + SOFA_UNUSED(col); + SOFA_UNUSED(_M); } void add(Index row, Index col, const sofa::type::Mat3x3f& _M) override { + SOFA_UNUSED(row); + SOFA_UNUSED(col); + SOFA_UNUSED(_M); } static const char* Name() { return "EmptyMatrix"; } }; diff --git a/Sofa/Component/Mass/tests/UniformMass_test.cpp b/Sofa/Component/Mass/tests/UniformMass_test.cpp index aa1ce288189..af23f730459 100644 --- a/Sofa/Component/Mass/tests/UniformMass_test.cpp +++ b/Sofa/Component/Mass/tests/UniformMass_test.cpp @@ -338,7 +338,7 @@ struct UniformMassTest : public BaseTest "" " " " " - " " + " " " " ; const Node::SPtr root = SceneLoaderXML::loadFromMemory("loadWithNoParam", scene.c_str()); diff --git a/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.h b/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.h index 7bf769b9c3a..4cc2bfbae6d 100644 --- a/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.h +++ b/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.h @@ -82,41 +82,27 @@ class EllipsoidForceField : public core::behavior::ForceField }; - union - { - SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DEPRECATED() Data > contacts; ///< Contacts - Data > d_contacts; ///< Contacts - }; + Data > d_contacts; ///< Vector of contacts + SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DISABLED() DeprecatedAndRemoved contacts; ///< Contacts EllipsoidForceFieldInternalData data; public: - union - { - Data d_center; ///< ellipsoid center - SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DEPRECATED() Data center; ///< ellipsoid center - }; - union - { - Data d_vradius; ///< ellipsoid radius - SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DEPRECATED() Data vradius; ///< ellipsoid radius - }; - union - { - Data d_stiffness; ///< force stiffness (positive to repulse outward, negative inward) - SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DEPRECATED() Data stiffness; ///< force stiffness (positive to repulse outward, negative inward) - }; - union - { - Data d_damping; ///< force damping - SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DEPRECATED() Data damping; ///< force damping - }; - union - { - Data d_color; ///< ellipsoid color. (default=0,0.5,1.0,1.0) - SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DEPRECATED() Data color; ///< ellipsoid color. (default=0,0.5,1.0,1.0) - }; + Data d_center; ///< ellipsoid center + SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DISABLED() DeprecatedAndRemoved center; ///< ellipsoid center + + Data d_vradius; ///< ellipsoid radius + SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DISABLED() DeprecatedAndRemoved vradius; ///< ellipsoid radius + + Data d_stiffness; ///< force stiffness (positive to repulse outward, negative inward) + SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DISABLED() DeprecatedAndRemoved stiffness; ///< force stiffness (positive to repulse outward, negative inward) + + Data d_damping; ///< force damping + SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DISABLED() DeprecatedAndRemoved damping; ///< force damping + + Data d_color; ///< ellipsoid color. (default=0,0.5,1.0,1.0) + SOFA_ELLIPSOIDFORCEFIELD_RENAMEDDATA_DISABLED() DeprecatedAndRemoved color; ///< ellipsoid color. (default=0,0.5,1.0,1.0) protected: EllipsoidForceField(); diff --git a/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.inl b/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.inl index 4459517d8eb..49c6a8c2527 100644 --- a/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.inl +++ b/Sofa/Component/MechanicalLoad/src/sofa/component/mechanicalload/EllipsoidForceField.inl @@ -57,7 +57,7 @@ namespace sofa::component::mechanicalload template EllipsoidForceField::EllipsoidForceField() - : d_contacts(initData(&d_contacts,"contacts", "Contacts")) + : d_contacts(initData(&d_contacts,"contacts", "Vector of contacts")) , d_center(initData(&d_center, "center", "ellipsoid center")) , d_vradius(initData(&d_vradius, "vradius", "ellipsoid radius")) , d_stiffness(initData(&d_stiffness, (Real)500, "stiffness", "force stiffness (positive to repulse outward, negative inward)")) @@ -69,12 +69,6 @@ EllipsoidForceField::EllipsoidForceField() template EllipsoidForceField::~EllipsoidForceField() { - d_contacts.~Data(); - d_center.~Data(); - d_vradius.~Data(); - d_stiffness.~Data(); - d_damping.~Data(); - d_color.~Data(); } template @@ -115,7 +109,7 @@ void EllipsoidForceField::addForce(const sofa::core::MechanicalParams { Coord dp = p1[i] - center; Real norm2 = 0; - for (int j=0; j void TriangularFEMForceFieldOptim::computePrincipalStress() { const VecElement& triangles = m_topology->getTriangles(); - - sofa::helper::ReadAccessor< core::objectmodel::Data< VecTriangleState > > triStates = d_triangleState; sofa::helper::WriteAccessor< core::objectmodel::Data< VecTriangleInfo > > triInfos = d_triangleInfo; Real minStress = 0; diff --git a/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/EdgeSetTopologyContainer.cpp b/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/EdgeSetTopologyContainer.cpp index 791d760f0f9..26f90cca3ca 100644 --- a/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/EdgeSetTopologyContainer.cpp +++ b/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/EdgeSetTopologyContainer.cpp @@ -122,7 +122,7 @@ void EdgeSetTopologyContainer::createEdgesAroundVertexArray() if (edge[0] >= unsigned(nbPoints) || edge[1] >= unsigned(nbPoints)) { - msg_warning() << "EdgesAroundVertex creation failed, Edge buffer is not concistent with number of points: Edge: " << edge << " for: " << nbPoints << " points."; + msg_warning() << "EdgesAroundVertex creation failed, Edge buffer is not consistent with number of points, Edge: " << edge << " for: " << nbPoints << " points."; continue; } diff --git a/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/TriangleSetTopologyContainer.cpp b/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/TriangleSetTopologyContainer.cpp index 96b6d62727b..f7a81582eb8 100644 --- a/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/TriangleSetTopologyContainer.cpp +++ b/Sofa/Component/Topology/Container/Dynamic/src/sofa/component/topology/container/dynamic/TriangleSetTopologyContainer.cpp @@ -125,6 +125,13 @@ void TriangleSetTopologyContainer::createTrianglesAroundVertexArray() m_trianglesAroundVertex.resize(getNbPoints()); for (size_t i = 0; i < m_triangle.size(); ++i) { + if (m_triangle[i][0] >= getNbPoints() || m_triangle[i][1] >= getNbPoints() || m_triangle[i][2] >= getNbPoints()) + { + msg_warning() << "trianglesAroundVertex creation failed, Triangle buffer is not consistent with number of points, Triangle: " << m_triangle[i] << " for: " << getNbPoints() << " points."; + continue; + } + + // adding edge i in the edge shell of both points for (unsigned int j=0; j<3; ++j) m_trianglesAroundVertex[ m_triangle[i][j] ].push_back( (TriangleID)i ); diff --git a/Sofa/Component/Visual/CMakeLists.txt b/Sofa/Component/Visual/CMakeLists.txt index f8d24c40363..bd66bcd60b5 100644 --- a/Sofa/Component/Visual/CMakeLists.txt +++ b/Sofa/Component/Visual/CMakeLists.txt @@ -36,13 +36,13 @@ set(SOURCE_FILES ) sofa_find_package(Sofa.Simulation.Core REQUIRED) -sofa_find_package(TinyXML REQUIRED) # BaseCamera +sofa_find_package(TinyXML2 REQUIRED) # BaseCamera sofa_find_package(Sofa.Component.Topology.Container.Grid REQUIRED) # VisualModelImpl add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Simulation.Core) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Component.Topology.Container.Grid) -target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml) +target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml2::tinyxml2) sofa_create_package_with_targets( PACKAGE_NAME ${PROJECT_NAME} diff --git a/Sofa/Component/Visual/Sofa.Component.VisualConfig.cmake.in b/Sofa/Component/Visual/Sofa.Component.VisualConfig.cmake.in index ee078d4732f..f1e48b20a1d 100644 --- a/Sofa/Component/Visual/Sofa.Component.VisualConfig.cmake.in +++ b/Sofa/Component/Visual/Sofa.Component.VisualConfig.cmake.in @@ -4,7 +4,7 @@ @PACKAGE_INIT@ find_package(Sofa.Simulation.Core QUIET REQUIRED) -find_package(TinyXML QUIET REQUIRED) +find_package(TinyXML2 QUIET REQUIRED) find_package(Sofa.Component.Topology.Container.Grid QUIET REQUIRED) if(NOT TARGET @PROJECT_NAME@) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/BaseCamera.cpp b/Sofa/Component/Visual/src/sofa/component/visual/BaseCamera.cpp index ea98dce9ebe..ea658e27654 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/BaseCamera.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/BaseCamera.cpp @@ -36,7 +36,7 @@ using Mat4 = sofa::type::Mat4x4; using sofa::helper::isEqual; #include -#include +#include using sofa::type::RGBAColor ; @@ -782,13 +782,13 @@ void BaseCamera::setDefaultView(const type::Vec3 & gravity) computeZ(); } -void BaseCameraXMLExportSingleParameter(TiXmlElement* root, core::objectmodel::BaseData& data, const std::string& comment) +void BaseCameraXMLExportSingleParameter(tinyxml2::XMLElement* root, core::objectmodel::BaseData& data, const std::string& comment) { - TiXmlElement* node = new TiXmlElement( data.getName().c_str() ); + tinyxml2::XMLElement* node = root->GetDocument()->NewElement( data.getName().c_str() ); node->SetAttribute("value", data.getValueString().c_str() ); if(!comment.empty()) { - TiXmlComment* com = new TiXmlComment( comment.c_str() ); + tinyxml2::XMLComment* com = root->GetDocument()->NewComment( comment.c_str() ); root->LinkEndChild(com); } root->LinkEndChild(node); @@ -796,11 +796,11 @@ void BaseCameraXMLExportSingleParameter(TiXmlElement* root, core::objectmodel::B bool BaseCamera::exportParametersInFile(const std::string& viewFilename) { - TiXmlDocument doc; - TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" ); + tinyxml2::XMLDocument doc; + tinyxml2::XMLDeclaration* decl = doc.NewDeclaration(); doc.LinkEndChild( decl ); - TiXmlElement* root = new TiXmlElement( "Camera" ); + tinyxml2::XMLElement* root = doc.NewElement( "Camera" ); root->SetAttribute("version", "1.0" ); doc.LinkEndChild( root ); @@ -816,14 +816,14 @@ bool BaseCamera::exportParametersInFile(const std::string& viewFilename) return doc.SaveFile( viewFilename.c_str() ); } -bool BaseCameraXMLImportSingleParameter(TiXmlElement* root, core::objectmodel::BaseData& data, BaseCamera* c) +bool BaseCameraXMLImportSingleParameter(tinyxml2::XMLElement* root, core::objectmodel::BaseData& data, BaseCamera* c) { if(root) { - TiXmlNode* node = root->FirstChild( data.getName().c_str() ); + tinyxml2::XMLNode* node = root->FirstChildElement( data.getName().c_str() ); if(node) { - const TiXmlElement* element = node->ToElement(); + const tinyxml2::XMLElement* element = node->ToElement(); if(element) { const char* attrValue; @@ -862,16 +862,14 @@ bool BaseCamera::importParametersFromFile(const std::string& viewFilename) bool result = true; msg_info() << "Reading " << viewFilename << " for view parameters."; - TiXmlDocument doc(viewFilename.c_str()); - if (!doc.LoadFile()) + tinyxml2::XMLDocument doc; + if (doc.LoadFile(viewFilename.c_str()) != tinyxml2::XML_SUCCESS) { result = false; } - const TiXmlHandle hDoc(&doc); - TiXmlElement* root; - - root = hDoc.FirstChildElement().ToElement(); + tinyxml2::XMLHandle hDoc(&doc); + tinyxml2::XMLElement* root = hDoc.FirstChildElement().ToElement(); if (!root) result = false; diff --git a/Sofa/GUI/Common/CMakeLists.txt b/Sofa/GUI/Common/CMakeLists.txt index f6cb2e6dd63..266583e4eb4 100644 --- a/Sofa/GUI/Common/CMakeLists.txt +++ b/Sofa/GUI/Common/CMakeLists.txt @@ -3,7 +3,7 @@ project(Sofa.GUI.Common LANGUAGES CXX) find_package(cxxopts 3.1 QUIET) if(NOT cxxopts_FOUND AND SOFA_ALLOW_FETCH_DEPENDENCIES) - message("Sofa.GUI.Common: DEPENDENCY cxxopt NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is ON, fetching cxxopt...") + message("Sofa.GUI.Common: DEPENDENCY cxxopts NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is ON, fetching cxxopts...") include(FetchContent) FetchContent_Declare(cxxopts @@ -23,7 +23,7 @@ if(NOT cxxopts_FOUND AND SOFA_ALLOW_FETCH_DEPENDENCIES) add_subdirectory(${cxxopts_SOURCE_DIR} ${cxxopts_BINARY_DIR}) endif() elseif (NOT cxxopts_FOUND) - message(FATAL_ERROR "Sofa.GUI.Common: DEPENDENCY cxxopt NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is OFF and thus cannot be fetched. Install libcxxopts-dev (version>=3.1.0), or enable SOFA_ALLOW_FETCH_DEPENDENCIES to fix this issue.") + message(FATAL_ERROR "Sofa.GUI.Common: DEPENDENCY cxxopts NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is OFF and thus cannot be fetched. Install libcxxopts-dev (version>=3.1.0), or enable SOFA_ALLOW_FETCH_DEPENDENCIES to fix this issue.") endif() set(SOFAGUICOMMON_ROOT src/sofa/gui/common) diff --git a/Sofa/GUI/Qt/CMakeLists.txt b/Sofa/GUI/Qt/CMakeLists.txt index 8de94a80a93..6076ed56190 100644 --- a/Sofa/GUI/Qt/CMakeLists.txt +++ b/Sofa/GUI/Qt/CMakeLists.txt @@ -106,7 +106,7 @@ sofa_find_package(FFMPEG_exec BOTH_SCOPES) # TinyXML if(SOFA_DUMP_VISITOR_INFO) - sofa_find_package(TinyXML REQUIRED BOTH_SCOPES) + sofa_find_package(TinyXML2 REQUIRED BOTH_SCOPES) endif() set(SRC_ROOT src/sofa/gui/qt) @@ -324,7 +324,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Component.SceneUtility) target_link_libraries(${PROJECT_NAME} PUBLIC ${QT_TARGETS}) if(SOFA_DUMP_VISITOR_INFO) - target_link_libraries(${PROJECT_NAME} PUBLIC tinyxml) + target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml2::tinyxml2) endif() if(Sofa.GL_FOUND) diff --git a/Sofa/GUI/Qt/Sofa.GUI.QtConfig.cmake.in b/Sofa/GUI/Qt/Sofa.GUI.QtConfig.cmake.in index 1e3bcd227f9..e41f4695dd7 100644 --- a/Sofa/GUI/Qt/Sofa.GUI.QtConfig.cmake.in +++ b/Sofa/GUI/Qt/Sofa.GUI.QtConfig.cmake.in @@ -41,9 +41,7 @@ endif() if(SOFA_GUI_QT_HAVE_NODEEDITOR) find_package(NodeEditor QUIET REQUIRED) endif() -if(SOFA_GUI_QT_HAVE_TINYXML) - find_package(TinyXML QUIET REQUIRED) -endif() + if(NOT TARGET @PROJECT_NAME@) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.cpp b/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.cpp old mode 100644 new mode 100755 index 281ca2134b1..83e7b0492c7 --- a/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.cpp +++ b/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.cpp @@ -40,13 +40,13 @@ bool cmpTime(const dataTime &a, const dataTime &b) { return a.time > b.time;} bool GraphVisitor::load(std::string &file) { //Open it using TinyXML - TiXmlDocument doc; + tinyxml2::XMLDocument doc; doc.Parse(file.c_str()); //std::cerr << "GRAPH:"<< std::endl << file << std::endl; - TiXmlHandle hDoc(&doc); - TiXmlNode* pElem; + tinyxml2::XMLHandle hDoc(&doc); + tinyxml2::XMLNode* pElem; //Getting the root of the file pElem=hDoc.FirstChildElement().ToElement(); @@ -94,10 +94,10 @@ bool GraphVisitor::load(std::string &file) } -void GraphVisitor::openAttribute ( TiXmlElement* element, QTreeWidgetItem* item) +void GraphVisitor::openAttribute ( tinyxml2::XMLElement* element, QTreeWidgetItem* item) { if (!element) return; - TiXmlAttribute* attribute=element->FirstAttribute(); + const tinyxml2::XMLAttribute* attribute=element->FirstAttribute(); while (attribute) { std::string nameOfAttribute(attribute->Name()); @@ -110,11 +110,11 @@ void GraphVisitor::openAttribute ( TiXmlElement* element, QTreeWidgetItem* -void GraphVisitor::openTime ( TiXmlNode* node, QTreeWidgetItem* item) +void GraphVisitor::openTime ( tinyxml2::XMLNode* node, QTreeWidgetItem* item) { - TiXmlElement* element=node->ToElement(); + tinyxml2::XMLElement* element=node->ToElement(); if (!element) return; - TiXmlAttribute* attribute=element->FirstAttribute(); + const tinyxml2::XMLAttribute* attribute=element->FirstAttribute(); double timeSec= getTime(attribute); double time = 100.0*timeSec/totalTime; std::ostringstream s; @@ -123,13 +123,13 @@ void GraphVisitor::openTime ( TiXmlNode* node, QTreeWidgetItem* item) s << time << "%"; - TiXmlNode* parent = node->Parent(); + tinyxml2::XMLNode* parent = node->Parent(); if (parent) { std::string nodeType = parent->Value(); if (nodeType == "Component") { - TiXmlAttribute* attribute=parent->ToElement()->FirstAttribute(); + const tinyxml2::XMLAttribute* attribute=parent->ToElement()->FirstAttribute(); std::string componentName, componentType, componentPtr; while (attribute) { @@ -186,7 +186,7 @@ void GraphVisitor::openTime ( TiXmlNode* node, QTreeWidgetItem* item) addTime(item, s.str()); } -double GraphVisitor::getTime(TiXmlAttribute* attribute) const +double GraphVisitor::getTime(const tinyxml2::XMLAttribute* attribute) const { static double conversion=1.0/(double)CTime::getTicksPerSec(); std::string valueOfAttribute(attribute->Value()); @@ -194,25 +194,25 @@ double GraphVisitor::getTime(TiXmlAttribute* attribute) const return result; } -double GraphVisitor::getTotalTime(TiXmlNode* node) const +double GraphVisitor::getTotalTime(tinyxml2::XMLNode* node) const { - for ( TiXmlNode* child = node->FirstChild(); child != 0; child = child->NextSibling()) + for ( tinyxml2::XMLNode* child = node->FirstChild(); child != 0; child = child->NextSibling()) { std::string nameOfNode=child->Value(); if (nameOfNode == "TotalTime") { - TiXmlAttribute* attribute=child->ToElement()->FirstAttribute(); + const tinyxml2::XMLAttribute* attribute=child->ToElement()->FirstAttribute(); double total=getTime(attribute); std::ostringstream out; out << total; - attribute->SetValue(out.str().c_str()); + child->ToElement()->SetAttribute(attribute->Name(),out.str().c_str()); return total; } } return 1; } -QTreeWidgetItem* GraphVisitor::openNode( TiXmlNode* node, QTreeWidgetItem* parent, QTreeWidgetItem* elementAbove) +QTreeWidgetItem* GraphVisitor::openNode( tinyxml2::XMLNode* node, QTreeWidgetItem* parent, QTreeWidgetItem* elementAbove) { if (!node) return NULL; @@ -224,10 +224,10 @@ QTreeWidgetItem* GraphVisitor::openNode( TiXmlNode* node, QTreeWidgetItem* paren // -- Jeremie A. 02/07/2011 //int typeOfNode=node->Type(); QTreeWidgetItem *graphNode=NULL; - if (node->ToDocument()) // case TiXmlNode::DOCUMENT: + if (node->ToDocument()) // case tinyxml2::XMLNode::DOCUMENT: { } - else if (node->ToElement()) // case TiXmlNode::ELEMENT: + else if (node->ToElement()) // case tinyxml2::XMLNode::ELEMENT: { if (nameOfNode == "Time") { @@ -239,14 +239,14 @@ QTreeWidgetItem* GraphVisitor::openNode( TiXmlNode* node, QTreeWidgetItem* paren openAttribute( node->ToElement(), graphNode); } } - else if (node->ToComment()) // case TiXmlNode::COMMENT: + else if (node->ToComment()) // case tinyxml2::XMLNode::COMMENT: { graphNode = addComment(parent, elementAbove, nameOfNode); } - else if (node->ToText()) // case TiXmlNode::TEXT: + else if (node->ToText()) // case tinyxml2::XMLNode::TEXT: { } - else if (node->ToDeclaration()) // case TiXmlNode::DECLARATION: + else if (node->ToDeclaration()) // case tinyxml2::XMLNode::DECLARATION: { } else // default: @@ -256,7 +256,7 @@ QTreeWidgetItem* GraphVisitor::openNode( TiXmlNode* node, QTreeWidgetItem* paren QTreeWidgetItem *element=NULL; timeComponentsBelow.push_back(0); - for ( TiXmlNode* child = node->FirstChild(); child != 0; child = child->NextSibling()) + for ( tinyxml2::XMLNode* child = node->FirstChild(); child != 0; child = child->NextSibling()) { element = openNode( child, graphNode, element); } diff --git a/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.h b/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.h old mode 100644 new mode 100755 index c527858a069..4e056e87a13 --- a/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.h +++ b/Sofa/GUI/Qt/src/sofa/gui/qt/GraphVisitor.h @@ -31,8 +31,8 @@ #include #include -#include -#include +#include +//#include #include #include @@ -54,13 +54,13 @@ class GraphVisitor void setGraph(QTreeWidget* g) {graph = g;} void clear() {graph->clear();} - double getTotalTime(TiXmlNode* node) const; - inline double getTime(TiXmlAttribute* attribute) const; + double getTotalTime(tinyxml2::XMLNode* node) const; + inline double getTime(const tinyxml2::XMLAttribute* attribute) const; protected: - void openTime ( TiXmlNode* element, QTreeWidgetItem* item); - void openAttribute ( TiXmlElement* element, QTreeWidgetItem* item); - QTreeWidgetItem* openNode( TiXmlNode* node, QTreeWidgetItem* parent, QTreeWidgetItem* elementAbove); + void openTime ( tinyxml2::XMLNode* element, QTreeWidgetItem* item); + void openAttribute ( tinyxml2::XMLElement* element, QTreeWidgetItem* item); + QTreeWidgetItem* openNode( tinyxml2::XMLNode* node, QTreeWidgetItem* parent, QTreeWidgetItem* elementAbove); QTreeWidget *graph; WindowVisitor *window; diff --git a/Sofa/framework/Config/cmake/Modules/FindGTest.cmake b/Sofa/framework/Config/cmake/Modules/FindGTest.cmake new file mode 100644 index 00000000000..8e22f79198d --- /dev/null +++ b/Sofa/framework/Config/cmake/Modules/FindGTest.cmake @@ -0,0 +1,294 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindGTest +--------- + +Locate the Google C++ Testing Framework. + +.. versionadded:: 3.20 + Upstream ``GTestConfig.cmake`` is used if possible. + +Imported targets +^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.20 + This module defines the following :prop_tgt:`IMPORTED` targets: + +``GTest::gtest`` + The Google Test ``gtest`` library, if found; adds Thread::Thread + automatically +``GTest::gtest_main`` + The Google Test ``gtest_main`` library, if found + +.. deprecated:: 3.20 + For backwards compatibility, this module defines additionally the + following deprecated :prop_tgt:`IMPORTED` targets (available since 3.5): + +``GTest::GTest`` + The Google Test ``gtest`` library, if found; adds Thread::Thread + automatically +``GTest::Main`` + The Google Test ``gtest_main`` library, if found + + +Result variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project: + +``GTest_FOUND`` + Found the Google Testing framework +``GTEST_INCLUDE_DIRS`` + the directory containing the Google Test headers + +The library variables below are set as normal variables. These +contain debug/optimized keywords when a debugging library is found. + +``GTEST_LIBRARIES`` + The Google Test ``gtest`` library; note it also requires linking + with an appropriate thread library +``GTEST_MAIN_LIBRARIES`` + The Google Test ``gtest_main`` library +``GTEST_BOTH_LIBRARIES`` + Both ``gtest`` and ``gtest_main`` + +Cache variables +^^^^^^^^^^^^^^^ + +The following cache variables may also be set: + +``GTEST_ROOT`` + The root directory of the Google Test installation (may also be + set as an environment variable) +``GTEST_MSVC_SEARCH`` + If compiling with MSVC, this variable can be set to ``MT`` or + ``MD`` (the default) to enable searching a GTest build tree + + +Example usage +^^^^^^^^^^^^^ + +:: + + enable_testing() + find_package(GTest REQUIRED) + + add_executable(foo foo.cc) + target_link_libraries(foo GTest::gtest GTest::gtest_main) + + add_test(AllTestsInFoo foo) + + +Deeper integration with CTest +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +See :module:`GoogleTest` for information on the :command:`gtest_add_tests` +and :command:`gtest_discover_tests` commands. + +.. versionchanged:: 3.9 + Previous CMake versions defined :command:`gtest_add_tests` macro in this + module. +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/GoogleTest.cmake) + +function(__gtest_append_debugs _endvar _library) + if(${_library} AND ${_library}_DEBUG) + set(_output optimized ${${_library}} debug ${${_library}_DEBUG}) + else() + set(_output ${${_library}}) + endif() + set(${_endvar} ${_output} PARENT_SCOPE) +endfunction() + +function(__gtest_find_library _name) + find_library(${_name} + NAMES ${ARGN} + HINTS + ENV GTEST_ROOT + ${GTEST_ROOT} + PATH_SUFFIXES ${_gtest_libpath_suffixes} + ) + mark_as_advanced(${_name}) +endfunction() + +macro(__gtest_determine_windows_library_type _var) + if(EXISTS "${${_var}}") + file(TO_NATIVE_PATH "${${_var}}" _lib_path) + get_filename_component(_name "${${_var}}" NAME_WE) + file(STRINGS "${${_var}}" _match REGEX "${_name}\\.dll" LIMIT_COUNT 1) + if(NOT _match STREQUAL "") + set(${_var}_TYPE SHARED PARENT_SCOPE) + else() + set(${_var}_TYPE UNKNOWN PARENT_SCOPE) + endif() + return() + endif() +endmacro() + +function(__gtest_determine_library_type _var) + if(WIN32) + # For now, at least, only Windows really needs to know the library type + __gtest_determine_windows_library_type(${_var}) + __gtest_determine_windows_library_type(${_var}_RELEASE) + __gtest_determine_windows_library_type(${_var}_DEBUG) + endif() + # If we get here, no determination was made from the above checks + set(${_var}_TYPE UNKNOWN PARENT_SCOPE) +endfunction() + +function(__gtest_import_library _target _var _config) + if(_config) + set(_config_suffix "_${_config}") + else() + set(_config_suffix "") + endif() + + set(_lib "${${_var}${_config_suffix}}") + if(EXISTS "${_lib}") + if(_config) + set_property(TARGET ${_target} APPEND PROPERTY + IMPORTED_CONFIGURATIONS ${_config}) + endif() + set_target_properties(${_target} PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES${_config_suffix} "CXX") + if(WIN32 AND ${_var}_TYPE STREQUAL SHARED) + set_target_properties(${_target} PROPERTIES + IMPORTED_IMPLIB${_config_suffix} "${_lib}") + else() + set_target_properties(${_target} PROPERTIES + IMPORTED_LOCATION${_config_suffix} "${_lib}") + endif() + endif() +endfunction() + +function(__gtest_define_backwards_compatible_library_targets) + set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} PARENT_SCOPE) + + # Add targets mapping the same library names as defined in + # older versions of CMake's FindGTest + if(NOT TARGET GTest::GTest) + add_library(GTest::GTest INTERFACE IMPORTED) + target_link_libraries(GTest::GTest INTERFACE GTest::gtest) + endif() + if(NOT TARGET GTest::Main) + add_library(GTest::Main INTERFACE IMPORTED) + target_link_libraries(GTest::Main INTERFACE GTest::gtest_main) + endif() +endfunction() + +# + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +# first specifically look for the CMake version of GTest +find_package(GTest QUIET NO_MODULE) + +# if we found the GTest cmake package then we are done, and +# can print what we found and return. +if(GTest_FOUND) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest HANDLE_COMPONENTS CONFIG_MODE) + + set(GTEST_LIBRARIES GTest::gtest) + set(GTEST_MAIN_LIBRARIES GTest::gtest_main) + + __gtest_define_backwards_compatible_library_targets() + + return() +endif() + +if(NOT DEFINED GTEST_MSVC_SEARCH) + set(GTEST_MSVC_SEARCH MD) +endif() + +set(_gtest_libpath_suffixes lib) +if(MSVC) + if(GTEST_MSVC_SEARCH STREQUAL "MD") + list(APPEND _gtest_libpath_suffixes + msvc/gtest-md/Debug + msvc/gtest-md/Release + msvc/x64/Debug + msvc/x64/Release + msvc/2010/gtest-md/Win32-Debug + msvc/2010/gtest-md/Win32-Release + msvc/2010/gtest-md/x64-Debug + msvc/2010/gtest-md/x64-Release + ) + elseif(GTEST_MSVC_SEARCH STREQUAL "MT") + list(APPEND _gtest_libpath_suffixes + msvc/gtest/Debug + msvc/gtest/Release + msvc/x64/Debug + msvc/x64/Release + msvc/2010/gtest/Win32-Debug + msvc/2010/gtest/Win32-Release + msvc/2010/gtest/x64-Debug + msvc/2010/gtest/x64-Release + ) + endif() +endif() + + +find_path(GTEST_INCLUDE_DIR gtest/gtest.h + HINTS + $ENV{GTEST_ROOT}/include + ${GTEST_ROOT}/include +) +mark_as_advanced(GTEST_INCLUDE_DIR) + +if(MSVC AND GTEST_MSVC_SEARCH STREQUAL "MD") + # The provided /MD project files for Google Test add -md suffixes to the + # library names. + __gtest_find_library(GTEST_LIBRARY gtest-md gtest) + __gtest_find_library(GTEST_LIBRARY_DEBUG gtest-mdd gtestd) + __gtest_find_library(GTEST_MAIN_LIBRARY gtest_main-md gtest_main) + __gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_main-mdd gtest_maind) +else() + __gtest_find_library(GTEST_LIBRARY gtest) + __gtest_find_library(GTEST_LIBRARY_DEBUG gtestd) + __gtest_find_library(GTEST_MAIN_LIBRARY gtest_main) + __gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_maind) +endif() + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest DEFAULT_MSG GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY) + +if(GTest_FOUND) + set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIR}) + __gtest_append_debugs(GTEST_LIBRARIES GTEST_LIBRARY) + __gtest_append_debugs(GTEST_MAIN_LIBRARIES GTEST_MAIN_LIBRARY) + + find_package(Threads QUIET) + + if(NOT TARGET GTest::gtest) + __gtest_determine_library_type(GTEST_LIBRARY) + add_library(GTest::gtest ${GTEST_LIBRARY_TYPE} IMPORTED) + if(TARGET Threads::Threads) + set_target_properties(GTest::gtest PROPERTIES + INTERFACE_LINK_LIBRARIES Threads::Threads) + endif() + if(GTEST_LIBRARY_TYPE STREQUAL "SHARED") + set_target_properties(GTest::gtest PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1") + endif() + if(GTEST_INCLUDE_DIRS) + set_target_properties(GTest::gtest PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIRS}") + endif() + __gtest_import_library(GTest::gtest GTEST_LIBRARY "") + __gtest_import_library(GTest::gtest GTEST_LIBRARY "RELEASE") + __gtest_import_library(GTest::gtest GTEST_LIBRARY "DEBUG") + endif() + if(NOT TARGET GTest::gtest_main) + __gtest_determine_library_type(GTEST_MAIN_LIBRARY) + add_library(GTest::gtest_main ${GTEST_MAIN_LIBRARY_TYPE} IMPORTED) + set_target_properties(GTest::gtest_main PROPERTIES + INTERFACE_LINK_LIBRARIES "GTest::gtest") + __gtest_import_library(GTest::gtest_main GTEST_MAIN_LIBRARY "") + __gtest_import_library(GTest::gtest_main GTEST_MAIN_LIBRARY "RELEASE") + __gtest_import_library(GTest::gtest_main GTEST_MAIN_LIBRARY "DEBUG") + endif() + + __gtest_define_backwards_compatible_library_targets() +endif() diff --git a/Sofa/framework/Config/cmake/Modules/FindPackageHandleStandardArgs.cmake b/Sofa/framework/Config/cmake/Modules/FindPackageHandleStandardArgs.cmake index de35e1f0d7d..fbcf7cd88bc 100644 --- a/Sofa/framework/Config/cmake/Modules/FindPackageHandleStandardArgs.cmake +++ b/Sofa/framework/Config/cmake/Modules/FindPackageHandleStandardArgs.cmake @@ -1,300 +1,605 @@ -# FIND_PACKAGE_HANDLE_STANDARD_ARGS( ... ) -# -# This function is intended to be used in FindXXX.cmake modules files. -# It handles the REQUIRED, QUIET and version-related arguments to find_package(). -# It also sets the _FOUND variable. -# The package is considered found if all variables ... listed contain -# valid results, e.g. valid filepaths. -# -# There are two modes of this function. The first argument in both modes is -# the name of the Find-module where it is called (in original casing). -# -# The first simple mode looks like this: -# FIND_PACKAGE_HANDLE_STANDARD_ARGS( (DEFAULT_MSG|"Custom failure message") ... ) -# If the variables to are all valid, then _FOUND -# will be set to TRUE. -# If DEFAULT_MSG is given as second argument, then the function will generate -# itself useful success and error messages. You can also supply a custom error message -# for the failure case. This is not recommended. -# -# The second mode is more powerful and also supports version checking: -# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS ...] -# [VERSION_VAR ] -# [HANDLE_COMPONENTS] -# [CONFIG_MODE] -# [FAIL_MESSAGE "Custom failure message"] ) -# -# As above, if through are all valid, _FOUND -# will be set to TRUE. -# After REQUIRED_VARS the variables which are required for this package are listed. -# Following VERSION_VAR the name of the variable can be specified which holds -# the version of the package which has been found. If this is done, this version -# will be checked against the (potentially) specified required version used -# in the find_package() call. The EXACT keyword is also handled. The default -# messages include information about the required version and the version -# which has been actually found, both if the version is ok or not. -# If the package supports components, use the HANDLE_COMPONENTS option to enable -# handling them. In this case, find_package_handle_standard_args() will report -# which components have been found and which are missing, and the _FOUND -# variable will be set to FALSE if any of the required components (i.e. not the -# ones listed after OPTIONAL_COMPONENTS) are missing. -# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for -# a find_package(... NO_MODULE) call. In this case VERSION_VAR will be set -# to _VERSION and the macro will automatically check whether the -# Config module was found. -# Via FAIL_MESSAGE a custom failure message can be specified, if this is not -# used, the default message will be displayed. -# -# Example for mode 1: -# -# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) -# -# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and -# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE. -# If it is not found and REQUIRED was used, it fails with FATAL_ERROR, -# independent whether QUIET was used or not. -# If it is found, success will be reported, including the content of . -# On repeated Cmake runs, the same message won't be printed again. -# -# Example for mode 2: -# -# FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE -# VERSION_VAR BISON_VERSION) -# In this case, BISON is considered to be found if the variable(s) listed -# after REQUIRED_VAR are all valid, i.e. BISON_EXECUTABLE in this case. -# Also the version of BISON will be checked by using the version contained -# in BISON_VERSION. -# Since no FAIL_MESSAGE is given, the default messages will be printed. -# -# Another example for mode 2: -# -# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) -# FIND_PACKAGE_HANDLE_STANDARD_ARGS(Automoc4 CONFIG_MODE) -# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4 NO_MODULE) -# and adds an additional search directory for automoc4. -# The following FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper -# success/error message. - -#============================================================================= -# Copyright 2007-2009 Kitware, Inc. -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -include_guard(GLOBAL) -include(FindPackageMessage) -include(CMakeParseArguments) +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindPackageHandleStandardArgs +----------------------------- + +This module provides functions intended to be used in :ref:`Find Modules` +implementing :command:`find_package()` calls. + +.. command:: find_package_handle_standard_args + + This command handles the ``REQUIRED``, ``QUIET`` and version-related + arguments of :command:`find_package`. It also sets the + ``_FOUND`` variable. The package is considered found if all + variables listed contain valid results, e.g. valid filepaths. + + There are two signatures: + + .. code-block:: cmake + + find_package_handle_standard_args( + (DEFAULT_MSG|) + ... + ) + + find_package_handle_standard_args( + [FOUND_VAR ] + [REQUIRED_VARS ...] + [VERSION_VAR ] + [HANDLE_VERSION_RANGE] + [HANDLE_COMPONENTS] + [CONFIG_MODE] + [NAME_MISMATCHED] + [REASON_FAILURE_MESSAGE ] + [FAIL_MESSAGE ] + ) + + The ``_FOUND`` variable will be set to ``TRUE`` if all + the variables ``...`` are valid and any optional + constraints are satisfied, and ``FALSE`` otherwise. A success or + failure message may be displayed based on the results and on + whether the ``REQUIRED`` and/or ``QUIET`` option was given to + the :command:`find_package` call. + + The options are: + + ``(DEFAULT_MSG|)`` + In the simple signature this specifies the failure message. + Use ``DEFAULT_MSG`` to ask for a default message to be computed + (recommended). Not valid in the full signature. + + ``FOUND_VAR `` + .. deprecated:: 3.3 + + Specifies either ``_FOUND`` or + ``_FOUND`` as the result variable. This exists only + for compatibility with older versions of CMake and is now ignored. + Result variables of both names are always set for compatibility. + + ``REQUIRED_VARS ...`` + Specify the variables which are required for this package. + These may be named in the generated failure message asking the + user to set the missing variable values. Therefore these should + typically be cache entries such as ``FOO_LIBRARY`` and not output + variables like ``FOO_LIBRARIES``. + + .. versionchanged:: 3.18 + If ``HANDLE_COMPONENTS`` is specified, this option can be omitted. + + ``VERSION_VAR `` + Specify the name of a variable that holds the version of the package + that has been found. This version will be checked against the + (potentially) specified required version given to the + :command:`find_package` call, including its ``EXACT`` option. + The default messages include information about the required + version and the version which has been actually found, both + if the version is ok or not. + + ``HANDLE_VERSION_RANGE`` + .. versionadded:: 3.19 + + Enable handling of a version range, if one is specified. Without this + option, a developer warning will be displayed if a version range is + specified. + + ``HANDLE_COMPONENTS`` + Enable handling of package components. In this case, the command + will report which components have been found and which are missing, + and the ``_FOUND`` variable will be set to ``FALSE`` + if any of the required components (i.e. not the ones listed after + the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are + missing. + + ``CONFIG_MODE`` + Specify that the calling find module is a wrapper around a + call to ``find_package( NO_MODULE)``. This implies + a ``VERSION_VAR`` value of ``_VERSION``. The command + will automatically check whether the package configuration file + was found. + + ``REASON_FAILURE_MESSAGE `` + .. versionadded:: 3.16 + + Specify a custom message of the reason for the failure which will be + appended to the default generated message. + + ``FAIL_MESSAGE `` + Specify a custom failure message instead of using the default + generated message. Not recommended. + + ``NAME_MISMATCHED`` + .. versionadded:: 3.17 + + Indicate that the ```` does not match + ``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a + warning, but it may be intentional for usage of the command for components + of a larger package. + +Example for the simple signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibXml2 DEFAULT_MSG + LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) + +The ``LibXml2`` package is considered to be found if both +``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid. +Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found +and ``REQUIRED`` was used, it fails with a +:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was +used or not. If it is found, success will be reported, including +the content of the first ````. On repeated CMake runs, +the same message will not be printed again. + +.. note:: + + If ```` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the + calling module, a warning that there is a mismatch is given. The + ``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using + the old signature and the ``NAME_MISMATCHED`` argument using the new + signature. To avoid forcing the caller to require newer versions of CMake for + usage, the variable's value will be used if defined when the + ``NAME_MISMATCHED`` argument is not passed for the new signature (but using + both is an error).. + +Example for the full signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibArchive + REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR + VERSION_VAR LibArchive_VERSION) + +In this case, the ``LibArchive`` package is considered to be found if +both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid. +Also the version of ``LibArchive`` will be checked by using the version +contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given, +the default messages will be printed. + +Another example for the full signature: + +.. code-block:: cmake + + find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) + find_package_handle_standard_args(Automoc4 CONFIG_MODE) + +In this case, a ``FindAutmoc4.cmake`` module wraps a call to +``find_package(Automoc4 NO_MODULE)`` and adds an additional search +directory for ``automoc4``. Then the call to +``find_package_handle_standard_args`` produces a proper success/failure +message. + +.. command:: find_package_check_version + + .. versionadded:: 3.19 + + Helper function which can be used to check if a ```` is valid + against version-related arguments of :command:`find_package`. + + .. code-block:: cmake + + find_package_check_version( + [HANDLE_VERSION_RANGE] + [RESULT_MESSAGE_VARIABLE ] + ) + + The ```` will hold a boolean value giving the result of the check. + + The options are: + + ``HANDLE_VERSION_RANGE`` + Enable handling of a version range, if one is specified. Without this + option, a developer warning will be displayed if a version range is + specified. + + ``RESULT_MESSAGE_VARIABLE `` + Specify a variable to get back a message describing the result of the check. + +Example for the usage: + +.. code-block:: cmake + + find_package_check_version(1.2.3 result HANDLE_VERSION_RANGE + RESULT_MESSAGE_VARIABLE reason) + if (result) + message (STATUS "${reason}") + else() + message (FATAL_ERROR "${reason}") + endif() +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake) + + +cmake_policy(PUSH) +# numbers and boolean constants +cmake_policy (SET CMP0012 NEW) +# IN_LIST operator +cmake_policy (SET CMP0057 NEW) + # internal helper macro macro(_FPHSA_FAILURE_MESSAGE _msg) - if (${_NAME}_FIND_REQUIRED) - message(FATAL_ERROR "${_msg}") - else () - if (NOT ${_NAME}_FIND_QUIETLY) - message(STATUS "${_msg}") - endif () + set (__msg "${_msg}") + if (FPHSA_REASON_FAILURE_MESSAGE) + string(APPEND __msg "\n Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n") + endif() + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${__msg}") + else () + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${__msg}") endif () + endif () endmacro() # internal helper macro to generate the failure message when used in CONFIG_MODE: macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) - # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: - if(${_NAME}_CONFIG) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + if(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + else() + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + if(${_NAME}_CONSIDERED_CONFIGS) + set(configsText "") + list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + math(EXPR configsCount "${configsCount} - 1") + foreach(currentConfigIndex RANGE ${configsCount}) + list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + string(APPEND configsText "\n ${filename} (version ${version})") + endforeach() + if (${_NAME}_NOT_FOUND_MESSAGE) + if (FPHSA_REASON_FAILURE_MESSAGE) + string(PREPEND FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}\n ") + else() + set(FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}") + endif() + else() + string(APPEND configsText "\n") + endif() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:${configsText}") + else() - # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. - # List them all in the error message: - if(${_NAME}_CONSIDERED_CONFIGS) - set(configsText "") - list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) - math(EXPR configsCount "${configsCount} - 1") - foreach(currentConfigIndex RANGE ${configsCount}) - list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) - list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) - set(configsText "${configsText} ${filename} (version ${version})\n") - endforeach() - if (${_NAME}_NOT_FOUND_MESSAGE) - set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n") - endif() - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + endif() + endif() +endmacro() + +function(FIND_PACKAGE_CHECK_VERSION version result) + cmake_parse_arguments (PARSE_ARGV 2 FPCV "HANDLE_VERSION_RANGE;NO_AUTHOR_WARNING_VERSION_RANGE" "RESULT_MESSAGE_VARIABLE" "") + + if (FPCV_UNPARSED_ARGUMENTS) + message (FATAL_ERROR "find_package_check_version(): ${FPCV_UNPARSED_ARGUMENTS}: unexpected arguments") + endif() + if ("RESULT_MESSAGE_VARIABLE" IN_LIST FPCV_KEYWORDS_MISSING_VALUES) + message (FATAL_ERROR "find_package_check_version(): RESULT_MESSAGE_VARIABLE expects an argument") + endif() + + set (${result} FALSE PARENT_SCOPE) + if (FPCV_RESULT_MESSAGE_VARIABLE) + unset (${FPCV_RESULT_MESSAGE_VARIABLE} PARENT_SCOPE) + endif() + + if (_CMAKE_FPHSA_PACKAGE_NAME) + set (package "${_CMAKE_FPHSA_PACKAGE_NAME}") + elseif (CMAKE_FIND_PACKAGE_NAME) + set (package "${CMAKE_FIND_PACKAGE_NAME}") + else() + message (FATAL_ERROR "find_package_check_version(): Cannot be used outside a 'Find Module'") + endif() + + if (NOT FPCV_NO_AUTHOR_WARNING_VERSION_RANGE + AND ${package}_FIND_VERSION_RANGE AND NOT FPCV_HANDLE_VERSION_RANGE) + message(AUTHOR_WARNING + "`find_package()` specify a version range but the option " + "HANDLE_VERSION_RANGE` is not passed to `find_package_check_version()`. " + "Only the lower endpoint of the range will be used.") + endif() + + + set (version_ok FALSE) + unset (version_msg) + + if (FPCV_HANDLE_VERSION_RANGE AND ${package}_FIND_VERSION_RANGE) + if ((${package}_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" + AND version VERSION_GREATER_EQUAL ${package}_FIND_VERSION_MIN) + AND ((${package}_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" + AND version VERSION_LESS_EQUAL ${package}_FIND_VERSION_MAX) + OR (${package}_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" + AND version VERSION_LESS ${package}_FIND_VERSION_MAX))) + set (version_ok TRUE) + set(version_msg "(found suitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\")") + else() + set(version_msg "Found unsuitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\"") + endif() + elseif (DEFINED ${package}_FIND_VERSION) + if(${package}_FIND_VERSION_EXACT) # exact version required + # count the dots in the version string + string(REGEX REPLACE "[^.]" "" version_dots "${version}") + # add one dot because there is one dot more than there are components + string(LENGTH "${version_dots}." version_dots) + if (version_dots GREATER ${package}_FIND_VERSION_COUNT) + # Because of the C++ implementation of find_package() ${package}_FIND_VERSION_COUNT + # is at most 4 here. Therefore a simple lookup table is used. + if (${package}_FIND_VERSION_COUNT EQUAL 1) + set(version_regex "[^.]*") + elseif (${package}_FIND_VERSION_COUNT EQUAL 2) + set(version_regex "[^.]*\\.[^.]*") + elseif (${package}_FIND_VERSION_COUNT EQUAL 3) + set(version_regex "[^.]*\\.[^.]*\\.[^.]*") else() - # Simple case: No Config-file was found at all: - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + set(version_regex "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*") endif() + string(REGEX REPLACE "^(${version_regex})\\..*" "\\1" version_head "${version}") + if (NOT ${package}_FIND_VERSION VERSION_EQUAL version_head) + set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"") + else () + set(version_ok TRUE) + set(version_msg "(found suitable exact version \"${_FOUND_VERSION}\")") + endif () + else () + if (NOT ${package}_FIND_VERSION VERSION_EQUAL version) + set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"") + else () + set(version_ok TRUE) + set(version_msg "(found suitable exact version \"${version}\")") + endif () + endif () + else() # minimum version + if (${package}_FIND_VERSION VERSION_GREATER version) + set(version_msg "Found unsuitable version \"${version}\", but required is at least \"${${package}_FIND_VERSION}\"") + else() + set(version_ok TRUE) + set(version_msg "(found suitable version \"${version}\", minimum required is \"${${package}_FIND_VERSION}\")") + endif() endif() -endmacro() + else () + set(version_ok TRUE) + set(version_msg "(found version \"${version}\")") + endif() + + set (${result} ${version_ok} PARENT_SCOPE) + if (FPCV_RESULT_MESSAGE_VARIABLE) + set (${FPCV_RESULT_MESSAGE_VARIABLE} "${version_msg}" PARENT_SCOPE) + endif() +endfunction() function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) - # set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in - # new extended or in the "old" mode: - set(options CONFIG_MODE HANDLE_COMPONENTS) - set(oneValueArgs FAIL_MESSAGE VERSION_VAR) - set(multiValueArgs REQUIRED_VARS) - set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) - list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) - - if(${INDEX} EQUAL -1) - set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) - set(FPHSA_REQUIRED_VARS ${ARGN}) - set(FPHSA_VERSION_VAR) - else() + # Set up the arguments for `cmake_parse_arguments`. + set(options CONFIG_MODE HANDLE_COMPONENTS NAME_MISMATCHED HANDLE_VERSION_RANGE) + set(oneValueArgs FAIL_MESSAGE REASON_FAILURE_MESSAGE VERSION_VAR FOUND_VAR) + set(multiValueArgs REQUIRED_VARS) + + # Check whether we are in 'simple' or 'extended' mode: + set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + unset(FPHSA_NAME_MISMATCHED_override) + if (DEFINED FPHSA_NAME_MISMATCHED) + # If the variable NAME_MISMATCHED variable is set, error if it is passed as + # an argument. The former is for old signatures, the latter is for new + # signatures. + list(FIND ARGN "NAME_MISMATCHED" name_mismatched_idx) + if (NOT name_mismatched_idx EQUAL "-1") + message(FATAL_ERROR + "The `NAME_MISMATCHED` argument may only be specified by the argument or " + "the variable, not both.") + endif () - CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + # But use the variable if it is not an argument to avoid forcing minimum + # CMake version bumps for calling modules. + set(FPHSA_NAME_MISMATCHED_override "${FPHSA_NAME_MISMATCHED}") + endif () - if(FPHSA_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") - endif() + if(${INDEX} EQUAL -1) + set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + set(FPHSA_REQUIRED_VARS ${ARGN}) + set(FPHSA_VERSION_VAR) + else() + cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) - if(NOT FPHSA_FAIL_MESSAGE) - set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") - endif() + if(FPHSA_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") endif() - # now that we collected all arguments, process them - - if("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") - set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + if(NOT FPHSA_FAIL_MESSAGE) + set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") endif() - # In config-mode, we rely on the variable _CONFIG, which is set by find_package() + # In config-mode, we rely on the variable _CONFIG, which is set by find_package() # when it successfully found the config-file, including version checking: if(FPHSA_CONFIG_MODE) - list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) - list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) - set(FPHSA_VERSION_VAR ${_NAME}_VERSION) + list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + set(FPHSA_VERSION_VAR ${_NAME}_VERSION) endif() - if(NOT FPHSA_REQUIRED_VARS) - message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + if(NOT FPHSA_REQUIRED_VARS AND NOT FPHSA_HANDLE_COMPONENTS) + message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") endif() - + endif() + + if (DEFINED FPHSA_NAME_MISMATCHED_override) + set(FPHSA_NAME_MISMATCHED "${FPHSA_NAME_MISMATCHED_override}") + endif () + + if (DEFINED CMAKE_FIND_PACKAGE_NAME + AND NOT FPHSA_NAME_MISMATCHED + AND NOT _NAME STREQUAL CMAKE_FIND_PACKAGE_NAME) + message(AUTHOR_WARNING + "The package name passed to `find_package_handle_standard_args` " + "(${_NAME}) does not match the name of the calling package " + "(${CMAKE_FIND_PACKAGE_NAME}). This can lead to problems in calling " + "code that expects `find_package` result variables (e.g., `_FOUND`) " + "to follow a certain pattern.") + endif () + + if (${_NAME}_FIND_VERSION_RANGE AND NOT FPHSA_HANDLE_VERSION_RANGE) + message(AUTHOR_WARNING + "`find_package()` specify a version range but the module ${_NAME} does " + "not support this capability. Only the lower endpoint of the range " + "will be used.") + endif() + + # to propagate package name to FIND_PACKAGE_CHECK_VERSION + set(_CMAKE_FPHSA_PACKAGE_NAME "${_NAME}") + + # now that we collected all arguments, process them + + if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") + set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + endif() + + if (FPHSA_REQUIRED_VARS) list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + endif() - string(TOUPPER ${_NAME} _NAME_UPPER) - string(TOLOWER ${_NAME} _NAME_LOWER) + string(TOUPPER ${_NAME} _NAME_UPPER) + string(TOLOWER ${_NAME} _NAME_LOWER) - # collect all variables which were not found, so they can be printed, so the - # user knows better what went wrong (#6375) - set(MISSING_VARS "") - set(DETAILS "") + if(FPHSA_FOUND_VAR) + set(_FOUND_VAR_UPPER ${_NAME_UPPER}_FOUND) + set(_FOUND_VAR_MIXED ${_NAME}_FOUND) + if(FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_MIXED OR FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_UPPER) + set(_FOUND_VAR ${FPHSA_FOUND_VAR}) + else() + message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_FOUND_VAR_MIXED}\" and \"${_FOUND_VAR_UPPER}\" are valid names.") + endif() + else() + set(_FOUND_VAR ${_NAME_UPPER}_FOUND) + endif() + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + set(MISSING_VARS "") + set(DETAILS "") + # check if all passed variables are valid + set(FPHSA_FOUND_${_NAME} TRUE) + foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + if(NOT ${_CURRENT_VAR}) + set(FPHSA_FOUND_${_NAME} FALSE) + string(APPEND MISSING_VARS " ${_CURRENT_VAR}") + else() + string(APPEND DETAILS "[${${_CURRENT_VAR}}]") + endif() + endforeach() + if(FPHSA_FOUND_${_NAME}) + set(${_NAME}_FOUND TRUE) set(${_NAME_UPPER}_FOUND TRUE) - # check if all passed variables are valid - foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) - if(NOT ${_CURRENT_VAR}) - set(${_NAME_UPPER}_FOUND FALSE) - set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") - else() - set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") - endif() - endforeach() + else() + set(${_NAME}_FOUND FALSE) + set(${_NAME_UPPER}_FOUND FALSE) + endif() - # component handling - unset(FOUND_COMPONENTS_MSG) - unset(MISSING_COMPONENTS_MSG) + # component handling + unset(FOUND_COMPONENTS_MSG) + unset(MISSING_COMPONENTS_MSG) - if(FPHSA_HANDLE_COMPONENTS) - foreach(comp ${${_NAME}_FIND_COMPONENTS}) - if(${_NAME}_${comp}_FOUND) + if(FPHSA_HANDLE_COMPONENTS) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(${_NAME}_${comp}_FOUND) - if(NOT DEFINED FOUND_COMPONENTS_MSG) - set(FOUND_COMPONENTS_MSG "found components: ") - endif() - set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}") + if(NOT DEFINED FOUND_COMPONENTS_MSG) + set(FOUND_COMPONENTS_MSG "found components:") + endif() + string(APPEND FOUND_COMPONENTS_MSG " ${comp}") - else() + else() - if(NOT DEFINED MISSING_COMPONENTS_MSG) - set(MISSING_COMPONENTS_MSG "missing components: ") - endif() - set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}") + if(NOT DEFINED MISSING_COMPONENTS_MSG) + set(MISSING_COMPONENTS_MSG "missing components:") + endif() + string(APPEND MISSING_COMPONENTS_MSG " ${comp}") - if(${_NAME}_FIND_REQUIRED_${comp}) - set(${_NAME_UPPER}_FOUND FALSE) - set(MISSING_VARS "${MISSING_VARS} ${comp}") - endif() + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + string(APPEND MISSING_VARS " ${comp}") + endif() - endif() - endforeach() - set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") - set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]") + endif() + endforeach() + set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") + string(APPEND DETAILS "[c${COMPONENT_MSG}]") + endif() + + # version handling: + set(VERSION_MSG "") + set(VERSION_OK TRUE) + + # check with DEFINED here as the requested or found version may be "0" + if (DEFINED ${_NAME}_FIND_VERSION) + if(DEFINED ${FPHSA_VERSION_VAR}) + set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}}) + if (FPHSA_HANDLE_VERSION_RANGE) + set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE) + else() + set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE) + endif() + find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG + ${FPCV_HANDLE_VERSION_RANGE}) + else() + # if the package was not found, but a version was given, add that to the output: + if(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + elseif (FPHSA_HANDLE_VERSION_RANGE AND ${_NAME}_FIND_VERSION_RANGE) + set(VERSION_MSG "(Required is version range \"${${_NAME}_FIND_VERSION_RANGE}\")") + else() + set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + endif() + endif() + else () + # Check with DEFINED as the found version may be 0. + if(DEFINED ${FPHSA_VERSION_VAR}) + set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")") endif() + endif () - # version handling: - set(VERSION_MSG "") - set(VERSION_OK TRUE) - set(VERSION ${${FPHSA_VERSION_VAR}} ) - if (${_NAME}_FIND_VERSION) - - if(VERSION) - - if(${_NAME}_FIND_VERSION_EXACT) # exact version required - if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") - set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") - set(VERSION_OK FALSE) - else () - set(VERSION_MSG "(found suitable exact version \"${VERSION}\")") - endif () - - else() # minimum version specified: - if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") - set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") - set(VERSION_OK FALSE) - else () - set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")") - endif () - endif() + if(VERSION_OK) + string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]") + else() + set(${_NAME}_FOUND FALSE) + endif() - else() - # if the package was not found, but a version was given, add that to the output: - if(${_NAME}_FIND_VERSION_EXACT) - set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") - else() - set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") - endif() + # print the result: + if (${_NAME}_FOUND) + FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") + else () + if(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + else() + if(NOT VERSION_OK) + set(RESULT_MSG) + if (_FIRST_REQUIRED_VAR) + string (APPEND RESULT_MSG "found ${${_FIRST_REQUIRED_VAR}}") endif() - else () - if(VERSION) - set(VERSION_MSG "(found version \"${VERSION}\")") + if (COMPONENT_MSG) + if (RESULT_MSG) + string (APPEND RESULT_MSG ", ") + endif() + string (APPEND RESULT_MSG "${FOUND_COMPONENTS_MSG}") endif() - endif () - - if(VERSION_OK) - set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") - else() - set(${_NAME_UPPER}_FOUND FALSE) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (${RESULT_MSG})") + else() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}") + endif() endif() + endif () - # print the result: - if (${_NAME_UPPER}_FOUND) - FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") - else () - - if(FPHSA_CONFIG_MODE) - _FPHSA_HANDLE_FAILURE_CONFIG_MODE() - else() - if(NOT VERSION_OK) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") - else() - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") - endif() - endif() - - endif () + set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) + set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) +endfunction() - set(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE) -endfunction() +cmake_policy(POP) diff --git a/Sofa/framework/Config/cmake/Modules/FindPackageMessage.cmake b/Sofa/framework/Config/cmake/Modules/FindPackageMessage.cmake new file mode 100644 index 00000000000..0628b981691 --- /dev/null +++ b/Sofa/framework/Config/cmake/Modules/FindPackageMessage.cmake @@ -0,0 +1,48 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindPackageMessage +------------------ + +.. code-block:: cmake + + find_package_message( "message for user" "find result details") + +This function is intended to be used in FindXXX.cmake modules files. +It will print a message once for each unique find result. This is +useful for telling the user where a package was found. The first +argument specifies the name (XXX) of the package. The second argument +specifies the message to display. The third argument lists details +about the find result so that if they change the message will be +displayed again. The macro also obeys the QUIET argument to the +find_package command. + +Example: + +.. code-block:: cmake + + if(X11_FOUND) + find_package_message(X11 "Found X11: ${X11_X11_LIB}" + "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") + else() + ... + endif() +#]=======================================================================] + +function(find_package_message pkg msg details) + # Avoid printing a message repeatedly for the same find result. + if(NOT ${pkg}_FIND_QUIETLY) + string(REPLACE "\n" "" details "${details}") + set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) + if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") + # The message has not yet been printed. + message(STATUS "${msg}") + + # Save the find details in the cache to avoid printing the same + # message again. + set("${DETAILS_VAR}" "${details}" + CACHE INTERNAL "Details about finding ${pkg}") + endif() + endif() +endfunction() diff --git a/Sofa/framework/Config/cmake/Modules/FindSOFA.cmake b/Sofa/framework/Config/cmake/Modules/FindSOFA.cmake index 2b0e8092b96..a1a53bfb117 100644 --- a/Sofa/framework/Config/cmake/Modules/FindSOFA.cmake +++ b/Sofa/framework/Config/cmake/Modules/FindSOFA.cmake @@ -146,7 +146,6 @@ list(APPEND SOFA_INCLUDE_OTHER_DIRS ${SOFA_INCLUDE_EXTLIBS}/taucs ${SOFA_INCLUDE_EXTLIBS}/taucs_mt ${SOFA_INCLUDE_EXTLIBS}/taucs-svn - ${SOFA_INCLUDE_EXTLIBS}/tinyxml ${SOFA_INCLUDE_EXTLIBS}/VRPN ${SOFA_INCLUDE_EXTLIBS}/wiiuse ) @@ -330,7 +329,6 @@ list(APPEND SOFA_LIB_EXT_NAME qwt SOFA_LIB_QWT miniFlowVR SOFA_LIB_MINI_FLOWVR newmat SOFA_LIB_NEWMAT - tinyxml SOFA_LIB_TINYXML ${SOFA_LIB_MSVC} ) diff --git a/Sofa/framework/Config/cmake/Modules/Findcxxopts.cmake b/Sofa/framework/Config/cmake/Modules/Findcxxopts.cmake new file mode 100644 index 00000000000..ad3a0b4e7a2 --- /dev/null +++ b/Sofa/framework/Config/cmake/Modules/Findcxxopts.cmake @@ -0,0 +1,78 @@ +# Find the cxxopts headers +# Behavior is to first look for config files, such as the one installed by some package +# managers who provides their own cmake files. +# Most of them and official sources does not provide cmake finders, so if no config files +# were found, this tries to find the library by looking at headers file. +# +# Defines: +# cxxopts_FOUND : True if cxxopts is found +# cxxopts_VERSION : cxxopts version if found +# +# Provides both target cxxopts::cxxopts. + +find_package(cxxopts NO_MODULE QUIET HINTS ${cxxopts_DIR}) + +macro(_cxxopts_check_version) + if(EXISTS "${cxxopts_INCLUDE_DIR}/cxxopts.hpp") + file(READ "${cxxopts_INCLUDE_DIR}/cxxopts.hpp" _cxxopts_version_header) + endif() + + string(REGEX MATCH "define[ \t]+CXXOPTS__VERSION_MAJOR[ \t]+([0-9]+)" _cxxopts_major_version_match "${_cxxopts_version_header}") + set(cxxopts_VERSION_MAJOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+CXXOPTS__VERSION_MINOR[ \t]+([0-9]+)" _cxxopts_minor_version_match "${_cxxopts_version_header}") + set(cxxopts_VERSION_MINOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+CXXOPTS__VERSION_PATCH[ \t]+([0-9]+)" _cxxopts_patch_version_match "${_cxxopts_version_header}") + set(cxxopts_VERSION_PATCH "${CMAKE_MATCH_1}") + + set(cxxopts_VERSION ${cxxopts_VERSION_MAJOR}.${cxxopts_VERSION_MINOR}.${cxxopts_VERSION_PATCH}) + set(cxxopts_VERSION_OK TRUE) + if(${cxxopts_VERSION} VERSION_LESS ${cxxopts_FIND_VERSION}) + set(cxxopts_VERSION_OK FALSE) + message(WARNING "cxxopts version ${cxxopts_VERSION} found in ${cxxopts_INCLUDE_DIR}/cxxopts.hpp, " + "but at least version ${cxxopts_FIND_VERSION} is required") + endif() + if(${cxxopts_FIND_VERSION_EXACT} AND NOT ${cxxopts_VERSION} VERSION_EQUAL ${cxxopts_FIND_VERSION}) + set(cxxopts_VERSION_OK FALSE) + message(WARNING "cxxopts version ${cxxopts_VERSION} found in ${cxxopts_INCLUDE_DIR}, " + "but exact version ${cxxopts_FIND_VERSION_EXACT} is required") + endif() +endmacro() + +if(NOT TARGET cxxopts::cxxopts) + + if(NOT cxxopts_INCLUDE_DIR) + find_path(cxxopts_INCLUDE_DIR + NAMES cxxopts.hpp + PATH_SUFFIXES include + ) + endif() + + if(cxxopts_INCLUDE_DIR) + if(cxxopts_FIND_VERSION) + _cxxopts_check_version() + set(cxxopts_FOUND ${cxxopts_VERSION_OK}) + else() + set(cxxopts_FOUND TRUE) + endif() + endif() + + if(cxxopts_FOUND) + set(cxxopts_INCLUDE_DIRS ${cxxopts_INCLUDE_DIR}) + + if(NOT cxxopts_FIND_QUIETLY) + message(STATUS "Found cxxopts version ${cxxopts_VERSION} from ${cxxopts_INCLUDE_DIR}/cxxopts.hpp)") + endif() + + if(NOT TARGET cxxopts::cxxopts) + add_library(cxxopts::cxxopts INTERFACE IMPORTED) + set_property(TARGET cxxopts::cxxopts PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${cxxopts_INCLUDE_DIR}") + endif() + else() + endif() + + mark_as_advanced(cxxopts_INCLUDE_DIR) +endif() + +if(NOT cxxopts_FOUND AND cxxopts_FIND_REQUIRED) + message(FATAL_ERROR "Cannot find cxxopts") +endif() diff --git a/Sofa/framework/Config/cmake/Modules/Findmetis.cmake b/Sofa/framework/Config/cmake/Modules/Findmetis.cmake new file mode 100644 index 00000000000..6bc48aead4a --- /dev/null +++ b/Sofa/framework/Config/cmake/Modules/Findmetis.cmake @@ -0,0 +1,108 @@ +# Find the metis headers and libraries +# Behavior is to first look for config files, such as the one installed by some package +# managers who provides their own cmake files. +# Most of them and official sources does not provide cmake finders, so if no config files +# were found, this tries to find the library by looking at headers / lib file. +# +# Defines: +# metis_FOUND : True if metis is found +# metis_VERSION : metis version if found +# +# Provides both targets metis and metis::metis. +# Target metis::metis is just an alias to metis. +# We chose to create an alias to provide a unified interface usable whatever the package manager +# was used to provide the library, as some package managers (such vcpkg) defines only short name +# for the target, whereas others (such as conan) defines a fully qualified name. + +find_package(metis NO_MODULE QUIET HINTS ${metis_DIR} NAMES metis Metis) + + +if(NOT metis_FIND_VERSION) + if(NOT metis_FIND_VERSION_MAJOR) + set(metis_FIND_VERSION_MAJOR 0) + endif(NOT metis_FIND_VERSION_MAJOR) + if(NOT metis_FIND_VERSION_MINOR) + set(metis_FIND_VERSION_MINOR 0) + endif(NOT metis_FIND_VERSION_MINOR) + if(NOT metis_FIND_VERSION_PATCH) + set(metis_FIND_VERSION_PATCH 0) + endif(NOT metis_FIND_VERSION_PATCH) + set(metis_FIND_VERSION "${metis_FIND_VERSION_MAJOR}.${metis_FIND_VERSION_MINOR}.${metis_FIND_VERSION_PATCH}") +endif() + +macro(_metis_check_version) + if(EXISTS "${metis_INCLUDE_DIR}/metis.h") + file(READ "${metis_INCLUDE_DIR}/metis.h" _metis_version_header) + endif() + + string(REGEX MATCH "define[ \t]+METIS_VER_MAJOR[ \t]+([0-9]+)" _metis_major_version_match "${_metis_version_header}") + set(metis_VERSION_MAJOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+METIS_VER_MINOR[ \t]+([0-9]+)" _metis_minor_version_match "${_metis_version_header}") + set(metis_VERSION_MINOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+METIS_VER_SUBMINOR[ \t]+([0-9]+)" _metis_patch_version_match "${_metis_version_header}") + set(metis_VERSION_PATCH "${CMAKE_MATCH_1}") + + set(metis_VERSION ${metis_VERSION_MAJOR}.${metis_VERSION_MINOR}.${metis_VERSION_PATCH}) + set(metis_VERSION_OK TRUE) + if(${metis_VERSION} VERSION_LESS ${metis_FIND_VERSION}) + set(metis_VERSION_OK FALSE) + message(WARNING "metis version ${metis_VERSION} found in ${metis_INCLUDE_DIR}, " + "but at least version ${metis_FIND_VERSION} is required") + endif() + if(${metis_FIND_VERSION_EXACT} AND NOT ${metis_VERSION} VERSION_EQUAL ${metis_FIND_VERSION}) + set(metis_VERSION_OK FALSE) + message(WARNING "metis version ${metis_VERSION} found in ${metis_INCLUDE_DIR}, " + "but exact version ${metis_FIND_VERSION} is required") + endif() +endmacro() + +if(TARGET metis) + set(metis_FOUND TRUE) # only metis_FOUND has been set + if(metis_INCLUDE_DIR AND NOT DEFINED metis_VERSION) + _metis_check_version() + set(metis_FOUND ${metis_VERSION_OK}) + endif() + add_library(metis::metis ALIAS metis) +else() + + if(NOT metis_INCLUDE_DIR) + find_path(metis_INCLUDE_DIR + NAMES metis.h + PATH_SUFFIXES include + ) + endif() + + if(NOT metis_LIBRARY) + find_library(metis_LIBRARY + NAMES metis + PATH_SUFFIXES lib + ) + endif() + + if(metis_INCLUDE_DIR AND metis_LIBRARY) + _metis_check_version() + set(metis_FOUND ${metis_VERSION_OK}) + endif() + + if(metis_FOUND) + set(metis_LIBRARIES ${metis_LIBRARY}) + set(metis_INCLUDE_DIRS ${metis_INCLUDE_DIR}) + + if(NOT metis_FIND_QUIETLY) + message(STATUS "Found metis: ${metis_LIBRARIES} (version ${metis_VERSION} from ${metis_INCLUDE_DIR}/metis.h)") + endif() + + if(NOT TARGET metis) + add_library(metis INTERFACE IMPORTED) + set_property(TARGET metis PROPERTY INTERFACE_LINK_LIBRARIES "${metis_LIBRARIES}") + set_property(TARGET metis PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${metis_INCLUDE_DIR}") + endif() + add_library(metis::metis ALIAS metis) + else() + endif() + mark_as_advanced(metis_INCLUDE_DIR metis_LIBRARY) +endif() + +if(NOT metis_FOUND AND metis_FIND_REQUIRED) + message(FATAL_ERROR "Cannot find metis") +endif() diff --git a/Sofa/framework/Config/cmake/Modules/GoogleTest.cmake b/Sofa/framework/Config/cmake/Modules/GoogleTest.cmake new file mode 100644 index 00000000000..2ea9e742502 --- /dev/null +++ b/Sofa/framework/Config/cmake/Modules/GoogleTest.cmake @@ -0,0 +1,559 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +GoogleTest +---------- + +.. versionadded:: 3.9 + +This module defines functions to help use the Google Test infrastructure. Two +mechanisms for adding tests are provided. :command:`gtest_add_tests` has been +around for some time, originally via ``find_package(GTest)``. +:command:`gtest_discover_tests` was introduced in CMake 3.10. + +The (older) :command:`gtest_add_tests` scans source files to identify tests. +This is usually effective, with some caveats, including in cross-compiling +environments, and makes setting additional properties on tests more convenient. +However, its handling of parameterized tests is less comprehensive, and it +requires re-running CMake to detect changes to the list of tests. + +The (newer) :command:`gtest_discover_tests` discovers tests by asking the +compiled test executable to enumerate its tests. This is more robust and +provides better handling of parameterized tests, and does not require CMake +to be re-run when tests change. However, it may not work in a cross-compiling +environment, and setting test properties is less convenient. + +More details can be found in the documentation of the respective functions. + +Both commands are intended to replace use of :command:`add_test` to register +tests, and will create a separate CTest test for each Google Test test case. +Note that this is in some cases less efficient, as common set-up and tear-down +logic cannot be shared by multiple test cases executing in the same instance. +However, it provides more fine-grained pass/fail information to CTest, which is +usually considered as more beneficial. By default, the CTest test name is the +same as the Google Test name (i.e. ``suite.testcase``); see also +``TEST_PREFIX`` and ``TEST_SUFFIX``. + +.. command:: gtest_add_tests + + Automatically add tests with CTest by scanning source code for Google Test + macros:: + + gtest_add_tests(TARGET target + [SOURCES src1...] + [EXTRA_ARGS arg1...] + [WORKING_DIRECTORY dir] + [TEST_PREFIX prefix] + [TEST_SUFFIX suffix] + [SKIP_DEPENDENCY] + [TEST_LIST outVar] + ) + + ``gtest_add_tests`` attempts to identify tests by scanning source files. + Although this is generally effective, it uses only a basic regular expression + match, which can be defeated by atypical test declarations, and is unable to + fully "split" parameterized tests. Additionally, it requires that CMake be + re-run to discover any newly added, removed or renamed tests (by default, + this means that CMake is re-run when any test source file is changed, but see + ``SKIP_DEPENDENCY``). However, it has the advantage of declaring tests at + CMake time, which somewhat simplifies setting additional properties on tests, + and always works in a cross-compiling environment. + + The options are: + + ``TARGET target`` + Specifies the Google Test executable, which must be a known CMake + executable target. CMake will substitute the location of the built + executable when running the test. + + ``SOURCES src1...`` + When provided, only the listed files will be scanned for test cases. If + this option is not given, the :prop_tgt:`SOURCES` property of the + specified ``target`` will be used to obtain the list of sources. + + ``EXTRA_ARGS arg1...`` + Any extra arguments to pass on the command line to each test case. + + ``WORKING_DIRECTORY dir`` + Specifies the directory in which to run the discovered test cases. If this + option is not provided, the current binary directory is used. + + ``TEST_PREFIX prefix`` + Specifies a ``prefix`` to be prepended to the name of each discovered test + case. This can be useful when the same source files are being used in + multiple calls to ``gtest_add_test()`` but with different ``EXTRA_ARGS``. + + ``TEST_SUFFIX suffix`` + Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of + every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may + be specified. + + ``SKIP_DEPENDENCY`` + Normally, the function creates a dependency which will cause CMake to be + re-run if any of the sources being scanned are changed. This is to ensure + that the list of discovered tests is updated. If this behavior is not + desired (as may be the case while actually writing the test cases), this + option can be used to prevent the dependency from being added. + + ``TEST_LIST outVar`` + The variable named by ``outVar`` will be populated in the calling scope + with the list of discovered test cases. This allows the caller to do + things like manipulate test properties of the discovered tests. + + Usage example: + + .. code-block:: cmake + + include(GoogleTest) + add_executable(FooTest FooUnitTest.cxx) + gtest_add_tests(TARGET FooTest + TEST_SUFFIX .noArgs + TEST_LIST noArgsTests + ) + gtest_add_tests(TARGET FooTest + EXTRA_ARGS --someArg someValue + TEST_SUFFIX .withArgs + TEST_LIST withArgsTests + ) + set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10) + set_tests_properties(${withArgsTests} PROPERTIES TIMEOUT 20) + + For backward compatibility, the following form is also supported:: + + gtest_add_tests(exe args files...) + + ``exe`` + The path to the test executable or the name of a CMake target. + ``args`` + A ;-list of extra arguments to be passed to executable. The entire + list must be passed as a single argument. Enclose it in quotes, + or pass ``""`` for no arguments. + ``files...`` + A list of source files to search for tests and test fixtures. + Alternatively, use ``AUTO`` to specify that ``exe`` is the name + of a CMake executable target whose sources should be scanned. + + .. code-block:: cmake + + include(GoogleTest) + set(FooTestArgs --foo 1 --bar 2) + add_executable(FooTest FooUnitTest.cxx) + gtest_add_tests(FooTest "${FooTestArgs}" AUTO) + +.. command:: gtest_discover_tests + + Automatically add tests with CTest by querying the compiled test executable + for available tests:: + + gtest_discover_tests(target + [EXTRA_ARGS arg1...] + [WORKING_DIRECTORY dir] + [TEST_PREFIX prefix] + [TEST_SUFFIX suffix] + [NO_PRETTY_TYPES] [NO_PRETTY_VALUES] + [PROPERTIES name1 value1...] + [TEST_LIST var] + [DISCOVERY_TIMEOUT seconds] + [XML_OUTPUT_DIR dir] + [DISCOVERY_MODE ] + ) + + .. versionadded:: 3.10 + + ``gtest_discover_tests()`` sets up a post-build command on the test executable + that generates the list of tests by parsing the output from running the test + with the ``--gtest_list_tests`` argument. Compared to the source parsing + approach of :command:`gtest_add_tests`, this ensures that the full list of + tests, including instantiations of parameterized tests, is obtained. Since + test discovery occurs at build time, it is not necessary to re-run CMake when + the list of tests changes. + However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set + in order to function in a cross-compiling environment. + + Additionally, setting properties on tests is somewhat less convenient, since + the tests are not available at CMake time. Additional test properties may be + assigned to the set of tests as a whole using the ``PROPERTIES`` option. If + more fine-grained test control is needed, custom content may be provided + through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES` + directory property. The set of discovered tests is made accessible to such a + script via the ``_TESTS`` variable. + + The options are: + + ``target`` + Specifies the Google Test executable, which must be a known CMake + executable target. CMake will substitute the location of the built + executable when running the test. + + ``EXTRA_ARGS arg1...`` + Any extra arguments to pass on the command line to each test case. + + ``WORKING_DIRECTORY dir`` + Specifies the directory in which to run the discovered test cases. If this + option is not provided, the current binary directory is used. + + ``TEST_PREFIX prefix`` + Specifies a ``prefix`` to be prepended to the name of each discovered test + case. This can be useful when the same test executable is being used in + multiple calls to ``gtest_discover_tests()`` but with different + ``EXTRA_ARGS``. + + ``TEST_SUFFIX suffix`` + Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of + every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may + be specified. + + ``NO_PRETTY_TYPES`` + By default, the type index of type-parameterized tests is replaced by the + actual type name in the CTest test name. If this behavior is undesirable + (e.g. because the type names are unwieldy), this option will suppress this + behavior. + + ``NO_PRETTY_VALUES`` + By default, the value index of value-parameterized tests is replaced by the + actual value in the CTest test name. If this behavior is undesirable + (e.g. because the value strings are unwieldy), this option will suppress + this behavior. + + ``PROPERTIES name1 value1...`` + Specifies additional properties to be set on all tests discovered by this + invocation of ``gtest_discover_tests()``. + + ``TEST_LIST var`` + Make the list of tests available in the variable ``var``, rather than the + default ``_TESTS``. This can be useful when the same test + executable is being used in multiple calls to ``gtest_discover_tests()``. + Note that this variable is only available in CTest. + + ``DISCOVERY_TIMEOUT num`` + .. versionadded:: 3.10.3 + + Specifies how long (in seconds) CMake will wait for the test to enumerate + available tests. If the test takes longer than this, discovery (and your + build) will fail. Most test executables will enumerate their tests very + quickly, but under some exceptional circumstances, a test may require a + longer timeout. The default is 5. See also the ``TIMEOUT`` option of + :command:`execute_process`. + + .. note:: + + In CMake versions 3.10.1 and 3.10.2, this option was called ``TIMEOUT``. + This clashed with the ``TIMEOUT`` test property, which is one of the + common properties that would be set with the ``PROPERTIES`` keyword, + usually leading to legal but unintended behavior. The keyword was + changed to ``DISCOVERY_TIMEOUT`` in CMake 3.10.3 to address this + problem. The ambiguous behavior of the ``TIMEOUT`` keyword in 3.10.1 + and 3.10.2 has not been preserved. + + ``XML_OUTPUT_DIR dir`` + .. versionadded:: 3.18 + + If specified, the parameter is passed along with ``--gtest_output=xml:`` + to test executable. The actual file name is the same as the test target, + including prefix and suffix. This should be used instead of + ``EXTRA_ARGS --gtest_output=xml`` to avoid race conditions writing the + XML result output when using parallel test execution. + + ``DISCOVERY_MODE`` + .. versionadded:: 3.18 + + Provides greater control over when ``gtest_discover_tests()`` performs test + discovery. By default, ``POST_BUILD`` sets up a post-build command + to perform test discovery at build time. In certain scenarios, like + cross-compiling, this ``POST_BUILD`` behavior is not desirable. + By contrast, ``PRE_TEST`` delays test discovery until just prior to test + execution. This way test discovery occurs in the target environment + where the test has a better chance at finding appropriate runtime + dependencies. + + ``DISCOVERY_MODE`` defaults to the value of the + ``CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not + passed when calling ``gtest_discover_tests()``. This provides a mechanism + for globally selecting a preferred test discovery behavior without having + to modify each call site. + +#]=======================================================================] + +# Save project's policies +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + +#------------------------------------------------------------------------------ +function(gtest_add_tests) + + if (ARGC LESS 1) + message(FATAL_ERROR "No arguments supplied to gtest_add_tests()") + endif() + + set(options + SKIP_DEPENDENCY + ) + set(oneValueArgs + TARGET + WORKING_DIRECTORY + TEST_PREFIX + TEST_SUFFIX + TEST_LIST + ) + set(multiValueArgs + SOURCES + EXTRA_ARGS + ) + set(allKeywords ${options} ${oneValueArgs} ${multiValueArgs}) + + unset(sources) + if("${ARGV0}" IN_LIST allKeywords) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(autoAddSources YES) + else() + # Non-keyword syntax, convert to keyword form + if (ARGC LESS 3) + message(FATAL_ERROR "gtest_add_tests() without keyword options requires at least 3 arguments") + endif() + set(ARGS_TARGET "${ARGV0}") + set(ARGS_EXTRA_ARGS "${ARGV1}") + if(NOT "${ARGV2}" STREQUAL "AUTO") + set(ARGS_SOURCES "${ARGV}") + list(REMOVE_AT ARGS_SOURCES 0 1) + endif() + endif() + + # The non-keyword syntax allows the first argument to be an arbitrary + # executable rather than a target if source files are also provided. In all + # other cases, both forms require a target. + if(NOT TARGET "${ARGS_TARGET}" AND NOT ARGS_SOURCES) + message(FATAL_ERROR "${ARGS_TARGET} does not define an existing CMake target") + endif() + if(NOT ARGS_WORKING_DIRECTORY) + unset(workDir) + else() + set(workDir WORKING_DIRECTORY "${ARGS_WORKING_DIRECTORY}") + endif() + + if(NOT ARGS_SOURCES) + get_property(ARGS_SOURCES TARGET ${ARGS_TARGET} PROPERTY SOURCES) + endif() + + unset(testList) + + set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") + set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") + + foreach(source IN LISTS ARGS_SOURCES) + if(NOT ARGS_SKIP_DEPENDENCY) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) + endif() + file(READ "${source}" contents) + string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests "${contents}") + foreach(hit ${found_tests}) + string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit}) + + # Parameterized tests have a different signature for the filter + if("x${test_type}" STREQUAL "xTEST_P") + string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") + string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" gtest_test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTYPED_TEST") + string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" gtest_test_name ${hit}) + else() + message(WARNING "Could not parse GTest ${hit} for adding to CTest.") + continue() + endif() + + # Make sure tests disabled in GTest get disabled in CTest + if(gtest_test_name MATCHES "(^|\\.)DISABLED_") + # Add the disabled test if CMake is new enough + # Note that this check is to allow backwards compatibility so this + # module can be copied locally in projects to use with older CMake + # versions + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.8.20170401) + string(REGEX REPLACE + "(^|\\.)DISABLED_" "\\1" + orig_test_name "${gtest_test_name}" + ) + set(ctest_test_name + ${ARGS_TEST_PREFIX}${orig_test_name}${ARGS_TEST_SUFFIX} + ) + add_test(NAME ${ctest_test_name} + ${workDir} + COMMAND ${ARGS_TARGET} + --gtest_also_run_disabled_tests + --gtest_filter=${gtest_test_name} + ${ARGS_EXTRA_ARGS} + ) + set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE) + list(APPEND testList ${ctest_test_name}) + endif() + else() + set(ctest_test_name ${ARGS_TEST_PREFIX}${gtest_test_name}${ARGS_TEST_SUFFIX}) + add_test(NAME ${ctest_test_name} + ${workDir} + COMMAND ${ARGS_TARGET} + --gtest_filter=${gtest_test_name} + ${ARGS_EXTRA_ARGS} + ) + list(APPEND testList ${ctest_test_name}) + endif() + endforeach() + endforeach() + + if(ARGS_TEST_LIST) + set(${ARGS_TEST_LIST} ${testList} PARENT_SCOPE) + endif() + +endfunction() + +#------------------------------------------------------------------------------ + +function(gtest_discover_tests TARGET) + cmake_parse_arguments( + "" + "NO_PRETTY_TYPES;NO_PRETTY_VALUES" + "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;DISCOVERY_TIMEOUT;XML_OUTPUT_DIR;DISCOVERY_MODE" + "EXTRA_ARGS;PROPERTIES" + ${ARGN} + ) + + if(NOT _WORKING_DIRECTORY) + set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + if(NOT _TEST_LIST) + set(_TEST_LIST ${TARGET}_TESTS) + endif() + if(NOT _DISCOVERY_TIMEOUT) + set(_DISCOVERY_TIMEOUT 5) + endif() + if(NOT _DISCOVERY_MODE) + if(NOT CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE) + set(CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE "POST_BUILD") + endif() + set(_DISCOVERY_MODE ${CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE}) + endif() + + get_property( + has_counter + TARGET ${TARGET} + PROPERTY CTEST_DISCOVERED_TEST_COUNTER + SET + ) + if(has_counter) + get_property( + counter + TARGET ${TARGET} + PROPERTY CTEST_DISCOVERED_TEST_COUNTER + ) + math(EXPR counter "${counter} + 1") + else() + set(counter 1) + endif() + set_property( + TARGET ${TARGET} + PROPERTY CTEST_DISCOVERED_TEST_COUNTER + ${counter} + ) + + # Define rule to generate test list for aforementioned test executable + set(ctest_file_base "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}[${counter}]") + set(ctest_include_file "${ctest_file_base}_include.cmake") + set(ctest_tests_file "${ctest_file_base}_tests.cmake") + get_property(crosscompiling_emulator + TARGET ${TARGET} + PROPERTY CROSSCOMPILING_EMULATOR + ) + + if(_DISCOVERY_MODE STREQUAL "POST_BUILD") + add_custom_command( + TARGET ${TARGET} POST_BUILD + BYPRODUCTS "${ctest_tests_file}" + COMMAND "${CMAKE_COMMAND}" + -D "TEST_TARGET=${TARGET}" + -D "TEST_EXECUTABLE=$" + -D "TEST_EXECUTOR=${crosscompiling_emulator}" + -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" + -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" + -D "TEST_PROPERTIES=${_PROPERTIES}" + -D "TEST_PREFIX=${_TEST_PREFIX}" + -D "TEST_SUFFIX=${_TEST_SUFFIX}" + -D "NO_PRETTY_TYPES=${_NO_PRETTY_TYPES}" + -D "NO_PRETTY_VALUES=${_NO_PRETTY_VALUES}" + -D "TEST_LIST=${_TEST_LIST}" + -D "CTEST_FILE=${ctest_tests_file}" + -D "TEST_DISCOVERY_TIMEOUT=${_DISCOVERY_TIMEOUT}" + -D "TEST_XML_OUTPUT_DIR=${_XML_OUTPUT_DIR}" + -P "${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}" + VERBATIM + ) + + file(WRITE "${ctest_include_file}" + "if(EXISTS \"${ctest_tests_file}\")\n" + " include(\"${ctest_tests_file}\")\n" + "else()\n" + " add_test(${TARGET}_NOT_BUILT ${TARGET}_NOT_BUILT)\n" + "endif()\n" + ) + elseif(_DISCOVERY_MODE STREQUAL "PRE_TEST") + + get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL + PROPERTY GENERATOR_IS_MULTI_CONFIG + ) + + if(GENERATOR_IS_MULTI_CONFIG) + set(ctest_tests_file "${ctest_file_base}_tests-$.cmake") + endif() + + string(CONCAT ctest_include_content + "if(EXISTS \"$\")" "\n" + " if(\"$\" IS_NEWER_THAN \"${ctest_tests_file}\")" "\n" + " include(\"${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}\")" "\n" + " gtest_discover_tests_impl(" "\n" + " TEST_EXECUTABLE" " [==[" "$" "]==]" "\n" + " TEST_EXECUTOR" " [==[" "${crosscompiling_emulator}" "]==]" "\n" + " TEST_WORKING_DIR" " [==[" "${_WORKING_DIRECTORY}" "]==]" "\n" + " TEST_EXTRA_ARGS" " [==[" "${_EXTRA_ARGS}" "]==]" "\n" + " TEST_PROPERTIES" " [==[" "${_PROPERTIES}" "]==]" "\n" + " TEST_PREFIX" " [==[" "${_TEST_PREFIX}" "]==]" "\n" + " TEST_SUFFIX" " [==[" "${_TEST_SUFFIX}" "]==]" "\n" + " NO_PRETTY_TYPES" " [==[" "${_NO_PRETTY_TYPES}" "]==]" "\n" + " NO_PRETTY_VALUES" " [==[" "${_NO_PRETTY_VALUES}" "]==]" "\n" + " TEST_LIST" " [==[" "${_TEST_LIST}" "]==]" "\n" + " CTEST_FILE" " [==[" "${ctest_tests_file}" "]==]" "\n" + " TEST_DISCOVERY_TIMEOUT" " [==[" "${_DISCOVERY_TIMEOUT}" "]==]" "\n" + " TEST_XML_OUTPUT_DIR" " [==[" "${_XML_OUTPUT_DIR}" "]==]" "\n" + " )" "\n" + " endif()" "\n" + " include(\"${ctest_tests_file}\")" "\n" + "else()" "\n" + " add_test(${TARGET}_NOT_BUILT ${TARGET}_NOT_BUILT)" "\n" + "endif()" "\n" + ) + + if(GENERATOR_IS_MULTI_CONFIG) + foreach(_config ${CMAKE_CONFIGURATION_TYPES}) + file(GENERATE OUTPUT "${ctest_file_base}_include-${_config}.cmake" CONTENT "${ctest_include_content}" CONDITION $) + endforeach() + file(WRITE "${ctest_include_file}" "include(\"${ctest_file_base}_include-\${CTEST_CONFIGURATION_TYPE}.cmake\")") + else() + file(GENERATE OUTPUT "${ctest_file_base}_include.cmake" CONTENT "${ctest_include_content}") + file(WRITE "${ctest_include_file}" "include(\"${ctest_file_base}_include.cmake\")") + endif() + + else() + message(FATAL_ERROR "Unknown DISCOVERY_MODE: ${_DISCOVERY_MODE}") + endif() + + # Add discovered tests to directory TEST_INCLUDE_FILES + set_property(DIRECTORY + APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" + ) + +endfunction() + +############################################################################### + +set(_GOOGLETEST_DISCOVER_TESTS_SCRIPT + ${CMAKE_CURRENT_LIST_DIR}/GoogleTestAddTests.cmake +) + +# Restore project's policies +cmake_policy(POP) diff --git a/Sofa/framework/Config/cmake/Modules/GoogleTestAddTests.cmake b/Sofa/framework/Config/cmake/Modules/GoogleTestAddTests.cmake new file mode 100644 index 00000000000..0f79c9afc0e --- /dev/null +++ b/Sofa/framework/Config/cmake/Modules/GoogleTestAddTests.cmake @@ -0,0 +1,188 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION ${CMAKE_VERSION}) + +# Overwrite possibly existing ${_CTEST_FILE} with empty file +set(flush_tests_MODE WRITE) + +# Flushes script to ${_CTEST_FILE} +macro(flush_script) + file(${flush_tests_MODE} "${_CTEST_FILE}" "${script}") + set(flush_tests_MODE APPEND) + + set(script "") +endmacro() + +# Flushes tests_buffer to tests +macro(flush_tests_buffer) + list(APPEND tests "${tests_buffer}") + set(tests_buffer "") +endmacro() + +macro(add_command NAME) + set(_args "") + foreach(_arg ${ARGN}) + if(_arg MATCHES "[^-./:a-zA-Z0-9_]") + string(APPEND _args " [==[${_arg}]==]") + else() + string(APPEND _args " ${_arg}") + endif() + endforeach() + string(APPEND script "${NAME}(${_args})\n") + string(LENGTH "${script}" _script_len) + if(${_script_len} GREATER "50000") + flush_script() + endif() + # Unsets macro local variables to prevent leakage outside of this macro. + unset(_args) + unset(_script_len) +endmacro() + +function(gtest_discover_tests_impl) + + cmake_parse_arguments( + "" + "" + "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR" + "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR" + ${ARGN} + ) + + set(prefix "${_TEST_PREFIX}") + set(suffix "${_TEST_SUFFIX}") + set(extra_args ${_TEST_EXTRA_ARGS}) + set(properties ${_TEST_PROPERTIES}) + set(script) + set(suite) + set(tests) + set(tests_buffer) + + # Run test executable to get list of available tests + if(NOT EXISTS "${_TEST_EXECUTABLE}") + message(FATAL_ERROR + "Specified test executable does not exist.\n" + " Path: '${_TEST_EXECUTABLE}'" + ) + endif() + execute_process( + COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests + WORKING_DIRECTORY "${_TEST_WORKING_DIR}" + TIMEOUT ${_TEST_DISCOVERY_TIMEOUT} + OUTPUT_VARIABLE output + RESULT_VARIABLE result + ) + if(NOT ${result} EQUAL 0) + string(REPLACE "\n" "\n " output "${output}") + message(FATAL_ERROR + "Error running test executable.\n" + " Path: '${_TEST_EXECUTABLE}'\n" + " Result: ${result}\n" + " Output:\n" + " ${output}\n" + ) + endif() + + # Preserve semicolon in test-parameters + string(REPLACE [[;]] [[\;]] output "${output}") + string(REPLACE "\n" ";" output "${output}") + + # Parse output + foreach(line ${output}) + # Skip header + if(NOT line MATCHES "gtest_main\\.cc") + # Do we have a module name or a test name? + if(NOT line MATCHES "^ ") + # Module; remove trailing '.' to get just the name... + string(REGEX REPLACE "\\.( *#.*)?" "" suite "${line}") + if(line MATCHES "#" AND NOT _NO_PRETTY_TYPES) + string(REGEX REPLACE "/[0-9]\\.+ +#.*= +" "/" pretty_suite "${line}") + else() + set(pretty_suite "${suite}") + endif() + string(REGEX REPLACE "^DISABLED_" "" pretty_suite "${pretty_suite}") + else() + # Test name; strip spaces and comments to get just the name... + string(REGEX REPLACE " +" "" test "${line}") + if(test MATCHES "#" AND NOT _NO_PRETTY_VALUES) + string(REGEX REPLACE "/[0-9]+#GetParam..=" "/" pretty_test "${test}") + else() + string(REGEX REPLACE "#.*" "" pretty_test "${test}") + endif() + string(REGEX REPLACE "^DISABLED_" "" pretty_test "${pretty_test}") + string(REGEX REPLACE "#.*" "" test "${test}") + if(NOT "${_TEST_XML_OUTPUT_DIR}" STREQUAL "") + set(TEST_XML_OUTPUT_PARAM "--gtest_output=xml:${_TEST_XML_OUTPUT_DIR}/${prefix}${suite}.${test}${suffix}.xml") + else() + unset(TEST_XML_OUTPUT_PARAM) + endif() + + # sanitize test name for further processing downstream + set(testname "${prefix}${pretty_suite}.${pretty_test}${suffix}") + # escape \ + string(REPLACE [[\]] [[\\]] testname "${testname}") + # escape ; + string(REPLACE [[;]] [[\;]] testname "${testname}") + # escape $ + string(REPLACE [[$]] [[\$]] testname "${testname}") + + # ...and add to script + add_command(add_test + "${testname}" + ${_TEST_EXECUTOR} + "${_TEST_EXECUTABLE}" + "--gtest_filter=${suite}.${test}" + "--gtest_also_run_disabled_tests" + ${TEST_XML_OUTPUT_PARAM} + ${extra_args} + ) + if(suite MATCHES "^DISABLED_" OR test MATCHES "^DISABLED_") + add_command(set_tests_properties + "${testname}" + PROPERTIES DISABLED TRUE + ) + endif() + add_command(set_tests_properties + "${testname}" + PROPERTIES + WORKING_DIRECTORY "${_TEST_WORKING_DIR}" + SKIP_REGULAR_EXPRESSION "\\\\[ SKIPPED \\\\]" + ${properties} + ) + list(APPEND tests_buffer "${testname}") + list(LENGTH tests_buffer tests_buffer_length) + if(${tests_buffer_length} GREATER "250") + flush_tests_buffer() + endif() + endif() + endif() + endforeach() + + + # Create a list of all discovered tests, which users may use to e.g. set + # properties on the tests + flush_tests_buffer() + add_command(set ${_TEST_LIST} ${tests}) + + # Write CTest script + flush_script() + +endfunction() + +if(CMAKE_SCRIPT_MODE_FILE) + gtest_discover_tests_impl( + NO_PRETTY_TYPES ${NO_PRETTY_TYPES} + NO_PRETTY_VALUES ${NO_PRETTY_VALUES} + TEST_EXECUTABLE ${TEST_EXECUTABLE} + TEST_EXECUTOR ${TEST_EXECUTOR} + TEST_WORKING_DIR ${TEST_WORKING_DIR} + TEST_PREFIX ${TEST_PREFIX} + TEST_SUFFIX ${TEST_SUFFIX} + TEST_LIST ${TEST_LIST} + CTEST_FILE ${CTEST_FILE} + TEST_DISCOVERY_TIMEOUT ${TEST_DISCOVERY_TIMEOUT} + TEST_XML_OUTPUT_DIR ${TEST_XML_OUTPUT_DIR} + TEST_EXTRA_ARGS ${TEST_EXTRA_ARGS} + TEST_PROPERTIES ${TEST_PROPERTIES} + ) +endif() diff --git a/Sofa/framework/Config/cmake/SofaMacrosConfigure.cmake b/Sofa/framework/Config/cmake/SofaMacrosConfigure.cmake index acb4d2d31b7..0c69342ab15 100644 --- a/Sofa/framework/Config/cmake/SofaMacrosConfigure.cmake +++ b/Sofa/framework/Config/cmake/SofaMacrosConfigure.cmake @@ -187,7 +187,7 @@ endmacro() # function(sofa_add_generic_external directory name type) set(optionArgs FETCH_ONLY) - set(oneValueArgs DEFAULT_VALUE WHEN_TO_SHOW VALUE_IF_HIDDEN) + set(oneValueArgs DEFAULT_VALUE WHEN_TO_SHOW VALUE_IF_HIDDEN GIT_REF) set(multiValueArgs) cmake_parse_arguments("ARG" "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -223,6 +223,11 @@ function(sofa_add_generic_external directory name type) if(${fetch_enabled}) message("Fetching ${type_lower} ${name}") + if("${ARG_GIT_REF}" STREQUAL "") + message(SEND_ERROR "One value argument GIT_REF is required when option EXTERNAL is set. This is the name of the branch or the tag checkouted when cloning the subdirectory.") + return() + endif() + if(NOT EXISTS ${fetched_dir}) file(MAKE_DIRECTORY "${fetched_dir}/") endif() @@ -275,7 +280,7 @@ endfunction() macro(sofa_add_subdirectory type directory name) set(optionArgs EXTERNAL EXPERIMENTAL) - set(oneValueArgs) + set(oneValueArgs GIT_REF) set(multiValueArgs) cmake_parse_arguments("ARG" "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -291,8 +296,9 @@ macro(sofa_add_subdirectory type directory name) set(default_value ON) endif() + if(ARG_EXTERNAL) - sofa_add_generic_external(${directory} ${name} "External ${type_lower}" DEFAULT_VALUE ${default_value} ${ARGN}) + sofa_add_generic_external(${directory} ${name} "External ${type_lower}" GIT_REF ${ARG_GIT_REF} DEFAULT_VALUE ${default_value} ${ARGN}) else() sofa_add_generic(${directory} ${name} ${type_lower} DEFAULT_VALUE ${default_value} ${ARGN}) endif() diff --git a/Sofa/framework/LinearAlgebra/src/sofa/linearalgebra/CompressedRowSparseMatrixGeneric.h b/Sofa/framework/LinearAlgebra/src/sofa/linearalgebra/CompressedRowSparseMatrixGeneric.h index 4647c6f9a1a..31fd33baf5c 100644 --- a/Sofa/framework/LinearAlgebra/src/sofa/linearalgebra/CompressedRowSparseMatrixGeneric.h +++ b/Sofa/framework/LinearAlgebra/src/sofa/linearalgebra/CompressedRowSparseMatrixGeneric.h @@ -263,7 +263,7 @@ public : /// Returns the range of indices from the column indices corresponding to the id-th row Range getRowRange(Index id) const { - if (id + 1 >= rowBegin.size()) + if (id + 1 >= static_cast(rowBegin.size())) { return Range(s_invalidIndex, s_invalidIndex); } diff --git a/Sofa/framework/Simulation/Common/CMakeLists.txt b/Sofa/framework/Simulation/Common/CMakeLists.txt index 230a89799a0..0afa122d21d 100644 --- a/Sofa/framework/Simulation/Common/CMakeLists.txt +++ b/Sofa/framework/Simulation/Common/CMakeLists.txt @@ -39,11 +39,17 @@ set(SOURCE_FILES sofa_find_package(Sofa.Core REQUIRED) sofa_find_package(Sofa.Simulation.Core REQUIRED) -sofa_find_package(TinyXML REQUIRED) +sofa_find_package(TinyXML2 REQUIRED) + +if(UNIX AND NOT APPLE) + sofa_install_libraries(PATHS ${TinyXML2_LIBRARY}) +else() + sofa_install_libraries(TARGETS tinyxml2::tinyxml2) +endif() add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Core Sofa.Simulation.Core) -target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml) # Private because not exported in API +target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml2::tinyxml2) # Private because not exported in API set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Sofa.Framework) # IDE folder diff --git a/Sofa/framework/Simulation/Common/Sofa.Simulation.CommonConfig.cmake.in b/Sofa/framework/Simulation/Common/Sofa.Simulation.CommonConfig.cmake.in index 9913298f590..a458d995a3a 100644 --- a/Sofa/framework/Simulation/Common/Sofa.Simulation.CommonConfig.cmake.in +++ b/Sofa/framework/Simulation/Common/Sofa.Simulation.CommonConfig.cmake.in @@ -5,7 +5,6 @@ find_package(Sofa.Core QUIET REQUIRED) find_package(Sofa.Simulation.Core QUIET REQUIRED) -find_package(TinyXML QUIET REQUIRED) if(NOT TARGET @PROJECT_NAME@) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.cpp b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.cpp index 76d27346985..e94809eedb2 100644 --- a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.cpp +++ b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include /* For loading the scene */ @@ -66,28 +66,21 @@ void recReplaceAttribute(BaseElement* node, const char* attr, const char* value, } -BaseElement* includeNode (TiXmlNode* root,const char *basefilename); -BaseElement* attributeNode(TiXmlNode* root,const char *basefilename); +BaseElement* includeNode (tinyxml2::XMLNode* root,const char *basefilename); +BaseElement* attributeNode(tinyxml2::XMLNode* root,const char *basefilename); void recursiveMergeNode(BaseElement* destNode, BaseElement* srcNode); int numDefault=0; -BaseElement* createNode(TiXmlNode* root, const char *basefilename, bool isRoot = false) +BaseElement* createNode(tinyxml2::XMLNode* root, const char *basefilename, bool isRoot = false) { - //if (!xmlStrcmp(root->name,(const xmlChar*)"text")) return nullptr; - - // TinyXml API changed in 2.6.0, ELEMENT was replaced with TINYXML_ELEMENT - // As the version number is not available as a macro, the most portable was is to - // replace these constants with checks of the return value of ToElement() - // (which is already done here). -- Jeremie A. 02/07/2011 - // if (root->Type() != TiXmlNode::ELEMENT) return nullptr; - TiXmlElement* element = root->ToElement(); + tinyxml2::XMLElement* element = root->ToElement(); if (!element) return nullptr; if (!element->Value() || !element->Value()[0]) { - msg_error_withfile("XMLParser", basefilename, element->Row()) << "Invalid element : " << *element ; + msg_error_withfile("XMLParser", basefilename, element->GetLineNum()) << "Invalid element." ; return nullptr; } @@ -141,7 +134,7 @@ BaseElement* createNode(TiXmlNode* root, const char *basefilename, bool isRoot = { // we found a replacement xml element->SetAttribute("href",filename.c_str()); - element->RemoveAttribute("type"); + element->DeleteAttribute("type"); return includeNode(root, basefilename); } } @@ -149,7 +142,7 @@ BaseElement* createNode(TiXmlNode* root, const char *basefilename, bool isRoot = BaseElement* node = BaseElement::Create(classType,name,type); if (node==nullptr) { - msg_info_withfile("XMLParser", basefilename, element->Row()) << "Node "<Value()<<" name "<GetLineNum()) << "Node "<Value()<<" name "<setBaseFile( basefilename ); node->setSrcFile(basefilename); - node->setSrcLine(element->Row()) ; + node->setSrcLine(element->GetLineNum()) ; // List attributes - for (TiXmlAttribute* attr=element->FirstAttribute(); attr ; attr = attr->Next()) + for (const tinyxml2::XMLAttribute* attr=element->FirstAttribute(); attr ; attr = attr->Next()) { if (attr->Value()==nullptr) continue; if (!(strcmp(attr->Name(), "name"))) continue; @@ -168,7 +161,7 @@ BaseElement* createNode(TiXmlNode* root, const char *basefilename, bool isRoot = node->setAttribute(attr->Name(), std::string(attr->Value())); } - for (TiXmlNode* child = root->FirstChild() ; child != nullptr; child = child->NextSibling()) + for (tinyxml2::XMLNode* child = root->FirstChild() ; child != nullptr; child = child->NextSibling()) { BaseElement* childnode = createNode(child, basefilename); if (childnode != nullptr) @@ -180,7 +173,7 @@ BaseElement* createNode(TiXmlNode* root, const char *basefilename, bool isRoot = { if (!node->addChild(childnode)) { - msg_info_withfile("XMLParser", basefilename, element->Row()) << "Node "<getClass()<<" name "<getName()<<" type "<getType() + msg_info_withfile("XMLParser", basefilename, element->GetLineNum()) << "Node "<getClass()<<" name "<getName()<<" type "<getType() <<" cannot be a child of node "<getClass()<<" name "<getName()<<" type "<getType() ; delete childnode; } @@ -205,9 +198,9 @@ BaseElement* createNode(TiXmlNode* root, const char *basefilename, bool isRoot = return node; } -BaseElement* processXMLLoading(const char *filename, const TiXmlDocument &doc, bool fromMem) +BaseElement* processXMLLoading(const char *filename, const tinyxml2::XMLDocument &doc, bool fromMem) { - const TiXmlElement* hRoot = doc.RootElement(); + const tinyxml2::XMLElement* hRoot = doc.RootElement(); if (hRoot == nullptr) { @@ -220,7 +213,7 @@ BaseElement* processXMLLoading(const char *filename, const TiXmlDocument &doc, b basefilename = filename ; else basefilename = sofa::helper::system::SetDirectory::GetRelativeFromDir(filename,sofa::helper::system::SetDirectory::GetCurrentDir().c_str()); - BaseElement* graph = createNode((TiXmlElement*)hRoot, basefilename.c_str(), true); + BaseElement* graph = createNode((tinyxml2::XMLElement*)hRoot, basefilename.c_str(), true); if (graph == nullptr) { @@ -233,14 +226,14 @@ BaseElement* processXMLLoading(const char *filename, const TiXmlDocument &doc, b BaseElement* loadFromMemory(const char* filename, const char* data) { - TiXmlDocument doc; // the resulting document tree + tinyxml2::XMLDocument doc; // the resulting document tree //xmlSubstituteEntitiesDefault(1); doc.Parse(data); if (doc.Error()) { - msg_error("XMLParser") << "Failed to open " << filename << "\n" << doc.ErrorDesc() << " at line " << doc.ErrorRow() << " row " << doc.ErrorCol(); + msg_error("XMLParser") << "Failed to open " << filename << "\n" << doc.ErrorStr() << " at line " << doc.ErrorLineNum(); return nullptr; } return processXMLLoading(filename, doc, true); @@ -256,13 +249,13 @@ BaseElement* loadFromFile(const char *filename) // this initialize the library and check potential ABI mismatches // between the version it was compiled for and the actual shared // library used. - TiXmlDocument* doc = new TiXmlDocument; // the resulting document tree + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument; // the resulting document tree // xmlSubstituteEntitiesDefault(1); - if (!(doc->LoadFile(filename))) + if (doc->LoadFile(filename) != tinyxml2::XML_SUCCESS) { - msg_error("XMLParser") << "Failed to open " << filename << "\n" << doc->ErrorDesc() << " at line " << doc->ErrorRow() << " row " << doc->ErrorCol() ; + msg_error("XMLParser") << "Failed to open " << filename << "\n" << doc->ErrorStr() << " at line " << doc->ErrorLineNum(); delete doc; return nullptr; } @@ -277,9 +270,9 @@ BaseElement* loadFromFile(const char *filename) } -BaseElement* includeNode(TiXmlNode* root,const char *basefilename) +BaseElement* includeNode(tinyxml2::XMLNode* root,const char *basefilename) { - TiXmlElement* element = root->ToElement(); + tinyxml2::XMLElement* element = root->ToElement(); if (!element) return nullptr; std::string filename; @@ -294,13 +287,13 @@ BaseElement* includeNode(TiXmlNode* root,const char *basefilename) return nullptr; } sofa::helper::system::DataRepository.findFileFromFile(filename, basefilename); - TiXmlDocument doc; // the resulting document tree - if (!doc.LoadFile(filename.c_str())) + tinyxml2::XMLDocument doc; // the resulting document tree + if (doc.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS) { msg_error("XMLParser") << "Failed to parse " << filename << "\n"; return nullptr; } - TiXmlElement* newroot = doc.RootElement(); + tinyxml2::XMLElement* newroot = doc.RootElement(); if (newroot == nullptr) { @@ -315,7 +308,7 @@ BaseElement* includeNode(TiXmlNode* root,const char *basefilename) if (result->getName() == "_Group_") result->setIncludeNodeType(INCLUDE_NODE_GROUP); if (result->getName() == "_Merge_") result->setIncludeNodeType(INCLUDE_NODE_MERGE); // Copy attributes - for (TiXmlAttribute* attr=element->FirstAttribute(); attr != nullptr ; attr = attr->Next()) + for (const tinyxml2::XMLAttribute* attr=element->FirstAttribute(); attr != nullptr ; attr = attr->Next()) { if (attr->Value()==nullptr) continue; if (!(strcmp(attr->Name(), "href"))) continue; diff --git a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.h b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.h index da301264691..74111af1e2a 100644 --- a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.h +++ b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/xml/XML.h @@ -23,12 +23,17 @@ #include #include -class TiXmlDocument; +namespace tinyxml2 +{ + + class XMLDocument; + +} // namespace tinyxml2 namespace sofa::simulation::xml { -SOFA_SIMULATION_COMMON_API BaseElement* processXMLLoading(const char *filename, const TiXmlDocument &doc, bool fromMem=false); +SOFA_SIMULATION_COMMON_API BaseElement* processXMLLoading(const char *filename, const tinyxml2::XMLDocument &doc, bool fromMem=false); SOFA_SIMULATION_COMMON_API BaseElement* loadFromFile(const char *filename); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/DefaultAnimationLoop.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/DefaultAnimationLoop.cpp index 0bf53d191c8..5d54680785b 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/DefaultAnimationLoop.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/DefaultAnimationLoop.cpp @@ -71,6 +71,7 @@ DefaultAnimationLoop::DefaultAnimationLoop(simulation::Node* _m_node) : Inherit() , d_parallelODESolving(initData(&d_parallelODESolving, false, "parallelODESolving", "If true, solves all the ODEs in parallel")) { + SOFA_UNUSED(_m_node); this->addUpdateCallback("parallelODESolving", {&d_parallelODESolving}, [this](const core::DataTracker& tracker) -> sofa::core::objectmodel::ComponentState { diff --git a/Sofa/framework/Testing/CMakeLists.txt b/Sofa/framework/Testing/CMakeLists.txt index 2235ab8af07..ae545ed3093 100644 --- a/Sofa/framework/Testing/CMakeLists.txt +++ b/Sofa/framework/Testing/CMakeLists.txt @@ -4,10 +4,57 @@ project(Sofa.Testing LANGUAGES CXX) # Enable testing features of cmake, like the add_test() command. enable_testing() -# add gtest library -# set(gtest_disable_pthreads ON CACHE INTERNAL "") -add_subdirectory(extlibs/gtest) -# add custom gtest main +# add googletest library +# set(googletest_disable_pthreads ON CACHE INTERNAL "") +find_package(GTest QUIET) +if(NOT GTest_FOUND AND SOFA_ALLOW_FETCH_DEPENDENCIES) + message("${PROJECT_NAME}: DEPENDENCY googletest NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is ON, fetching googletest...") + + include(FetchContent) + FetchContent_Declare(googletest + GIT_REPOSITORY https://github.com/google/googletest + GIT_TAG v1.14.0 + ) + + FetchContent_GetProperties(googletest) + if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + + set(BUILD_GMOCK OFF CACHE INTERNAL "") + set(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE) + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) # rely on SOFA macros + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + set(gtest_disable_pthreads OFF CACHE BOOL "" FORCE) + + message("${PROJECT_NAME}: adding subdirectory ${googletest_SOURCE_DIR}") + + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + + target_compile_options(gtest_main PRIVATE "-DGTEST_LINKED_AS_SHARED_LIBRARY=0") + target_compile_options(gtest PRIVATE "-DGTEST_CREATE_SHARED_LIBRARY=1") + + install(DIRECTORY ${googletest_SOURCE_DIR}/googletest/include/gtest DESTINATION include/extlibs/GTest/ COMPONENT headers) + target_include_directories(gtest PUBLIC "$") + + include(SofaMacros) + sofa_create_package_with_targets( + PACKAGE_NAME GTest + PACKAGE_VERSION 1.14.0 + TARGETS gtest AUTO_SET_TARGET_PROPERTIES + INCLUDE_SOURCE_DIR "include" + INCLUDE_INSTALL_DIR "extlibs/GTest" + ) + + set_target_properties(gtest PROPERTIES FOLDER Testing) + set_target_properties(gtest_main PROPERTIES FOLDER Testing) + endif() +elseif (NOT GTest_FOUND) + message(FATAL_ERROR "${PROJECT_NAME}: DEPENDENCY googletest NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is OFF and thus cannot be fetched. Install googletest, or enable SOFA_ALLOW_FETCH_DEPENDENCIES to fix this issue.") +endif() + + + +# add custom googletest main add_subdirectory(SofaGTestMain) set(SOFATESTINGSRC_ROOT "src/sofa/testing") @@ -38,7 +85,9 @@ sofa_find_package(Sofa.Core REQUIRED) sofa_find_package(Sofa.Simulation.Graph REQUIRED) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Helper Sofa.DefaultType Sofa.Core Sofa.Simulation.Graph gtest SofaGTestMain ) +target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Helper Sofa.DefaultType Sofa.Core Sofa.Simulation.Graph GTest::gtest SofaGTestMain ) +target_compile_options(${PROJECT_NAME} PUBLIC "-DGTEST_LINKED_AS_SHARED_LIBRARY=1") + set(SOFA_TESTING_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources") set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Sofa.Framework) # IDE folder diff --git a/Sofa/framework/Testing/extlibs/gtest/GTestConfig.cmake.in b/Sofa/framework/Testing/GTestConfig.cmake.in similarity index 100% rename from Sofa/framework/Testing/extlibs/gtest/GTestConfig.cmake.in rename to Sofa/framework/Testing/GTestConfig.cmake.in diff --git a/Sofa/framework/Testing/Sofa.TestingConfig.cmake.in b/Sofa/framework/Testing/Sofa.TestingConfig.cmake.in index 78d7ebdeeb5..b5ee077871c 100644 --- a/Sofa/framework/Testing/Sofa.TestingConfig.cmake.in +++ b/Sofa/framework/Testing/Sofa.TestingConfig.cmake.in @@ -4,7 +4,7 @@ @PACKAGE_INIT@ find_package(Threads QUIET REQUIRED) -find_package(GTest CONFIG QUIET REQUIRED) +find_package(GTest QUIET REQUIRED) find_package(SofaGTestMain QUIET REQUIRED) find_package(Sofa.Helper QUIET REQUIRED) find_package(Sofa.DefaultType QUIET REQUIRED) diff --git a/Sofa/framework/Testing/SofaGTestMain/CMakeLists.txt b/Sofa/framework/Testing/SofaGTestMain/CMakeLists.txt index 713c7c42ff2..55bca42d69d 100644 --- a/Sofa/framework/Testing/SofaGTestMain/CMakeLists.txt +++ b/Sofa/framework/Testing/SofaGTestMain/CMakeLists.txt @@ -3,11 +3,11 @@ project(SofaGTestMain) ## Dependencies sofa_find_package(Sofa.Simulation.Graph REQUIRED) -sofa_find_package(GTest CONFIG REQUIRED) +sofa_find_package(GTest REQUIRED) add_library(${PROJECT_NAME} SofaGTestMain.cpp) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Helper Sofa.Simulation.Graph) -target_link_libraries(${PROJECT_NAME} PUBLIC gtest) +target_link_libraries(${PROJECT_NAME} PUBLIC GTest::gtest) ## Install rules for the library; CMake package configurations files sofa_create_package_with_targets( diff --git a/Sofa/framework/Testing/SofaGTestMain/SofaGTestMainConfig.cmake.in b/Sofa/framework/Testing/SofaGTestMain/SofaGTestMainConfig.cmake.in index ec53c2e5ab3..980a99eaf8d 100644 --- a/Sofa/framework/Testing/SofaGTestMain/SofaGTestMainConfig.cmake.in +++ b/Sofa/framework/Testing/SofaGTestMain/SofaGTestMainConfig.cmake.in @@ -3,7 +3,7 @@ @PACKAGE_INIT@ find_package(Sofa.Simulation.Graph QUIET REQUIRED) -find_package(GTest CONFIG QUIET REQUIRED) +find_package(GTest QUIET REQUIRED) if(NOT TARGET SofaGTestMain) include("${CMAKE_CURRENT_LIST_DIR}/SofaGTestMainTargets.cmake") diff --git a/Sofa/framework/Testing/extlibs/gtest/CHANGES b/Sofa/framework/Testing/extlibs/gtest/CHANGES deleted file mode 100644 index 05521324212..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/CHANGES +++ /dev/null @@ -1,157 +0,0 @@ -Changes for 1.7.0: - -* New feature: death tests are supported on OpenBSD and in iOS - simulator now. -* New feature: Google Test now implements a protocol to allow - a test runner to detect that a test program has exited - prematurely and report it as a failure (before it would be - falsely reported as a success if the exit code is 0). -* New feature: Test::RecordProperty() can now be used outside of the - lifespan of a test method, in which case it will be attributed to - the current test case or the test program in the XML report. -* New feature (potentially breaking): --gtest_list_tests now prints - the type parameters and value parameters for each test. -* Improvement: char pointers and char arrays are now escaped properly - in failure messages. -* Improvement: failure summary in XML reports now includes file and - line information. -* Improvement: the XML element now has a timestamp attribute. -* Improvement: When --gtest_filter is specified, XML report now doesn't - contain information about tests that are filtered out. -* Fixed the bug where long --gtest_filter flag values are truncated in - death tests. -* Potentially breaking change: RUN_ALL_TESTS() is now implemented as a - function instead of a macro in order to work better with Clang. -* Compatibility fixes with C++ 11 and various platforms. -* Bug/warning fixes. - -Changes for 1.6.0: - -* New feature: ADD_FAILURE_AT() for reporting a test failure at the - given source location -- useful for writing testing utilities. -* New feature: the universal value printer is moved from Google Mock - to Google Test. -* New feature: type parameters and value parameters are reported in - the XML report now. -* A gtest_disable_pthreads CMake option. -* Colored output works in GNU Screen sessions now. -* Parameters of value-parameterized tests are now printed in the - textual output. -* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are - now correctly reported. -* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to - ostream. -* More complete handling of exceptions. -* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter - name is already used by another library. -* --gtest_catch_exceptions is now true by default, allowing a test - program to continue after an exception is thrown. -* Value-parameterized test fixtures can now derive from Test and - WithParamInterface separately, easing conversion of legacy tests. -* Death test messages are clearly marked to make them more - distinguishable from other messages. -* Compatibility fixes for Android, Google Native Client, MinGW, HP UX, - PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear), - IBM XL C++ (Visual Age C++), and C++0x. -* Bug fixes and implementation clean-ups. -* Potentially incompatible changes: disables the harmful 'make install' - command in autotools. - -Changes for 1.5.0: - - * New feature: assertions can be safely called in multiple threads - where the pthreads library is available. - * New feature: predicates used inside EXPECT_TRUE() and friends - can now generate custom failure messages. - * New feature: Google Test can now be compiled as a DLL. - * New feature: fused source files are included. - * New feature: prints help when encountering unrecognized Google Test flags. - * Experimental feature: CMake build script (requires CMake 2.6.4+). - * Experimental feature: the Pump script for meta programming. - * double values streamed to an assertion are printed with enough precision - to differentiate any two different values. - * Google Test now works on Solaris and AIX. - * Build and test script improvements. - * Bug fixes and implementation clean-ups. - - Potentially breaking changes: - - * Stopped supporting VC++ 7.1 with exceptions disabled. - * Dropped support for 'make install'. - -Changes for 1.4.0: - - * New feature: the event listener API - * New feature: test shuffling - * New feature: the XML report format is closer to junitreport and can - be parsed by Hudson now. - * New feature: when a test runs under Visual Studio, its failures are - integrated in the IDE. - * New feature: /MD(d) versions of VC++ projects. - * New feature: elapsed time for the tests is printed by default. - * New feature: comes with a TR1 tuple implementation such that Boost - is no longer needed for Combine(). - * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends. - * New feature: the Xcode project can now produce static gtest - libraries in addition to a framework. - * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile, - Symbian, gcc, and C++Builder. - * Bug fixes and implementation clean-ups. - -Changes for 1.3.0: - - * New feature: death tests on Windows, Cygwin, and Mac. - * New feature: ability to use Google Test assertions in other testing - frameworks. - * New feature: ability to run disabled test via - --gtest_also_run_disabled_tests. - * New feature: the --help flag for printing the usage. - * New feature: access to Google Test flag values in user code. - * New feature: a script that packs Google Test into one .h and one - .cc file for easy deployment. - * New feature: support for distributing test functions to multiple - machines (requires support from the test runner). - * Bug fixes and implementation clean-ups. - -Changes for 1.2.1: - - * Compatibility fixes for Linux IA-64 and IBM z/OS. - * Added support for using Boost and other TR1 implementations. - * Changes to the build scripts to support upcoming release of Google C++ - Mocking Framework. - * Added Makefile to the distribution package. - * Improved build instructions in README. - -Changes for 1.2.0: - - * New feature: value-parameterized tests. - * New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS) - macros. - * Changed the XML report format to match JUnit/Ant's. - * Added tests to the Xcode project. - * Added scons/SConscript for building with SCons. - * Added src/gtest-all.cc for building Google Test from a single file. - * Fixed compatibility with Solaris and z/OS. - * Enabled running Python tests on systems with python 2.3 installed, - e.g. Mac OS X 10.4. - * Bug fixes. - -Changes for 1.1.0: - - * New feature: type-parameterized tests. - * New feature: exception assertions. - * New feature: printing elapsed time of tests. - * Improved the robustness of death tests. - * Added an Xcode project and samples. - * Adjusted the output format on Windows to be understandable by Visual Studio. - * Minor bug fixes. - -Changes for 1.0.1: - - * Added project files for Visual Studio 7.1. - * Fixed issues with compiling on Mac OS X. - * Fixed issues with compiling on Cygwin. - -Changes for 1.0.0: - - * Initial Open Source release of Google Test diff --git a/Sofa/framework/Testing/extlibs/gtest/CMakeLists.txt b/Sofa/framework/Testing/extlibs/gtest/CMakeLists.txt deleted file mode 100644 index 0b807aa920f..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/CMakeLists.txt +++ /dev/null @@ -1,94 +0,0 @@ -cmake_minimum_required(VERSION 3.12) -project(gtest VERSION 2.6.2 LANGUAGES CXX C) - -## Options -# When other libraries are using a shared version of runtime libraries, -# Google Test also has to use one. -option(gtest_force_shared_crt "Use shared (DLL) run-time lib even when Google Test is built as static lib." ON) -mark_as_advanced(gtest_force_shared_crt) - -option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF) -mark_as_advanced(gtest_disable_pthreads) - -## Config -# Define helper functions and macros used by Google Test. -include(cmake/internal_utils.cmake) -config_compiler_and_linker() # Defined in internal_utils.cmake. - -# The code must be relocatable if we want to link a shared library against it. -if(NOT WIN32) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xGNU" OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang") - add_compile_options(-fPIC) - endif() -endif() - -set(HEADER_FILES - include/gtest/gtest.h - include/gtest/gtest-death-test.h - include/gtest/gtest-matchers.h - include/gtest/gtest-message.h - include/gtest/gtest-param-test.h - include/gtest/gtest_pred_impl.h - include/gtest/gtest-printers.h - include/gtest/gtest_prod.h - include/gtest/gtest-spi.h - include/gtest/gtest-test-part.h - include/gtest/gtest-typed-test.h - include/gtest/internal/gtest-death-test-internal.h - include/gtest/internal/gtest-filepath.h - include/gtest/internal/gtest-internal.h - include/gtest/internal/gtest-linked_ptr.h - include/gtest/internal/gtest-param-util-generated.h - include/gtest/internal/gtest-param-util.h - include/gtest/internal/gtest-port-arch.h - include/gtest/internal/gtest-port.h - include/gtest/internal/gtest-string.h - include/gtest/internal/gtest-tuple.h - include/gtest/internal/gtest-type-util.h - include/gtest/internal/custom/gtest-port.h - include/gtest/internal/custom/gtest-printers.h - include/gtest/internal/custom/gtest.h -) - -set(SOURCE_FILES - src/gtest.cc - src/gtest-death-test.cc - src/gtest-filepath.cc - src/gtest-port.cc - src/gtest-printers.cc - src/gtest-test-part.cc - src/gtest-typed-test.cc - ) - -# make the gtest library as a shared library. -cxx_shared_library(gtest "${cxx_strict}" ${SOURCE_FILES} ${HEADER_FILES}) - -target_compile_options(gtest INTERFACE "-DGTEST_LINKED_AS_SHARED_LIBRARY=1") -target_compile_options(gtest PRIVATE "-DGTEST_CREATE_SHARED_LIBRARY=1") - -# In Visual Studio 2012 (VC11) _VARIADIC_MAX is by default defined as -# 5, which is not enough for gtest. So we ensure that everything that -# links against gtest defines _VARIADIC_MAX=10 -if(MSVC) - target_compile_options(gtest PUBLIC "-D_VARIADIC_MAX=10") -else() - target_compile_options(gtest PRIVATE "-Wno-missing-field-initializers") -endif() - -target_include_directories(gtest - SYSTEM PUBLIC "$" - PRIVATE "$" # for src/gtest.cc -> src/gtest-internal-inl.h - ) - -target_compile_features(gtest PUBLIC cxx_std_17) - -include(SofaMacros) -sofa_create_package_with_targets( - PACKAGE_NAME GTest - PACKAGE_VERSION ${PROJECT_VERSION} - TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES - INCLUDE_SOURCE_DIR "include" - INCLUDE_INSTALL_DIR "extlibs/GTest" - ) - -set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Testing) diff --git a/Sofa/framework/Testing/extlibs/gtest/CONTRIBUTORS b/Sofa/framework/Testing/extlibs/gtest/CONTRIBUTORS deleted file mode 100644 index feae2fc0441..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/CONTRIBUTORS +++ /dev/null @@ -1,37 +0,0 @@ -# This file contains a list of people who've made non-trivial -# contribution to the Google C++ Testing Framework project. People -# who commit code to the project are encouraged to add their names -# here. Please keep the list sorted by first names. - -Ajay Joshi -Balázs Dán -Bharat Mediratta -Chandler Carruth -Chris Prince -Chris Taylor -Dan Egnor -Eric Roman -Hady Zalek -Jeffrey Yasskin -Jói Sigurðsson -Keir Mierle -Keith Ray -Kenton Varda -Manuel Klimek -Markus Heule -Mika Raento -Miklós Fazekas -Pasi Valminen -Patrick Hanna -Patrick Riley -Peter Kaminski -Preston Jackson -Rainer Klaffenboeck -Russ Cox -Russ Rufer -Sean Mcafee -Sigurður Ásgeirsson -Tracy Bialik -Vadim Berman -Vlad Losev -Zhanyong Wan diff --git a/Sofa/framework/Testing/extlibs/gtest/LICENSE b/Sofa/framework/Testing/extlibs/gtest/LICENSE deleted file mode 100644 index 1941a11f8ce..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2008, Google Inc. -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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER 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. diff --git a/Sofa/framework/Testing/extlibs/gtest/README b/Sofa/framework/Testing/extlibs/gtest/README deleted file mode 100644 index 26f35a84794..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/README +++ /dev/null @@ -1,435 +0,0 @@ -Google C++ Testing Framework -============================ - -http://code.google.com/p/googletest/ - -Overview --------- - -Google's framework for writing C++ tests on a variety of platforms -(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the -xUnit architecture. Supports automatic test discovery, a rich set of -assertions, user-defined assertions, death tests, fatal and non-fatal -failures, various options for running the tests, and XML test report -generation. - -Please see the project page above for more information as well as the -mailing list for questions, discussions, and development. There is -also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please -join us! - -Requirements for End Users --------------------------- - -Google Test is designed to have fairly minimal requirements to build -and use with your projects, but there are some. Currently, we support -Linux, Windows, Mac OS X, and Cygwin. We will also make our best -effort to support other platforms (e.g. Solaris, AIX, and z/OS). -However, since core members of the Google Test project have no access -to these platforms, Google Test may have outstanding issues there. If -you notice any problems on your platform, please notify -googletestframework@googlegroups.com. Patches for fixing them are -even more welcome! - -### Linux Requirements ### - -These are the base requirements to build and use Google Test from a source -package (as described below): - * GNU-compatible Make or gmake - * POSIX-standard shell - * POSIX(-2) Regular Expressions (regex.h) - * A C++98-standard-compliant compiler - -### Windows Requirements ### - - * Microsoft Visual C++ 7.1 or newer - -### Cygwin Requirements ### - - * Cygwin 1.5.25-14 or newer - -### Mac OS X Requirements ### - - * Mac OS X 10.4 Tiger or newer - * Developer Tools Installed - -Also, you'll need CMake 2.6.4 or higher if you want to build the -samples using the provided CMake script, regardless of the platform. - -Requirements for Contributors ------------------------------ - -We welcome patches. If you plan to contribute a patch, you need to -build Google Test and its own tests from an SVN checkout (described -below), which has further requirements: - - * Python version 2.3 or newer (for running some of the tests and - re-generating certain source files from templates) - * CMake 2.6.4 or newer - -Getting the Source ------------------- - -There are two primary ways of getting Google Test's source code: you -can download a stable source release in your preferred archive format, -or directly check out the source from our Subversion (SVN) repositary. -The SVN checkout requires a few extra steps and some extra software -packages on your system, but lets you track the latest development and -make patches much more easily, so we highly encourage it. - -### Source Package ### - -Google Test is released in versioned source packages which can be -downloaded from the download page [1]. Several different archive -formats are provided, but the only difference is the tools used to -manipulate them, and the size of the resulting file. Download -whichever you are most comfortable with. - - [1] http://code.google.com/p/googletest/downloads/list - -Once the package is downloaded, expand it using whichever tools you -prefer for that type. This will result in a new directory with the -name "gtest-X.Y.Z" which contains all of the source code. Here are -some examples on Linux: - - tar -xvzf gtest-X.Y.Z.tar.gz - tar -xvjf gtest-X.Y.Z.tar.bz2 - unzip gtest-X.Y.Z.zip - -### SVN Checkout ### - -To check out the main branch (also known as the "trunk") of Google -Test, run the following Subversion command: - - svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn - -Setting up the Build --------------------- - -To build Google Test and your tests that use it, you need to tell your -build system where to find its headers and source files. The exact -way to do it depends on which build system you use, and is usually -straightforward. - -### Generic Build Instructions ### - -Suppose you put Google Test in directory ${GTEST_DIR}. To build it, -create a library build target (or a project as called by Visual Studio -and Xcode) to compile - - ${GTEST_DIR}/src/gtest-all.cc - -with ${GTEST_DIR}/include in the system header search path and ${GTEST_DIR} -in the normal header search path. Assuming a Linux-like system and gcc, -something like the following will do: - - g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \ - -pthread -c ${GTEST_DIR}/src/gtest-all.cc - ar -rv libgtest.a gtest-all.o - -(We need -pthread as Google Test uses threads.) - -Next, you should compile your test source file with -${GTEST_DIR}/include in the system header search path, and link it -with gtest and any other necessary libraries: - - g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \ - -o your_test - -As an example, the make/ directory contains a Makefile that you can -use to build Google Test on systems where GNU make is available -(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google -Test's own tests. Instead, it just builds the Google Test library and -a sample test. You can use it as a starting point for your own build -script. - -If the default settings are correct for your environment, the -following commands should succeed: - - cd ${GTEST_DIR}/make - make - ./sample1_unittest - -If you see errors, try to tweak the contents of make/Makefile to make -them go away. There are instructions in make/Makefile on how to do -it. - -### Using CMake ### - -Google Test comes with a CMake build script (CMakeLists.txt) that can -be used on a wide range of platforms ("C" stands for cross-platofrm.). -If you don't have CMake installed already, you can download it for -free from http://www.cmake.org/. - -CMake works by generating native makefiles or build projects that can -be used in the compiler environment of your choice. The typical -workflow starts with: - - mkdir mybuild # Create a directory to hold the build output. - cd mybuild - cmake ${GTEST_DIR} # Generate native build scripts. - -If you want to build Google Test's samples, you should replace the -last command with - - cmake -Dgtest_build_samples=ON ${GTEST_DIR} - -If you are on a *nix system, you should now see a Makefile in the -current directory. Just type 'make' to build gtest. - -If you use Windows and have Vistual Studio installed, a gtest.sln file -and several .vcproj files will be created. You can then build them -using Visual Studio. - -On Mac OS X with Xcode installed, a .xcodeproj file will be generated. - -### Legacy Build Scripts ### - -Before settling on CMake, we have been providing hand-maintained build -projects/scripts for Visual Studio, Xcode, and Autotools. While we -continue to provide them for convenience, they are not actively -maintained any more. We highly recommend that you follow the -instructions in the previous two sections to integrate Google Test -with your existing build system. - -If you still need to use the legacy build scripts, here's how: - -The msvc\ folder contains two solutions with Visual C++ projects. -Open the gtest.sln or gtest-md.sln file using Visual Studio, and you -are ready to build Google Test the same way you build any Visual -Studio project. Files that have names ending with -md use DLL -versions of Microsoft runtime libraries (the /MD or the /MDd compiler -option). Files without that suffix use static versions of the runtime -libraries (the /MT or the /MTd option). Please note that one must use -the same option to compile both gtest and the test code. If you use -Visual Studio 2005 or above, we recommend the -md version as /MD is -the default for new projects in these versions of Visual Studio. - -On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using -Xcode. Build the "gtest" target. The universal binary framework will -end up in your selected build directory (selected in the Xcode -"Preferences..." -> "Building" pane and defaults to xcode/build). -Alternatively, at the command line, enter: - - xcodebuild - -This will build the "Release" configuration of gtest.framework in your -default build location. See the "xcodebuild" man page for more -information about building different configurations and building in -different locations. - -If you wish to use the Google Test Xcode project with Xcode 4.x and -above, you need to either: - * update the SDK configuration options in xcode/Config/General.xconfig. - Comment options SDKROOT, MACOS_DEPLOYMENT_TARGET, and GCC_VERSION. If - you choose this route you lose the ability to target earlier versions - of MacOS X. - * Install an SDK for an earlier version. This doesn't appear to be - supported by Apple, but has been reported to work - (http://stackoverflow.com/questions/5378518). - -Tweaking Google Test --------------------- - -Google Test can be used in diverse environments. The default -configuration may not work (or may not work well) out of the box in -some environments. However, you can easily tweak Google Test by -defining control macros on the compiler command line. Generally, -these macros are named like GTEST_XYZ and you define them to either 1 -or 0 to enable or disable a certain feature. - -We list the most frequently used macros below. For a complete list, -see file include/gtest/internal/gtest-port.h. - -### Choosing a TR1 Tuple Library ### - -Some Google Test features require the C++ Technical Report 1 (TR1) -tuple library, which is not yet available with all compilers. The -good news is that Google Test implements a subset of TR1 tuple that's -enough for its own need, and will automatically use this when the -compiler doesn't provide TR1 tuple. - -Usually you don't need to care about which tuple library Google Test -uses. However, if your project already uses TR1 tuple, you need to -tell Google Test to use the same TR1 tuple library the rest of your -project uses, or the two tuple implementations will clash. To do -that, add - - -DGTEST_USE_OWN_TR1_TUPLE=0 - -to the compiler flags while compiling Google Test and your tests. If -you want to force Google Test to use its own tuple library, just add - - -DGTEST_USE_OWN_TR1_TUPLE=1 - -to the compiler flags instead. - -If you don't want Google Test to use tuple at all, add - - -DGTEST_HAS_TR1_TUPLE=0 - -and all features using tuple will be disabled. - -### Multi-threaded Tests ### - -Google Test is thread-safe where the pthread library is available. -After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE -macro to see whether this is the case (yes if the macro is #defined to -1, no if it's undefined.). - -If Google Test doesn't correctly detect whether pthread is available -in your environment, you can force it with - - -DGTEST_HAS_PTHREAD=1 - -or - - -DGTEST_HAS_PTHREAD=0 - -When Google Test uses pthread, you may need to add flags to your -compiler and/or linker to select the pthread library, or you'll get -link errors. If you use the CMake script or the deprecated Autotools -script, this is taken care of for you. If you use your own build -script, you'll need to read your compiler and linker's manual to -figure out what flags to add. - -### As a Shared Library (DLL) ### - -Google Test is compact, so most users can build and link it as a -static library for the simplicity. You can choose to use Google Test -as a shared library (known as a DLL on Windows) if you prefer. - -To compile *gtest* as a shared library, add - - -DGTEST_CREATE_SHARED_LIBRARY=1 - -to the compiler flags. You'll also need to tell the linker to produce -a shared library instead - consult your linker's manual for how to do -it. - -To compile your *tests* that use the gtest shared library, add - - -DGTEST_LINKED_AS_SHARED_LIBRARY=1 - -to the compiler flags. - -Note: while the above steps aren't technically necessary today when -using some compilers (e.g. GCC), they may become necessary in the -future, if we decide to improve the speed of loading the library (see -http://gcc.gnu.org/wiki/Visibility for details). Therefore you are -recommended to always add the above flags when using Google Test as a -shared library. Otherwise a future release of Google Test may break -your build script. - -### Avoiding Macro Name Clashes ### - -In C++, macros don't obey namespaces. Therefore two libraries that -both define a macro of the same name will clash if you #include both -definitions. In case a Google Test macro clashes with another -library, you can force Google Test to rename its macro to avoid the -conflict. - -Specifically, if both Google Test and some other code define macro -FOO, you can add - - -DGTEST_DONT_DEFINE_FOO=1 - -to the compiler flags to tell Google Test to change the macro's name -from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST. -For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write - - GTEST_TEST(SomeTest, DoesThis) { ... } - -instead of - - TEST(SomeTest, DoesThis) { ... } - -in order to define a test. - -Upgrating from an Earlier Version ---------------------------------- - -We strive to keep Google Test releases backward compatible. -Sometimes, though, we have to make some breaking changes for the -users' long-term benefits. This section describes what you'll need to -do if you are upgrading from an earlier version of Google Test. - -### Upgrading from 1.3.0 or Earlier ### - -You may need to explicitly enable or disable Google Test's own TR1 -tuple library. See the instructions in section "Choosing a TR1 Tuple -Library". - -### Upgrading from 1.4.0 or Earlier ### - -The Autotools build script (configure + make) is no longer officially -supportted. You are encouraged to migrate to your own build system or -use CMake. If you still need to use Autotools, you can find -instructions in the README file from Google Test 1.4.0. - -On platforms where the pthread library is available, Google Test uses -it in order to be thread-safe. See the "Multi-threaded Tests" section -for what this means to your build script. - -If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google -Test will no longer compile. This should affect very few people, as a -large portion of STL (including ) doesn't compile in this mode -anyway. We decided to stop supporting it in order to greatly simplify -Google Test's implementation. - -Developing Google Test ----------------------- - -This section discusses how to make your own changes to Google Test. - -### Testing Google Test Itself ### - -To make sure your changes work as intended and don't break existing -functionality, you'll want to compile and run Google Test's own tests. -For that you can use CMake: - - mkdir mybuild - cd mybuild - cmake -Dgtest_build_tests=ON ${GTEST_DIR} - -Make sure you have Python installed, as some of Google Test's tests -are written in Python. If the cmake command complains about not being -able to find Python ("Could NOT find PythonInterp (missing: -PYTHON_EXECUTABLE)"), try telling it explicitly where your Python -executable can be found: - - cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR} - -Next, you can build Google Test and all of its own tests. On *nix, -this is usually done by 'make'. To run the tests, do - - make test - -All tests should pass. - -### Regenerating Source Files ### - -Some of Google Test's source files are generated from templates (not -in the C++ sense) using a script. A template file is named FOO.pump, -where FOO is the name of the file it will generate. For example, the -file include/gtest/internal/gtest-type-util.h.pump is used to generate -gtest-type-util.h in the same directory. - -Normally you don't need to worry about regenerating the source files, -unless you need to modify them. In that case, you should modify the -corresponding .pump files instead and run the pump.py Python script to -regenerate them. You can find pump.py in the scripts/ directory. -Read the Pump manual [2] for how to use it. - - [2] http://code.google.com/p/googletest/wiki/PumpManual - -### Contributing a Patch ### - -We welcome patches. Please read the Google Test developer's guide [3] -for how you can contribute. In particular, make sure you have signed -the Contributor License Agreement, or we won't be able to accept the -patch. - - [3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide - -Happy testing! diff --git a/Sofa/framework/Testing/extlibs/gtest/README.md b/Sofa/framework/Testing/extlibs/gtest/README.md deleted file mode 100644 index e30fe804712..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/README.md +++ /dev/null @@ -1,341 +0,0 @@ -### Generic Build Instructions - -#### Setup - -To build Google Test and your tests that use it, you need to tell your build -system where to find its headers and source files. The exact way to do it -depends on which build system you use, and is usually straightforward. - -#### Build - -Suppose you put Google Test in directory `${GTEST_DIR}`. To build it, create a -library build target (or a project as called by Visual Studio and Xcode) to -compile - - ${GTEST_DIR}/src/gtest-all.cc - -with `${GTEST_DIR}/include` in the system header search path and `${GTEST_DIR}` -in the normal header search path. Assuming a Linux-like system and gcc, -something like the following will do: - - g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \ - -pthread -c ${GTEST_DIR}/src/gtest-all.cc - ar -rv libgtest.a gtest-all.o - -(We need `-pthread` as Google Test uses threads.) - -Next, you should compile your test source file with `${GTEST_DIR}/include` in -the system header search path, and link it with gtest and any other necessary -libraries: - - g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \ - -o your_test - -As an example, the make/ directory contains a Makefile that you can use to build -Google Test on systems where GNU make is available (e.g. Linux, Mac OS X, and -Cygwin). It doesn't try to build Google Test's own tests. Instead, it just -builds the Google Test library and a sample test. You can use it as a starting -point for your own build script. - -If the default settings are correct for your environment, the following commands -should succeed: - - cd ${GTEST_DIR}/make - make - ./sample1_unittest - -If you see errors, try to tweak the contents of `make/Makefile` to make them go -away. There are instructions in `make/Makefile` on how to do it. - -### Using CMake - -Google Test comes with a CMake build script ( -[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt)) -that can be used on a wide range of platforms ("C" stands for cross-platform.). -If you don't have CMake installed already, you can download it for free from -. - -CMake works by generating native makefiles or build projects that can be used in -the compiler environment of your choice. You can either build Google Test as a -standalone project or it can be incorporated into an existing CMake build for -another project. - -#### Standalone CMake Project - -When building Google Test as a standalone project, the typical workflow starts -with: - - mkdir mybuild # Create a directory to hold the build output. - cd mybuild - cmake ${GTEST_DIR} # Generate native build scripts. - -If you want to build Google Test's samples, you should replace the last command -with - - cmake -Dgtest_build_samples=ON ${GTEST_DIR} - -If you are on a \*nix system, you should now see a Makefile in the current -directory. Just type 'make' to build gtest. - -If you use Windows and have Visual Studio installed, a `gtest.sln` file and -several `.vcproj` files will be created. You can then build them using Visual -Studio. - -On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated. - -#### Incorporating Into An Existing CMake Project - -If you want to use gtest in a project which already uses CMake, then a more -robust and flexible approach is to build gtest as part of that project directly. -This is done by making the GoogleTest source code available to the main build -and adding it using CMake's `add_subdirectory()` command. This has the -significant advantage that the same compiler and linker settings are used -between gtest and the rest of your project, so issues associated with using -incompatible libraries (eg debug/release), etc. are avoided. This is -particularly useful on Windows. Making GoogleTest's source code available to the -main build can be done a few different ways: - -* Download the GoogleTest source code manually and place it at a known - location. This is the least flexible approach and can make it more difficult - to use with continuous integration systems, etc. -* Embed the GoogleTest source code as a direct copy in the main project's - source tree. This is often the simplest approach, but is also the hardest to - keep up to date. Some organizations may not permit this method. -* Add GoogleTest as a git submodule or equivalent. This may not always be - possible or appropriate. Git submodules, for example, have their own set of - advantages and drawbacks. -* Use CMake to download GoogleTest as part of the build's configure step. This - is just a little more complex, but doesn't have the limitations of the other - methods. - -The last of the above methods is implemented with a small piece of CMake code in -a separate file (e.g. `CMakeLists.txt.in`) which is copied to the build area and -then invoked as a sub-build _during the CMake stage_. That directory is then -pulled into the main build with `add_subdirectory()`. For example: - -New file `CMakeLists.txt.in`: - - cmake_minimum_required(VERSION 2.8.2) - - project(googletest-download NONE) - - include(ExternalProject) - ExternalProject_Add(googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG master - SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" - BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" - ) - -Existing build's `CMakeLists.txt`: - - # Download and unpack googletest at configure time - configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) - execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . - RESULT_VARIABLE result - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download ) - if(result) - message(FATAL_ERROR "CMake step for googletest failed: ${result}") - endif() - execute_process(COMMAND ${CMAKE_COMMAND} --build . - RESULT_VARIABLE result - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download ) - if(result) - message(FATAL_ERROR "Build step for googletest failed: ${result}") - endif() - - # Prevent overriding the parent project's compiler/linker - # settings on Windows - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - - # Add googletest directly to our build. This defines - # the gtest and gtest_main targets. - add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src - ${CMAKE_BINARY_DIR}/googletest-build - EXCLUDE_FROM_ALL) - - # The gtest/gtest_main targets carry header search path - # dependencies automatically when using CMake 2.8.11 or - # later. Otherwise we have to add them here ourselves. - if (CMAKE_VERSION VERSION_LESS 2.8.11) - include_directories("${gtest_SOURCE_DIR}/include") - endif() - - # Now simply link against gtest or gtest_main as needed. Eg - add_executable(example example.cpp) - target_link_libraries(example gtest_main) - add_test(NAME example_test COMMAND example) - -Note that this approach requires CMake 2.8.2 or later due to its use of the -`ExternalProject_Add()` command. The above technique is discussed in more detail -in [this separate article](http://crascit.com/2015/07/25/cmake-gtest/) which -also contains a link to a fully generalized implementation of the technique. - -##### Visual Studio Dynamic vs Static Runtimes - -By default, new Visual Studio projects link the C runtimes dynamically but -Google Test links them statically. This will generate an error that looks -something like the following: gtest.lib(gtest-all.obj) : error LNK2038: mismatch -detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value -'MDd_DynamicDebug' in main.obj - -Google Test already has a CMake option for this: `gtest_force_shared_crt` - -Enabling this option will make gtest link the runtimes dynamically too, and -match the project in which it is included. - -### Legacy Build Scripts - -Before settling on CMake, we have been providing hand-maintained build -projects/scripts for Visual Studio, Xcode, and Autotools. While we continue to -provide them for convenience, they are not actively maintained any more. We -highly recommend that you follow the instructions in the above sections to -integrate Google Test with your existing build system. - -If you still need to use the legacy build scripts, here's how: - -The msvc\ folder contains two solutions with Visual C++ projects. Open the -`gtest.sln` or `gtest-md.sln` file using Visual Studio, and you are ready to -build Google Test the same way you build any Visual Studio project. Files that -have names ending with -md use DLL versions of Microsoft runtime libraries (the -/MD or the /MDd compiler option). Files without that suffix use static versions -of the runtime libraries (the /MT or the /MTd option). Please note that one must -use the same option to compile both gtest and the test code. If you use Visual -Studio 2005 or above, we recommend the -md version as /MD is the default for new -projects in these versions of Visual Studio. - -On Mac OS X, open the `gtest.xcodeproj` in the `xcode/` folder using Xcode. -Build the "gtest" target. The universal binary framework will end up in your -selected build directory (selected in the Xcode "Preferences..." -> "Building" -pane and defaults to xcode/build). Alternatively, at the command line, enter: - - xcodebuild - -This will build the "Release" configuration of gtest.framework in your default -build location. See the "xcodebuild" man page for more information about -building different configurations and building in different locations. - -If you wish to use the Google Test Xcode project with Xcode 4.x and above, you -need to either: - -* update the SDK configuration options in xcode/Config/General.xconfig. - Comment options `SDKROOT`, `MACOS_DEPLOYMENT_TARGET`, and `GCC_VERSION`. If - you choose this route you lose the ability to target earlier versions of - MacOS X. -* Install an SDK for an earlier version. This doesn't appear to be supported - by Apple, but has been reported to work - (http://stackoverflow.com/questions/5378518). - -### Tweaking Google Test - -Google Test can be used in diverse environments. The default configuration may -not work (or may not work well) out of the box in some environments. However, -you can easily tweak Google Test by defining control macros on the compiler -command line. Generally, these macros are named like `GTEST_XYZ` and you define -them to either 1 or 0 to enable or disable a certain feature. - -We list the most frequently used macros below. For a complete list, see file -[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/include/gtest/internal/gtest-port.h). - -### Choosing a TR1 Tuple Library - -Some Google Test features require the C++ Technical Report 1 (TR1) tuple -library, which is not yet available with all compilers. The good news is that -Google Test implements a subset of TR1 tuple that's enough for its own need, and -will automatically use this when the compiler doesn't provide TR1 tuple. - -Usually you don't need to care about which tuple library Google Test uses. -However, if your project already uses TR1 tuple, you need to tell Google Test to -use the same TR1 tuple library the rest of your project uses, or the two tuple -implementations will clash. To do that, add - - -DGTEST_USE_OWN_TR1_TUPLE=0 - -to the compiler flags while compiling Google Test and your tests. If you want to -force Google Test to use its own tuple library, just add - - -DGTEST_USE_OWN_TR1_TUPLE=1 - -to the compiler flags instead. - -If you don't want Google Test to use tuple at all, add - - -DGTEST_HAS_TR1_TUPLE=0 - -and all features using tuple will be disabled. - -### Multi-threaded Tests - -Google Test is thread-safe where the pthread library is available. After -`#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE` macro to see -whether this is the case (yes if the macro is `#defined` to 1, no if it's -undefined.). - -If Google Test doesn't correctly detect whether pthread is available in your -environment, you can force it with - - -DGTEST_HAS_PTHREAD=1 - -or - - -DGTEST_HAS_PTHREAD=0 - -When Google Test uses pthread, you may need to add flags to your compiler and/or -linker to select the pthread library, or you'll get link errors. If you use the -CMake script or the deprecated Autotools script, this is taken care of for you. -If you use your own build script, you'll need to read your compiler and linker's -manual to figure out what flags to add. - -### As a Shared Library (DLL) - -Google Test is compact, so most users can build and link it as a static library -for the simplicity. You can choose to use Google Test as a shared library (known -as a DLL on Windows) if you prefer. - -To compile *gtest* as a shared library, add - - -DGTEST_CREATE_SHARED_LIBRARY=1 - -to the compiler flags. You'll also need to tell the linker to produce a shared -library instead - consult your linker's manual for how to do it. - -To compile your *tests* that use the gtest shared library, add - - -DGTEST_LINKED_AS_SHARED_LIBRARY=1 - -to the compiler flags. - -Note: while the above steps aren't technically necessary today when using some -compilers (e.g. GCC), they may become necessary in the future, if we decide to -improve the speed of loading the library (see - for details). Therefore you are recommended -to always add the above flags when using Google Test as a shared library. -Otherwise a future release of Google Test may break your build script. - -### Avoiding Macro Name Clashes - -In C++, macros don't obey namespaces. Therefore two libraries that both define a -macro of the same name will clash if you `#include` both definitions. In case a -Google Test macro clashes with another library, you can force Google Test to -rename its macro to avoid the conflict. - -Specifically, if both Google Test and some other code define macro FOO, you can -add - - -DGTEST_DONT_DEFINE_FOO=1 - -to the compiler flags to tell Google Test to change the macro's name from `FOO` -to `GTEST_FOO`. Currently `FOO` can be `FAIL`, `SUCCEED`, or `TEST`. For -example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write - - GTEST_TEST(SomeTest, DoesThis) { ... } - -instead of - - TEST(SomeTest, DoesThis) { ... } - -in order to define a test. diff --git a/Sofa/framework/Testing/extlibs/gtest/cmake/Config.cmake.in b/Sofa/framework/Testing/extlibs/gtest/cmake/Config.cmake.in deleted file mode 100644 index 12be4498b1a..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/cmake/Config.cmake.in +++ /dev/null @@ -1,9 +0,0 @@ -@PACKAGE_INIT@ -include(CMakeFindDependencyMacro) -if (@GTEST_HAS_PTHREAD@) - set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@) - find_dependency(Threads) -endif() - -include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake") -check_required_components("@project_name@") diff --git a/Sofa/framework/Testing/extlibs/gtest/cmake/gtest.pc.in b/Sofa/framework/Testing/extlibs/gtest/cmake/gtest.pc.in deleted file mode 100644 index e7967ad56ff..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/cmake/gtest.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ - -Name: gtest -Description: GoogleTest (without main() function) -Version: @PROJECT_VERSION@ -URL: https://github.com/google/googletest -Libs: -L${libdir} -lgtest @CMAKE_THREAD_LIBS_INIT@ -Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ diff --git a/Sofa/framework/Testing/extlibs/gtest/cmake/gtest_main.pc.in b/Sofa/framework/Testing/extlibs/gtest/cmake/gtest_main.pc.in deleted file mode 100644 index fe25d9c73c6..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/cmake/gtest_main.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ - -Name: gtest_main -Description: GoogleTest (with main() function) -Version: @PROJECT_VERSION@ -URL: https://github.com/google/googletest -Requires: gtest -Libs: -L${libdir} -lgtest_main @CMAKE_THREAD_LIBS_INIT@ -Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ diff --git a/Sofa/framework/Testing/extlibs/gtest/cmake/internal_utils.cmake b/Sofa/framework/Testing/extlibs/gtest/cmake/internal_utils.cmake deleted file mode 100644 index 8c1f9ba99cf..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/cmake/internal_utils.cmake +++ /dev/null @@ -1,318 +0,0 @@ -# Defines functions and macros useful for building Google Test and -# Google Mock. -# -# Note: -# -# - This file will be run twice when building Google Mock (once via -# Google Test's CMakeLists.txt, and once via Google Mock's). -# Therefore it shouldn't have any side effects other than defining -# the functions and macros. -# -# - The functions/macros defined in this file may depend on Google -# Test and Google Mock's option() definitions, and thus must be -# called *after* the options have been defined. - -# Tweaks CMake's default compiler/linker settings to suit Google Test's needs. -# -# This must be a macro(), as inside a function string() can only -# update variables in the function scope. -macro(fix_default_compiler_settings_) - if (MSVC) - # For MSVC, CMake sets certain flags to defaults we want to override. - # This replacement code is taken from sample in the CMake Wiki at - # https://gitlab.kitware.com/cmake/community/wikis/FAQ#dynamic-replace. - foreach (flag_var - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt) - # When Google Test is built as a shared library, it should also use - # shared runtime libraries. Otherwise, it may end up with multiple - # copies of runtime library data in different modules, resulting in - # hard-to-find crashes. When it is built as a static library, it is - # preferable to use CRT as static libraries, as we don't have to rely - # on CRT DLLs being available. CMake always defaults to using shared - # CRT libraries, so we override that default here. - string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}") - endif() - - # We prefer more strict warning checking for building Google Test. - # Replaces /W3 with /W4 in defaults. - string(REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}") - - # Prevent D9025 warning for targets that have exception handling - # turned off (/EHs-c- flag). Where required, exceptions are explicitly - # re-enabled using the cxx_exception_flags variable. - string(REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}") - endforeach() - endif() -endmacro() - -# Defines the compiler/linker flags used to build Google Test and -# Google Mock. You can tweak these definitions to suit your need. A -# variable's value is empty before it's explicitly assigned to. -macro(config_compiler_and_linker) - # Note: pthreads on MinGW is not supported, even if available - # instead, we use windows threading primitives - unset(GTEST_HAS_PTHREAD) - if (NOT gtest_disable_pthreads AND NOT MINGW) - # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT. - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_package(Threads) - if (CMAKE_USE_PTHREADS_INIT) - set(GTEST_HAS_PTHREAD ON) - endif() - endif() - - fix_default_compiler_settings_() - if (MSVC) - # Newlines inside flags variables break CMake's NMake generator. - # TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds. - set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J -Zi") - if (MSVC_VERSION LESS 1400) # 1400 is Visual Studio 2005 - # Suppress spurious warnings MSVC 7.1 sometimes issues. - # Forcing value to bool. - set(cxx_base_flags "${cxx_base_flags} -wd4800") - # Copy constructor and assignment operator could not be generated. - set(cxx_base_flags "${cxx_base_flags} -wd4511 -wd4512") - # Compatibility warnings not applicable to Google Test. - # Resolved overload was found by argument-dependent lookup. - set(cxx_base_flags "${cxx_base_flags} -wd4675") - endif() - if (MSVC_VERSION LESS 1500) # 1500 is Visual Studio 2008 - # Conditional expression is constant. - # When compiling with /W4, we get several instances of C4127 - # (Conditional expression is constant). In our code, we disable that - # warning on a case-by-case basis. However, on Visual Studio 2005, - # the warning fires on std::list. Therefore on that compiler and earlier, - # we disable the warning project-wide. - set(cxx_base_flags "${cxx_base_flags} -wd4127") - endif() - if (NOT (MSVC_VERSION LESS 1700)) # 1700 is Visual Studio 2012. - # Suppress "unreachable code" warning on VS 2012 and later. - # http://stackoverflow.com/questions/3232669 explains the issue. - set(cxx_base_flags "${cxx_base_flags} -wd4702") - endif() - - set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32") - set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN") - set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1") - set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0") - set(cxx_no_rtti_flags "-GR-") - elseif (CMAKE_COMPILER_IS_GNUCXX) - set(cxx_base_flags "-Wall -Wshadow -Werror") - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0) - set(cxx_base_flags "${cxx_base_flags} -Wno-error=dangling-else") - endif() - set(cxx_exception_flags "-fexceptions") - set(cxx_no_exception_flags "-fno-exceptions") - # Until version 4.3.2, GCC doesn't define a macro to indicate - # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI - # explicitly. - set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0") - set(cxx_strict_flags - "-Wextra -Wno-unused-parameter -Wno-missing-field-initializers") - elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") - set(cxx_exception_flags "-features=except") - # Sun Pro doesn't provide macros to indicate whether exceptions and - # RTTI are enabled, so we define GTEST_HAS_* explicitly. - set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0") - set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0") - elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR - CMAKE_CXX_COMPILER_ID STREQUAL "XL") - # CMake 2.8 changes Visual Age's compiler ID to "XL". - set(cxx_exception_flags "-qeh") - set(cxx_no_exception_flags "-qnoeh") - # Until version 9.0, Visual Age doesn't define a macro to indicate - # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI - # explicitly. - set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0") - elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP") - set(cxx_base_flags "-AA -mt") - set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1") - set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0") - # RTTI can not be disabled in HP aCC compiler. - set(cxx_no_rtti_flags "") - endif() - - # The pthreads library is available and allowed? - if (DEFINED GTEST_HAS_PTHREAD) - set(GTEST_HAS_PTHREAD_MACRO "-DGTEST_HAS_PTHREAD=1") - else() - set(GTEST_HAS_PTHREAD_MACRO "-DGTEST_HAS_PTHREAD=0") - endif() - set(cxx_base_flags "${cxx_base_flags} ${GTEST_HAS_PTHREAD_MACRO}") - - # For building gtest's own tests and samples. - set(cxx_exception "${cxx_base_flags} ${cxx_exception_flags}") - set(cxx_no_exception - "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}") - set(cxx_default "${cxx_exception}") - set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}") - set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1") - - # For building the gtest libraries. - set(cxx_strict "${cxx_default} ${cxx_strict_flags}") -endmacro() - -# Defines the gtest & gtest_main libraries. User tests should link -# with one of them. -function(cxx_library_with_type name type cxx_flags) - # type can be either STATIC or SHARED to denote a static or shared library. - # ARGN refers to additional arguments after 'cxx_flags'. - add_library(${name} ${type} ${ARGN}) - set_target_properties(${name} - PROPERTIES - COMPILE_FLAGS "${cxx_flags}") - # Generate debug library name with a postfix. - set_target_properties(${name} - PROPERTIES - DEBUG_POSTFIX "d") - if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED") - set_target_properties(${name} - PROPERTIES - COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1") - if (NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11") - target_compile_definitions(${name} INTERFACE - $) - endif() - endif() - if (DEFINED GTEST_HAS_PTHREAD) - if ("${CMAKE_VERSION}" VERSION_LESS "3.1.0") - set(threads_spec ${CMAKE_THREAD_LIBS_INIT}) - else() - set(threads_spec Threads::Threads) - endif() - target_link_libraries(${name} PUBLIC ${threads_spec}) - endif() -endfunction() - -######################################################################## -# -# Helper functions for creating build targets. - -function(cxx_shared_library name cxx_flags) - cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN}) -endfunction() - -function(cxx_library name cxx_flags) - cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN}) -endfunction() - -# cxx_executable_with_flags(name cxx_flags libs srcs...) -# -# creates a named C++ executable that depends on the given libraries and -# is built from the given source files with the given compiler flags. -function(cxx_executable_with_flags name cxx_flags libs) - add_executable(${name} ${ARGN}) - if (MSVC AND (NOT (MSVC_VERSION LESS 1700))) # 1700 is Visual Studio 2012. - # BigObj required for tests. - set(cxx_flags "${cxx_flags} -bigobj") - endif() - if (cxx_flags) - set_target_properties(${name} - PROPERTIES - COMPILE_FLAGS "${cxx_flags}") - endif() - if (BUILD_SHARED_LIBS) - set_target_properties(${name} - PROPERTIES - COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1") - endif() - # To support mixing linking in static and dynamic libraries, link each - # library in with an extra call to target_link_libraries. - foreach (lib "${libs}") - target_link_libraries(${name} ${lib}) - endforeach() -endfunction() - -# cxx_executable(name dir lib srcs...) -# -# creates a named target that depends on the given libs and is built -# from the given source files. dir/name.cc is implicitly included in -# the source file list. -function(cxx_executable name dir libs) - cxx_executable_with_flags( - ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN}) -endfunction() - -# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE. -find_package(PythonInterp) - -# cxx_test_with_flags(name cxx_flags libs srcs...) -# -# creates a named C++ test that depends on the given libs and is built -# from the given source files with the given compiler flags. -function(cxx_test_with_flags name cxx_flags libs) - cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN}) - add_test(NAME ${name} COMMAND ${name}) -endfunction() - -# cxx_test(name libs srcs...) -# -# creates a named test target that depends on the given libs and is -# built from the given source files. Unlike cxx_test_with_flags, -# test/name.cc is already implicitly included in the source file list. -function(cxx_test name libs) - cxx_test_with_flags("${name}" "${cxx_default}" "${libs}" - "test/${name}.cc" ${ARGN}) -endfunction() - -# py_test(name) -# -# creates a Python test with the given name whose main module is in -# test/name.py. It does nothing if Python is not installed. -function(py_test name) - if (PYTHONINTERP_FOUND) - if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.1) - if (CMAKE_CONFIGURATION_TYPES) - # Multi-configuration build generators as for Visual Studio save - # output in a subdirectory of CMAKE_CURRENT_BINARY_DIR (Debug, - # Release etc.), so we have to provide it here. - add_test( - NAME ${name} - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py - --build_dir=${CMAKE_CURRENT_BINARY_DIR}/$ ${ARGN}) - else (CMAKE_CONFIGURATION_TYPES) - # Single-configuration build generators like Makefile generators - # don't have subdirs below CMAKE_CURRENT_BINARY_DIR. - add_test( - NAME ${name} - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py - --build_dir=${CMAKE_CURRENT_BINARY_DIR} ${ARGN}) - endif (CMAKE_CONFIGURATION_TYPES) - else (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.1) - # ${CMAKE_CURRENT_BINARY_DIR} is known at configuration time, so we can - # directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known - # only at ctest runtime (by calling ctest -c ), so - # we have to escape $ to delay variable substitution here. - add_test( - ${name} - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py - --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN}) - endif (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.1) - endif(PYTHONINTERP_FOUND) -endfunction() - -# install_project(targets...) -# -# Installs the specified targets and configures the associated pkgconfig files. -function(install_project) - if(INSTALL_GTEST) - install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") - # Install the project targets. - install(TARGETS ${ARGN} - EXPORT ${targets_export_name} - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") - # Configure and install pkgconfig files. - foreach(t ${ARGN}) - set(configured_pc "${generated_dir}/${t}.pc") - configure_file("${PROJECT_SOURCE_DIR}/cmake/${t}.pc.in" - "${configured_pc}" @ONLY) - install(FILES "${configured_pc}" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") - endforeach() - endif() -endfunction() diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-death-test.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-death-test.h deleted file mode 100644 index dc878ffbb3a..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-death-test.h +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file defines the public API for death tests. It is -// #included by gtest.h so a user doesn't need to include this -// directly. -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ - -#include "gtest/internal/gtest-death-test-internal.h" - -namespace testing { - -// This flag controls the style of death tests. Valid values are "threadsafe", -// meaning that the death test child process will re-execute the test binary -// from the start, running only a single death test, or "fast", -// meaning that the child process will execute the test logic immediately -// after forking. -GTEST_DECLARE_string_(death_test_style); - -#if GTEST_HAS_DEATH_TEST - -namespace internal { - -// Returns a Boolean value indicating whether the caller is currently -// executing in the context of the death test child process. Tools such as -// Valgrind heap checkers may need this to modify their behavior in death -// tests. IMPORTANT: This is an internal utility. Using it may break the -// implementation of death tests. User code MUST NOT use it. -GTEST_API_ bool InDeathTestChild(); - -} // namespace internal - -// The following macros are useful for writing death tests. - -// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is -// executed: -// -// 1. It generates a warning if there is more than one active -// thread. This is because it's safe to fork() or clone() only -// when there is a single thread. -// -// 2. The parent process clone()s a sub-process and runs the death -// test in it; the sub-process exits with code 0 at the end of the -// death test, if it hasn't exited already. -// -// 3. The parent process waits for the sub-process to terminate. -// -// 4. The parent process checks the exit code and error message of -// the sub-process. -// -// Examples: -// -// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); -// for (int i = 0; i < 5; i++) { -// EXPECT_DEATH(server.ProcessRequest(i), -// "Invalid request .* in ProcessRequest()") -// << "Failed to die on request " << i; -// } -// -// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); -// -// bool KilledBySIGHUP(int exit_code) { -// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; -// } -// -// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); -// -// On the regular expressions used in death tests: -// -// GOOGLETEST_CM0005 DO NOT DELETE -// On POSIX-compliant systems (*nix), we use the library, -// which uses the POSIX extended regex syntax. -// -// On other platforms (e.g. Windows or Mac), we only support a simple regex -// syntax implemented as part of Google Test. This limited -// implementation should be enough most of the time when writing -// death tests; though it lacks many features you can find in PCRE -// or POSIX extended regex syntax. For example, we don't support -// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and -// repetition count ("x{5,7}"), among others. -// -// Below is the syntax that we do support. We chose it to be a -// subset of both PCRE and POSIX extended regex, so it's easy to -// learn wherever you come from. In the following: 'A' denotes a -// literal character, period (.), or a single \\ escape sequence; -// 'x' and 'y' denote regular expressions; 'm' and 'n' are for -// natural numbers. -// -// c matches any literal character c -// \\d matches any decimal digit -// \\D matches any character that's not a decimal digit -// \\f matches \f -// \\n matches \n -// \\r matches \r -// \\s matches any ASCII whitespace, including \n -// \\S matches any character that's not a whitespace -// \\t matches \t -// \\v matches \v -// \\w matches any letter, _, or decimal digit -// \\W matches any character that \\w doesn't match -// \\c matches any literal character c, which must be a punctuation -// . matches any single character except \n -// A? matches 0 or 1 occurrences of A -// A* matches 0 or many occurrences of A -// A+ matches 1 or many occurrences of A -// ^ matches the beginning of a string (not that of each line) -// $ matches the end of a string (not that of each line) -// xy matches x followed by y -// -// If you accidentally use PCRE or POSIX extended regex features -// not implemented by us, you will get a run-time failure. In that -// case, please try to rewrite your regular expression within the -// above syntax. -// -// This implementation is *not* meant to be as highly tuned or robust -// as a compiled regex library, but should perform well enough for a -// death test, which already incurs significant overhead by launching -// a child process. -// -// Known caveats: -// -// A "threadsafe" style death test obtains the path to the test -// program from argv[0] and re-executes it in the sub-process. For -// simplicity, the current implementation doesn't search the PATH -// when launching the sub-process. This means that the user must -// invoke the test program via a path that contains at least one -// path separator (e.g. path/to/foo_test and -// /absolute/path/to/bar_test are fine, but foo_test is not). This -// is rarely a problem as people usually don't put the test binary -// directory in PATH. -// - -// Asserts that a given statement causes the program to exit, with an -// integer exit status that satisfies predicate, and emitting error output -// that matches regex. -# define ASSERT_EXIT(statement, predicate, regex) \ - GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) - -// Like ASSERT_EXIT, but continues on to successive tests in the -// test suite, if any: -# define EXPECT_EXIT(statement, predicate, regex) \ - GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) - -// Asserts that a given statement causes the program to exit, either by -// explicitly exiting with a nonzero exit code or being killed by a -// signal, and emitting error output that matches regex. -# define ASSERT_DEATH(statement, regex) \ - ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) - -// Like ASSERT_DEATH, but continues on to successive tests in the -// test suite, if any: -# define EXPECT_DEATH(statement, regex) \ - EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) - -// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: - -// Tests that an exit code describes a normal exit with a given exit code. -class GTEST_API_ ExitedWithCode { - public: - explicit ExitedWithCode(int exit_code); - bool operator()(int exit_status) const; - private: - // No implementation - assignment is unsupported. - void operator=(const ExitedWithCode& other); - - const int exit_code_; -}; - -# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA -// Tests that an exit code describes an exit due to termination by a -// given signal. -// GOOGLETEST_CM0006 DO NOT DELETE -class GTEST_API_ KilledBySignal { - public: - explicit KilledBySignal(int signum); - bool operator()(int exit_status) const; - private: - const int signum_; -}; -# endif // !GTEST_OS_WINDOWS - -// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. -// The death testing framework causes this to have interesting semantics, -// since the sideeffects of the call are only visible in opt mode, and not -// in debug mode. -// -// In practice, this can be used to test functions that utilize the -// LOG(DFATAL) macro using the following style: -// -// int DieInDebugOr12(int* sideeffect) { -// if (sideeffect) { -// *sideeffect = 12; -// } -// LOG(DFATAL) << "death"; -// return 12; -// } -// -// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) { -// int sideeffect = 0; -// // Only asserts in dbg. -// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); -// -// #ifdef NDEBUG -// // opt-mode has sideeffect visible. -// EXPECT_EQ(12, sideeffect); -// #else -// // dbg-mode no visible sideeffect. -// EXPECT_EQ(0, sideeffect); -// #endif -// } -// -// This will assert that DieInDebugReturn12InOpt() crashes in debug -// mode, usually due to a DCHECK or LOG(DFATAL), but returns the -// appropriate fallback value (12 in this case) in opt mode. If you -// need to test that a function has appropriate side-effects in opt -// mode, include assertions against the side-effects. A general -// pattern for this is: -// -// EXPECT_DEBUG_DEATH({ -// // Side-effects here will have an effect after this statement in -// // opt mode, but none in debug mode. -// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); -// }, "death"); -// -# ifdef NDEBUG - -# define EXPECT_DEBUG_DEATH(statement, regex) \ - GTEST_EXECUTE_STATEMENT_(statement, regex) - -# define ASSERT_DEBUG_DEATH(statement, regex) \ - GTEST_EXECUTE_STATEMENT_(statement, regex) - -# else - -# define EXPECT_DEBUG_DEATH(statement, regex) \ - EXPECT_DEATH(statement, regex) - -# define ASSERT_DEBUG_DEATH(statement, regex) \ - ASSERT_DEATH(statement, regex) - -# endif // NDEBUG for EXPECT_DEBUG_DEATH -#endif // GTEST_HAS_DEATH_TEST - -// This macro is used for implementing macros such as -// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where -// death tests are not supported. Those macros must compile on such systems -// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters -// on systems that support death tests. This allows one to write such a macro on -// a system that does not support death tests and be sure that it will compile -// on a death-test supporting system. It is exposed publicly so that systems -// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST -// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and -// ASSERT_DEATH_IF_SUPPORTED. -// -// Parameters: -// statement - A statement that a macro such as EXPECT_DEATH would test -// for program termination. This macro has to make sure this -// statement is compiled but not executed, to ensure that -// EXPECT_DEATH_IF_SUPPORTED compiles with a certain -// parameter if and only if EXPECT_DEATH compiles with it. -// regex - A regex that a macro such as EXPECT_DEATH would use to test -// the output of statement. This parameter has to be -// compiled but not evaluated by this macro, to ensure that -// this macro only accepts expressions that a macro such as -// EXPECT_DEATH would accept. -// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED -// and a return statement for ASSERT_DEATH_IF_SUPPORTED. -// This ensures that ASSERT_DEATH_IF_SUPPORTED will not -// compile inside functions where ASSERT_DEATH doesn't -// compile. -// -// The branch that has an always false condition is used to ensure that -// statement and regex are compiled (and thus syntactically correct) but -// never executed. The unreachable code macro protects the terminator -// statement from generating an 'unreachable code' warning in case -// statement unconditionally returns or throws. The Message constructor at -// the end allows the syntax of streaming additional messages into the -// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. -# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - GTEST_LOG_(WARNING) \ - << "Death tests are not supported on this platform.\n" \ - << "Statement '" #statement "' cannot be verified."; \ - } else if (::testing::internal::AlwaysFalse()) { \ - ::testing::internal::RE::PartialMatch(".*", (regex)); \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - terminator; \ - } else \ - ::testing::Message() - -// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and -// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if -// death tests are supported; otherwise they just issue a warning. This is -// useful when you are combining death test assertions with normal test -// assertions in one test. -#if GTEST_HAS_DEATH_TEST -# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - EXPECT_DEATH(statement, regex) -# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ - ASSERT_DEATH(statement, regex) -#else -# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, ) -# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ - GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return) -#endif - -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-matchers.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-matchers.h deleted file mode 100644 index 9de6c2e10a2..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-matchers.h +++ /dev/null @@ -1,750 +0,0 @@ -// Copyright 2007, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This file implements just enough of the matcher interface to allow -// EXPECT_DEATH and friends to accept a matcher argument. - -// IWYU pragma: private, include "testing/base/public/gunit.h" -// IWYU pragma: friend third_party/googletest/googlemock/.* -// IWYU pragma: friend third_party/googletest/googletest/.* - -#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ -#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ - -#include -#include -#include -#include - -#include "gtest/gtest-printers.h" -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-port.h" - -// MSVC warning C5046 is new as of VS2017 version 15.8. -#if defined(_MSC_VER) && _MSC_VER >= 1915 -#define GTEST_MAYBE_5046_ 5046 -#else -#define GTEST_MAYBE_5046_ -#endif - -GTEST_DISABLE_MSC_WARNINGS_PUSH_( - 4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by - clients of class B */ - /* Symbol involving type with internal linkage not defined */) - -namespace testing { - -// To implement a matcher Foo for type T, define: -// 1. a class FooMatcherImpl that implements the -// MatcherInterface interface, and -// 2. a factory function that creates a Matcher object from a -// FooMatcherImpl*. -// -// The two-level delegation design makes it possible to allow a user -// to write "v" instead of "Eq(v)" where a Matcher is expected, which -// is impossible if we pass matchers by pointers. It also eases -// ownership management as Matcher objects can now be copied like -// plain values. - -// MatchResultListener is an abstract class. Its << operator can be -// used by a matcher to explain why a value matches or doesn't match. -// -class MatchResultListener { - public: - // Creates a listener object with the given underlying ostream. The - // listener does not own the ostream, and does not dereference it - // in the constructor or destructor. - explicit MatchResultListener(::std::ostream* os) : stream_(os) {} - virtual ~MatchResultListener() = 0; // Makes this class abstract. - - // Streams x to the underlying ostream; does nothing if the ostream - // is NULL. - template - MatchResultListener& operator<<(const T& x) { - if (stream_ != nullptr) *stream_ << x; - return *this; - } - - // Returns the underlying ostream. - ::std::ostream* stream() { return stream_; } - - // Returns true if and only if the listener is interested in an explanation - // of the match result. A matcher's MatchAndExplain() method can use - // this information to avoid generating the explanation when no one - // intends to hear it. - bool IsInterested() const { return stream_ != nullptr; } - - private: - ::std::ostream* const stream_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); -}; - -inline MatchResultListener::~MatchResultListener() { -} - -// An instance of a subclass of this knows how to describe itself as a -// matcher. -class MatcherDescriberInterface { - public: - virtual ~MatcherDescriberInterface() {} - - // Describes this matcher to an ostream. The function should print - // a verb phrase that describes the property a value matching this - // matcher should have. The subject of the verb phrase is the value - // being matched. For example, the DescribeTo() method of the Gt(7) - // matcher prints "is greater than 7". - virtual void DescribeTo(::std::ostream* os) const = 0; - - // Describes the negation of this matcher to an ostream. For - // example, if the description of this matcher is "is greater than - // 7", the negated description could be "is not greater than 7". - // You are not required to override this when implementing - // MatcherInterface, but it is highly advised so that your matcher - // can produce good error messages. - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "not ("; - DescribeTo(os); - *os << ")"; - } -}; - -// The implementation of a matcher. -template -class MatcherInterface : public MatcherDescriberInterface { - public: - // Returns true if and only if the matcher matches x; also explains the - // match result to 'listener' if necessary (see the next paragraph), in - // the form of a non-restrictive relative clause ("which ...", - // "whose ...", etc) that describes x. For example, the - // MatchAndExplain() method of the Pointee(...) matcher should - // generate an explanation like "which points to ...". - // - // Implementations of MatchAndExplain() should add an explanation of - // the match result *if and only if* they can provide additional - // information that's not already present (or not obvious) in the - // print-out of x and the matcher's description. Whether the match - // succeeds is not a factor in deciding whether an explanation is - // needed, as sometimes the caller needs to print a failure message - // when the match succeeds (e.g. when the matcher is used inside - // Not()). - // - // For example, a "has at least 10 elements" matcher should explain - // what the actual element count is, regardless of the match result, - // as it is useful information to the reader; on the other hand, an - // "is empty" matcher probably only needs to explain what the actual - // size is when the match fails, as it's redundant to say that the - // size is 0 when the value is already known to be empty. - // - // You should override this method when defining a new matcher. - // - // It's the responsibility of the caller (Google Test) to guarantee - // that 'listener' is not NULL. This helps to simplify a matcher's - // implementation when it doesn't care about the performance, as it - // can talk to 'listener' without checking its validity first. - // However, in order to implement dummy listeners efficiently, - // listener->stream() may be NULL. - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; - - // Inherits these methods from MatcherDescriberInterface: - // virtual void DescribeTo(::std::ostream* os) const = 0; - // virtual void DescribeNegationTo(::std::ostream* os) const; -}; - -namespace internal { - -// Converts a MatcherInterface to a MatcherInterface. -template -class MatcherInterfaceAdapter : public MatcherInterface { - public: - explicit MatcherInterfaceAdapter(const MatcherInterface* impl) - : impl_(impl) {} - ~MatcherInterfaceAdapter() override { delete impl_; } - - void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); } - - void DescribeNegationTo(::std::ostream* os) const override { - impl_->DescribeNegationTo(os); - } - - bool MatchAndExplain(const T& x, - MatchResultListener* listener) const override { - return impl_->MatchAndExplain(x, listener); - } - - private: - const MatcherInterface* const impl_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter); -}; - -struct AnyEq { - template - bool operator()(const A& a, const B& b) const { return a == b; } -}; -struct AnyNe { - template - bool operator()(const A& a, const B& b) const { return a != b; } -}; -struct AnyLt { - template - bool operator()(const A& a, const B& b) const { return a < b; } -}; -struct AnyGt { - template - bool operator()(const A& a, const B& b) const { return a > b; } -}; -struct AnyLe { - template - bool operator()(const A& a, const B& b) const { return a <= b; } -}; -struct AnyGe { - template - bool operator()(const A& a, const B& b) const { return a >= b; } -}; - -// A match result listener that ignores the explanation. -class DummyMatchResultListener : public MatchResultListener { - public: - DummyMatchResultListener() : MatchResultListener(nullptr) {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener); -}; - -// A match result listener that forwards the explanation to a given -// ostream. The difference between this and MatchResultListener is -// that the former is concrete. -class StreamMatchResultListener : public MatchResultListener { - public: - explicit StreamMatchResultListener(::std::ostream* os) - : MatchResultListener(os) {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); -}; - -// An internal class for implementing Matcher, which will derive -// from it. We put functionalities common to all Matcher -// specializations here to avoid code duplication. -template -class MatcherBase { - public: - // Returns true if and only if the matcher matches x; also explains the - // match result to 'listener'. - bool MatchAndExplain(const T& x, MatchResultListener* listener) const { - return impl_->MatchAndExplain(x, listener); - } - - // Returns true if and only if this matcher matches x. - bool Matches(const T& x) const { - DummyMatchResultListener dummy; - return MatchAndExplain(x, &dummy); - } - - // Describes this matcher to an ostream. - void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } - - // Describes the negation of this matcher to an ostream. - void DescribeNegationTo(::std::ostream* os) const { - impl_->DescribeNegationTo(os); - } - - // Explains why x matches, or doesn't match, the matcher. - void ExplainMatchResultTo(const T& x, ::std::ostream* os) const { - StreamMatchResultListener listener(os); - MatchAndExplain(x, &listener); - } - - // Returns the describer for this matcher object; retains ownership - // of the describer, which is only guaranteed to be alive when - // this matcher object is alive. - const MatcherDescriberInterface* GetDescriber() const { - return impl_.get(); - } - - protected: - MatcherBase() {} - - // Constructs a matcher from its implementation. - explicit MatcherBase(const MatcherInterface* impl) : impl_(impl) {} - - template - explicit MatcherBase( - const MatcherInterface* impl, - typename std::enable_if::value>::type* = - nullptr) - : impl_(new internal::MatcherInterfaceAdapter(impl)) {} - - MatcherBase(const MatcherBase&) = default; - MatcherBase& operator=(const MatcherBase&) = default; - MatcherBase(MatcherBase&&) = default; - MatcherBase& operator=(MatcherBase&&) = default; - - virtual ~MatcherBase() {} - - private: - std::shared_ptr> impl_; -}; - -} // namespace internal - -// A Matcher is a copyable and IMMUTABLE (except by assignment) -// object that can check whether a value of type T matches. The -// implementation of Matcher is just a std::shared_ptr to const -// MatcherInterface. Don't inherit from Matcher! -template -class Matcher : public internal::MatcherBase { - public: - // Constructs a null matcher. Needed for storing Matcher objects in STL - // containers. A default-constructed matcher is not yet initialized. You - // cannot use it until a valid value has been assigned to it. - explicit Matcher() {} // NOLINT - - // Constructs a matcher from its implementation. - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - template - explicit Matcher( - const MatcherInterface* impl, - typename std::enable_if::value>::type* = - nullptr) - : internal::MatcherBase(impl) {} - - // Implicit constructor here allows people to write - // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes - Matcher(T value); // NOLINT -}; - -// The following two specializations allow the user to write str -// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string -// matcher is expected. -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a std::string object. - Matcher(const std::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT -}; - -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a string object. - Matcher(const std::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT -}; - -#if GTEST_HAS_ABSL -// The following two specializations allow the user to write str -// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view -// matcher is expected. -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a std::string object. - Matcher(const std::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT - - // Allows the user to pass absl::string_views directly. - Matcher(absl::string_view s); // NOLINT -}; - -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a std::string object. - Matcher(const std::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT - - // Allows the user to pass absl::string_views directly. - Matcher(absl::string_view s); // NOLINT -}; -#endif // GTEST_HAS_ABSL - -// Prints a matcher in a human-readable format. -template -std::ostream& operator<<(std::ostream& os, const Matcher& matcher) { - matcher.DescribeTo(&os); - return os; -} - -// The PolymorphicMatcher class template makes it easy to implement a -// polymorphic matcher (i.e. a matcher that can match values of more -// than one type, e.g. Eq(n) and NotNull()). -// -// To define a polymorphic matcher, a user should provide an Impl -// class that has a DescribeTo() method and a DescribeNegationTo() -// method, and define a member function (or member function template) -// -// bool MatchAndExplain(const Value& value, -// MatchResultListener* listener) const; -// -// See the definition of NotNull() for a complete example. -template -class PolymorphicMatcher { - public: - explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {} - - // Returns a mutable reference to the underlying matcher - // implementation object. - Impl& mutable_impl() { return impl_; } - - // Returns an immutable reference to the underlying matcher - // implementation object. - const Impl& impl() const { return impl_; } - - template - operator Matcher() const { - return Matcher(new MonomorphicImpl(impl_)); - } - - private: - template - class MonomorphicImpl : public MatcherInterface { - public: - explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} - - virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); } - - virtual void DescribeNegationTo(::std::ostream* os) const { - impl_.DescribeNegationTo(os); - } - - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { - return impl_.MatchAndExplain(x, listener); - } - - private: - const Impl impl_; - }; - - Impl impl_; -}; - -// Creates a matcher from its implementation. -// DEPRECATED: Especially in the generic code, prefer: -// Matcher(new MyMatcherImpl(...)); -// -// MakeMatcher may create a Matcher that accepts its argument by value, which -// leads to unnecessary copies & lack of support for non-copyable types. -template -inline Matcher MakeMatcher(const MatcherInterface* impl) { - return Matcher(impl); -} - -// Creates a polymorphic matcher from its implementation. This is -// easier to use than the PolymorphicMatcher constructor as it -// doesn't require you to explicitly write the template argument, e.g. -// -// MakePolymorphicMatcher(foo); -// vs -// PolymorphicMatcher(foo); -template -inline PolymorphicMatcher MakePolymorphicMatcher(const Impl& impl) { - return PolymorphicMatcher(impl); -} - -namespace internal { -// Implements a matcher that compares a given value with a -// pre-supplied value using one of the ==, <=, <, etc, operators. The -// two values being compared don't have to have the same type. -// -// The matcher defined here is polymorphic (for example, Eq(5) can be -// used to match an int, a short, a double, etc). Therefore we use -// a template type conversion operator in the implementation. -// -// The following template definition assumes that the Rhs parameter is -// a "bare" type (i.e. neither 'const T' nor 'T&'). -template -class ComparisonBase { - public: - explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} - template - operator Matcher() const { - return Matcher(new Impl(rhs_)); - } - - private: - template - static const T& Unwrap(const T& v) { return v; } - template - static const T& Unwrap(std::reference_wrapper v) { return v; } - - template - class Impl : public MatcherInterface { - public: - explicit Impl(const Rhs& rhs) : rhs_(rhs) {} - bool MatchAndExplain(Lhs lhs, - MatchResultListener* /* listener */) const override { - return Op()(lhs, Unwrap(rhs_)); - } - void DescribeTo(::std::ostream* os) const override { - *os << D::Desc() << " "; - UniversalPrint(Unwrap(rhs_), os); - } - void DescribeNegationTo(::std::ostream* os) const override { - *os << D::NegatedDesc() << " "; - UniversalPrint(Unwrap(rhs_), os); - } - - private: - Rhs rhs_; - }; - Rhs rhs_; -}; - -template -class EqMatcher : public ComparisonBase, Rhs, AnyEq> { - public: - explicit EqMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyEq>(rhs) { } - static const char* Desc() { return "is equal to"; } - static const char* NegatedDesc() { return "isn't equal to"; } -}; -template -class NeMatcher : public ComparisonBase, Rhs, AnyNe> { - public: - explicit NeMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyNe>(rhs) { } - static const char* Desc() { return "isn't equal to"; } - static const char* NegatedDesc() { return "is equal to"; } -}; -template -class LtMatcher : public ComparisonBase, Rhs, AnyLt> { - public: - explicit LtMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyLt>(rhs) { } - static const char* Desc() { return "is <"; } - static const char* NegatedDesc() { return "isn't <"; } -}; -template -class GtMatcher : public ComparisonBase, Rhs, AnyGt> { - public: - explicit GtMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyGt>(rhs) { } - static const char* Desc() { return "is >"; } - static const char* NegatedDesc() { return "isn't >"; } -}; -template -class LeMatcher : public ComparisonBase, Rhs, AnyLe> { - public: - explicit LeMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyLe>(rhs) { } - static const char* Desc() { return "is <="; } - static const char* NegatedDesc() { return "isn't <="; } -}; -template -class GeMatcher : public ComparisonBase, Rhs, AnyGe> { - public: - explicit GeMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyGe>(rhs) { } - static const char* Desc() { return "is >="; } - static const char* NegatedDesc() { return "isn't >="; } -}; - -// Implements polymorphic matchers MatchesRegex(regex) and -// ContainsRegex(regex), which can be used as a Matcher as long as -// T can be converted to a string. -class MatchesRegexMatcher { - public: - MatchesRegexMatcher(const RE* regex, bool full_match) - : regex_(regex), full_match_(full_match) {} - -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, - MatchResultListener* listener) const { - return MatchAndExplain(std::string(s), listener); - } -#endif // GTEST_HAS_ABSL - - // Accepts pointer types, particularly: - // const char* - // char* - // const wchar_t* - // wchar_t* - template - bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { - return s != nullptr && MatchAndExplain(std::string(s), listener); - } - - // Matches anything that can convert to std::string. - // - // This is a template, not just a plain function with const std::string&, - // because absl::string_view has some interfering non-explicit constructors. - template - bool MatchAndExplain(const MatcheeStringType& s, - MatchResultListener* /* listener */) const { - const std::string& s2(s); - return full_match_ ? RE::FullMatch(s2, *regex_) - : RE::PartialMatch(s2, *regex_); - } - - void DescribeTo(::std::ostream* os) const { - *os << (full_match_ ? "matches" : "contains") << " regular expression "; - UniversalPrinter::Print(regex_->pattern(), os); - } - - void DescribeNegationTo(::std::ostream* os) const { - *os << "doesn't " << (full_match_ ? "match" : "contain") - << " regular expression "; - UniversalPrinter::Print(regex_->pattern(), os); - } - - private: - const std::shared_ptr regex_; - const bool full_match_; -}; -} // namespace internal - -// Matches a string that fully matches regular expression 'regex'. -// The matcher takes ownership of 'regex'. -inline PolymorphicMatcher MatchesRegex( - const internal::RE* regex) { - return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); -} -inline PolymorphicMatcher MatchesRegex( - const std::string& regex) { - return MatchesRegex(new internal::RE(regex)); -} - -// Matches a string that contains regular expression 'regex'. -// The matcher takes ownership of 'regex'. -inline PolymorphicMatcher ContainsRegex( - const internal::RE* regex) { - return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); -} -inline PolymorphicMatcher ContainsRegex( - const std::string& regex) { - return ContainsRegex(new internal::RE(regex)); -} - -// Creates a polymorphic matcher that matches anything equal to x. -// Note: if the parameter of Eq() were declared as const T&, Eq("foo") -// wouldn't compile. -template -inline internal::EqMatcher Eq(T x) { return internal::EqMatcher(x); } - -// Constructs a Matcher from a 'value' of type T. The constructed -// matcher matches any value that's equal to 'value'. -template -Matcher::Matcher(T value) { *this = Eq(value); } - -// Creates a monomorphic matcher that matches anything with type Lhs -// and equal to rhs. A user may need to use this instead of Eq(...) -// in order to resolve an overloading ambiguity. -// -// TypedEq(x) is just a convenient short-hand for Matcher(Eq(x)) -// or Matcher(x), but more readable than the latter. -// -// We could define similar monomorphic matchers for other comparison -// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do -// it yet as those are used much less than Eq() in practice. A user -// can always write Matcher(Lt(5)) to be explicit about the type, -// for example. -template -inline Matcher TypedEq(const Rhs& rhs) { return Eq(rhs); } - -// Creates a polymorphic matcher that matches anything >= x. -template -inline internal::GeMatcher Ge(Rhs x) { - return internal::GeMatcher(x); -} - -// Creates a polymorphic matcher that matches anything > x. -template -inline internal::GtMatcher Gt(Rhs x) { - return internal::GtMatcher(x); -} - -// Creates a polymorphic matcher that matches anything <= x. -template -inline internal::LeMatcher Le(Rhs x) { - return internal::LeMatcher(x); -} - -// Creates a polymorphic matcher that matches anything < x. -template -inline internal::LtMatcher Lt(Rhs x) { - return internal::LtMatcher(x); -} - -// Creates a polymorphic matcher that matches anything != x. -template -inline internal::NeMatcher Ne(Rhs x) { - return internal::NeMatcher(x); -} -} // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 - -#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-message.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-message.h deleted file mode 100644 index 4a80e11e6b2..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-message.h +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file defines the Message class. -// -// IMPORTANT NOTE: Due to limitation of the C++ language, we have to -// leave some internal implementation details in this header file. -// They are clearly marked by comments like this: -// -// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -// -// Such code is NOT meant to be used by a user directly, and is subject -// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user -// program! - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ -#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ - -#include -#include - -#include "gtest/internal/gtest-port.h" - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -// Ensures that there is at least one operator<< in the global namespace. -// See Message& operator<<(...) below for why. -void operator<<(const testing::internal::Secret&, int); - -namespace testing { - -// The Message class works like an ostream repeater. -// -// Typical usage: -// -// 1. You stream a bunch of values to a Message object. -// It will remember the text in a stringstream. -// 2. Then you stream the Message object to an ostream. -// This causes the text in the Message to be streamed -// to the ostream. -// -// For example; -// -// testing::Message foo; -// foo << 1 << " != " << 2; -// std::cout << foo; -// -// will print "1 != 2". -// -// Message is not intended to be inherited from. In particular, its -// destructor is not virtual. -// -// Note that stringstream behaves differently in gcc and in MSVC. You -// can stream a NULL char pointer to it in the former, but not in the -// latter (it causes an access violation if you do). The Message -// class hides this difference by treating a NULL char pointer as -// "(null)". -class GTEST_API_ Message { - private: - // The type of basic IO manipulators (endl, ends, and flush) for - // narrow streams. - typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); - - public: - // Constructs an empty Message. - Message(); - - // Copy constructor. - Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT - *ss_ << msg.GetString(); - } - - // Constructs a Message from a C-string. - explicit Message(const char* str) : ss_(new ::std::stringstream) { - *ss_ << str; - } - - // Streams a non-pointer value to this object. - template - inline Message& operator <<(const T& val) { - // Some libraries overload << for STL containers. These - // overloads are defined in the global namespace instead of ::std. - // - // C++'s symbol lookup rule (i.e. Koenig lookup) says that these - // overloads are visible in either the std namespace or the global - // namespace, but not other namespaces, including the testing - // namespace which Google Test's Message class is in. - // - // To allow STL containers (and other types that has a << operator - // defined in the global namespace) to be used in Google Test - // assertions, testing::Message must access the custom << operator - // from the global namespace. With this using declaration, - // overloads of << defined in the global namespace and those - // visible via Koenig lookup are both exposed in this function. - using ::operator <<; - *ss_ << val; - return *this; - } - - // Streams a pointer value to this object. - // - // This function is an overload of the previous one. When you - // stream a pointer to a Message, this definition will be used as it - // is more specialized. (The C++ Standard, section - // [temp.func.order].) If you stream a non-pointer, then the - // previous definition will be used. - // - // The reason for this overload is that streaming a NULL pointer to - // ostream is undefined behavior. Depending on the compiler, you - // may get "0", "(nil)", "(null)", or an access violation. To - // ensure consistent result across compilers, we always treat NULL - // as "(null)". - template - inline Message& operator <<(T* const& pointer) { // NOLINT - if (pointer == nullptr) { - *ss_ << "(null)"; - } else { - *ss_ << pointer; - } - return *this; - } - - // Since the basic IO manipulators are overloaded for both narrow - // and wide streams, we have to provide this specialized definition - // of operator <<, even though its body is the same as the - // templatized version above. Without this definition, streaming - // endl or other basic IO manipulators to Message will confuse the - // compiler. - Message& operator <<(BasicNarrowIoManip val) { - *ss_ << val; - return *this; - } - - // Instead of 1/0, we want to see true/false for bool values. - Message& operator <<(bool b) { - return *this << (b ? "true" : "false"); - } - - // These two overloads allow streaming a wide C string to a Message - // using the UTF-8 encoding. - Message& operator <<(const wchar_t* wide_c_str); - Message& operator <<(wchar_t* wide_c_str); - -#if GTEST_HAS_STD_WSTRING - // Converts the given wide string to a narrow string using the UTF-8 - // encoding, and streams the result to this Message object. - Message& operator <<(const ::std::wstring& wstr); -#endif // GTEST_HAS_STD_WSTRING - - // Gets the text streamed to this object so far as an std::string. - // Each '\0' character in the buffer is replaced with "\\0". - // - // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - std::string GetString() const; - - private: - // We'll hold the text streamed to this object here. - const std::unique_ptr< ::std::stringstream> ss_; - - // We declare (but don't implement) this to prevent the compiler - // from implementing the assignment operator. - void operator=(const Message&); -}; - -// Streams a Message to an ostream. -inline std::ostream& operator <<(std::ostream& os, const Message& sb) { - return os << sb.GetString(); -} - -namespace internal { - -// Converts a streamable value to an std::string. A NULL pointer is -// converted to "(null)". When the input value is a ::string, -// ::std::string, ::wstring, or ::std::wstring object, each NUL -// character in it is replaced with "\\0". -template -std::string StreamableToString(const T& streamable) { - return (Message() << streamable).GetString(); -} - -} // namespace internal -} // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-param-test.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-param-test.h deleted file mode 100644 index c2e6eae3d83..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-param-test.h +++ /dev/null @@ -1,503 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// Macros and functions for implementing parameterized tests -// in Google C++ Testing and Mocking Framework (Google Test) -// -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ - - -// Value-parameterized tests allow you to test your code with different -// parameters without writing multiple copies of the same test. -// -// Here is how you use value-parameterized tests: - -#if 0 - -// To write value-parameterized tests, first you should define a fixture -// class. It is usually derived from testing::TestWithParam (see below for -// another inheritance scheme that's sometimes useful in more complicated -// class hierarchies), where the type of your parameter values. -// TestWithParam is itself derived from testing::Test. T can be any -// copyable type. If it's a raw pointer, you are responsible for managing the -// lifespan of the pointed values. - -class FooTest : public ::testing::TestWithParam { - // You can implement all the usual class fixture members here. -}; - -// Then, use the TEST_P macro to define as many parameterized tests -// for this fixture as you want. The _P suffix is for "parameterized" -// or "pattern", whichever you prefer to think. - -TEST_P(FooTest, DoesBlah) { - // Inside a test, access the test parameter with the GetParam() method - // of the TestWithParam class: - EXPECT_TRUE(foo.Blah(GetParam())); - ... -} - -TEST_P(FooTest, HasBlahBlah) { - ... -} - -// Finally, you can use INSTANTIATE_TEST_SUITE_P to instantiate the test -// case with any set of parameters you want. Google Test defines a number -// of functions for generating test parameters. They return what we call -// (surprise!) parameter generators. Here is a summary of them, which -// are all in the testing namespace: -// -// -// Range(begin, end [, step]) - Yields values {begin, begin+step, -// begin+step+step, ...}. The values do not -// include end. step defaults to 1. -// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. -// ValuesIn(container) - Yields values from a C-style array, an STL -// ValuesIn(begin,end) container, or an iterator range [begin, end). -// Bool() - Yields sequence {false, true}. -// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product -// for the math savvy) of the values generated -// by the N generators. -// -// For more details, see comments at the definitions of these functions below -// in this file. -// -// The following statement will instantiate tests from the FooTest test suite -// each with parameter values "meeny", "miny", and "moe". - -INSTANTIATE_TEST_SUITE_P(InstantiationName, - FooTest, - Values("meeny", "miny", "moe")); - -// To distinguish different instances of the pattern, (yes, you -// can instantiate it more than once) the first argument to the -// INSTANTIATE_TEST_SUITE_P macro is a prefix that will be added to the -// actual test suite name. Remember to pick unique prefixes for different -// instantiations. The tests from the instantiation above will have -// these names: -// -// * InstantiationName/FooTest.DoesBlah/0 for "meeny" -// * InstantiationName/FooTest.DoesBlah/1 for "miny" -// * InstantiationName/FooTest.DoesBlah/2 for "moe" -// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" -// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" -// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" -// -// You can use these names in --gtest_filter. -// -// This statement will instantiate all tests from FooTest again, each -// with parameter values "cat" and "dog": - -const char* pets[] = {"cat", "dog"}; -INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); - -// The tests from the instantiation above will have these names: -// -// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" -// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" -// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" -// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" -// -// Please note that INSTANTIATE_TEST_SUITE_P will instantiate all tests -// in the given test suite, whether their definitions come before or -// AFTER the INSTANTIATE_TEST_SUITE_P statement. -// -// Please also note that generator expressions (including parameters to the -// generators) are evaluated in InitGoogleTest(), after main() has started. -// This allows the user on one hand, to adjust generator parameters in order -// to dynamically determine a set of tests to run and on the other hand, -// give the user a chance to inspect the generated tests with Google Test -// reflection API before RUN_ALL_TESTS() is executed. -// -// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc -// for more examples. -// -// In the future, we plan to publish the API for defining new parameter -// generators. But for now this interface remains part of the internal -// implementation and is subject to change. -// -// -// A parameterized test fixture must be derived from testing::Test and from -// testing::WithParamInterface, where T is the type of the parameter -// values. Inheriting from TestWithParam satisfies that requirement because -// TestWithParam inherits from both Test and WithParamInterface. In more -// complicated hierarchies, however, it is occasionally useful to inherit -// separately from Test and WithParamInterface. For example: - -class BaseTest : public ::testing::Test { - // You can inherit all the usual members for a non-parameterized test - // fixture here. -}; - -class DerivedTest : public BaseTest, public ::testing::WithParamInterface { - // The usual test fixture members go here too. -}; - -TEST_F(BaseTest, HasFoo) { - // This is an ordinary non-parameterized test. -} - -TEST_P(DerivedTest, DoesBlah) { - // GetParam works just the same here as if you inherit from TestWithParam. - EXPECT_TRUE(foo.Blah(GetParam())); -} - -#endif // 0 - -#include -#include - -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-port.h" - -namespace testing { - -// Functions producing parameter generators. -// -// Google Test uses these generators to produce parameters for value- -// parameterized tests. When a parameterized test suite is instantiated -// with a particular generator, Google Test creates and runs tests -// for each element in the sequence produced by the generator. -// -// In the following sample, tests from test suite FooTest are instantiated -// each three times with parameter values 3, 5, and 8: -// -// class FooTest : public TestWithParam { ... }; -// -// TEST_P(FooTest, TestThis) { -// } -// TEST_P(FooTest, TestThat) { -// } -// INSTANTIATE_TEST_SUITE_P(TestSequence, FooTest, Values(3, 5, 8)); -// - -// Range() returns generators providing sequences of values in a range. -// -// Synopsis: -// Range(start, end) -// - returns a generator producing a sequence of values {start, start+1, -// start+2, ..., }. -// Range(start, end, step) -// - returns a generator producing a sequence of values {start, start+step, -// start+step+step, ..., }. -// Notes: -// * The generated sequences never include end. For example, Range(1, 5) -// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) -// returns a generator producing {1, 3, 5, 7}. -// * start and end must have the same type. That type may be any integral or -// floating-point type or a user defined type satisfying these conditions: -// * It must be assignable (have operator=() defined). -// * It must have operator+() (operator+(int-compatible type) for -// two-operand version). -// * It must have operator<() defined. -// Elements in the resulting sequences will also have that type. -// * Condition start < end must be satisfied in order for resulting sequences -// to contain any elements. -// -template -internal::ParamGenerator Range(T start, T end, IncrementT step) { - return internal::ParamGenerator( - new internal::RangeGenerator(start, end, step)); -} - -template -internal::ParamGenerator Range(T start, T end) { - return Range(start, end, 1); -} - -// ValuesIn() function allows generation of tests with parameters coming from -// a container. -// -// Synopsis: -// ValuesIn(const T (&array)[N]) -// - returns a generator producing sequences with elements from -// a C-style array. -// ValuesIn(const Container& container) -// - returns a generator producing sequences with elements from -// an STL-style container. -// ValuesIn(Iterator begin, Iterator end) -// - returns a generator producing sequences with elements from -// a range [begin, end) defined by a pair of STL-style iterators. These -// iterators can also be plain C pointers. -// -// Please note that ValuesIn copies the values from the containers -// passed in and keeps them to generate tests in RUN_ALL_TESTS(). -// -// Examples: -// -// This instantiates tests from test suite StringTest -// each with C-string values of "foo", "bar", and "baz": -// -// const char* strings[] = {"foo", "bar", "baz"}; -// INSTANTIATE_TEST_SUITE_P(StringSequence, StringTest, ValuesIn(strings)); -// -// This instantiates tests from test suite StlStringTest -// each with STL strings with values "a" and "b": -// -// ::std::vector< ::std::string> GetParameterStrings() { -// ::std::vector< ::std::string> v; -// v.push_back("a"); -// v.push_back("b"); -// return v; -// } -// -// INSTANTIATE_TEST_SUITE_P(CharSequence, -// StlStringTest, -// ValuesIn(GetParameterStrings())); -// -// -// This will also instantiate tests from CharTest -// each with parameter values 'a' and 'b': -// -// ::std::list GetParameterChars() { -// ::std::list list; -// list.push_back('a'); -// list.push_back('b'); -// return list; -// } -// ::std::list l = GetParameterChars(); -// INSTANTIATE_TEST_SUITE_P(CharSequence2, -// CharTest, -// ValuesIn(l.begin(), l.end())); -// -template -internal::ParamGenerator< - typename std::iterator_traits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end) { - typedef typename std::iterator_traits::value_type ParamType; - return internal::ParamGenerator( - new internal::ValuesInIteratorRangeGenerator(begin, end)); -} - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]) { - return ValuesIn(array, array + N); -} - -template -internal::ParamGenerator ValuesIn( - const Container& container) { - return ValuesIn(container.begin(), container.end()); -} - -// Values() allows generating tests from explicitly specified list of -// parameters. -// -// Synopsis: -// Values(T v1, T v2, ..., T vN) -// - returns a generator producing sequences with elements v1, v2, ..., vN. -// -// For example, this instantiates tests from test suite BarTest each -// with values "one", "two", and "three": -// -// INSTANTIATE_TEST_SUITE_P(NumSequence, -// BarTest, -// Values("one", "two", "three")); -// -// This instantiates tests from test suite BazTest each with values 1, 2, 3.5. -// The exact type of values will depend on the type of parameter in BazTest. -// -// INSTANTIATE_TEST_SUITE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); -// -// -template -internal::ValueArray Values(T... v) { - return internal::ValueArray(std::move(v)...); -} - -// Bool() allows generating tests with parameters in a set of (false, true). -// -// Synopsis: -// Bool() -// - returns a generator producing sequences with elements {false, true}. -// -// It is useful when testing code that depends on Boolean flags. Combinations -// of multiple flags can be tested when several Bool()'s are combined using -// Combine() function. -// -// In the following example all tests in the test suite FlagDependentTest -// will be instantiated twice with parameters false and true. -// -// class FlagDependentTest : public testing::TestWithParam { -// virtual void SetUp() { -// external_flag = GetParam(); -// } -// } -// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool()); -// -inline internal::ParamGenerator Bool() { - return Values(false, true); -} - -// Combine() allows the user to combine two or more sequences to produce -// values of a Cartesian product of those sequences' elements. -// -// Synopsis: -// Combine(gen1, gen2, ..., genN) -// - returns a generator producing sequences with elements coming from -// the Cartesian product of elements from the sequences generated by -// gen1, gen2, ..., genN. The sequence elements will have a type of -// std::tuple where T1, T2, ..., TN are the types -// of elements from sequences produces by gen1, gen2, ..., genN. -// -// Combine can have up to 10 arguments. -// -// Example: -// -// This will instantiate tests in test suite AnimalTest each one with -// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), -// tuple("dog", BLACK), and tuple("dog", WHITE): -// -// enum Color { BLACK, GRAY, WHITE }; -// class AnimalTest -// : public testing::TestWithParam > {...}; -// -// TEST_P(AnimalTest, AnimalLooksNice) {...} -// -// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest, -// Combine(Values("cat", "dog"), -// Values(BLACK, WHITE))); -// -// This will instantiate tests in FlagDependentTest with all variations of two -// Boolean flags: -// -// class FlagDependentTest -// : public testing::TestWithParam > { -// virtual void SetUp() { -// // Assigns external_flag_1 and external_flag_2 values from the tuple. -// std::tie(external_flag_1, external_flag_2) = GetParam(); -// } -// }; -// -// TEST_P(FlagDependentTest, TestFeature1) { -// // Test your code using external_flag_1 and external_flag_2 here. -// } -// INSTANTIATE_TEST_SUITE_P(TwoBoolSequence, FlagDependentTest, -// Combine(Bool(), Bool())); -// -template -internal::CartesianProductHolder Combine(const Generator&... g) { - return internal::CartesianProductHolder(g...); -} - -#define TEST_P(test_suite_name, test_name) \ - class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ - : public test_suite_name { \ - public: \ - GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ - virtual void TestBody(); \ - \ - private: \ - static int AddToRegistry() { \ - ::testing::UnitTest::GetInstance() \ - ->parameterized_test_registry() \ - .GetTestSuitePatternHolder( \ - #test_suite_name, \ - ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ - ->AddTestPattern( \ - GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \ - new ::testing::internal::TestMetaFactory()); \ - return 0; \ - } \ - static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ - test_name)); \ - }; \ - int GTEST_TEST_CLASS_NAME_(test_suite_name, \ - test_name)::gtest_registering_dummy_ = \ - GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry(); \ - void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() - -// The last argument to INSTANTIATE_TEST_SUITE_P allows the user to specify -// generator and an optional function or functor that generates custom test name -// suffixes based on the test parameters. Such a function or functor should -// accept one argument of type testing::TestParamInfo, and -// return std::string. -// -// testing::PrintToStringParamName is a builtin test suffix generator that -// returns the value of testing::PrintToString(GetParam()). -// -// Note: test names must be non-empty, unique, and may only contain ASCII -// alphanumeric characters or underscore. Because PrintToString adds quotes -// to std::string and C strings, it won't work for these types. - -#define GTEST_EXPAND_(arg) arg -#define GTEST_GET_FIRST_(first, ...) first -#define GTEST_GET_SECOND_(first, second, ...) second - -#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \ - static ::testing::internal::ParamGenerator \ - gtest_##prefix##test_suite_name##_EvalGenerator_() { \ - return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \ - } \ - static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \ - const ::testing::TestParamInfo& info) { \ - if (::testing::internal::AlwaysFalse()) { \ - ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \ - __VA_ARGS__, \ - ::testing::internal::DefaultParamName, \ - DUMMY_PARAM_))); \ - auto t = std::make_tuple(__VA_ARGS__); \ - static_assert(std::tuple_size::value <= 2, \ - "Too Many Args!"); \ - } \ - return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \ - __VA_ARGS__, \ - ::testing::internal::DefaultParamName, \ - DUMMY_PARAM_))))(info); \ - } \ - static int gtest_##prefix##test_suite_name##_dummy_ \ - GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::UnitTest::GetInstance() \ - ->parameterized_test_registry() \ - .GetTestSuitePatternHolder( \ - #test_suite_name, \ - ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ - ->AddTestSuiteInstantiation( \ - #prefix, >est_##prefix##test_suite_name##_EvalGenerator_, \ - >est_##prefix##test_suite_name##_EvalGenerateName_, \ - __FILE__, __LINE__) - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#define INSTANTIATE_TEST_CASE_P \ - static_assert(::testing::internal::InstantiateTestCase_P_IsDeprecated(), \ - ""); \ - INSTANTIATE_TEST_SUITE_P -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-param-test.h.pump b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-param-test.h.pump deleted file mode 100644 index 274f2b3b569..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-param-test.h.pump +++ /dev/null @@ -1,500 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 50 $$ Maximum length of Values arguments we want to support. -$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// Macros and functions for implementing parameterized tests -// in Google C++ Testing and Mocking Framework (Google Test) -// -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ - - -// Value-parameterized tests allow you to test your code with different -// parameters without writing multiple copies of the same test. -// -// Here is how you use value-parameterized tests: - -#if 0 - -// To write value-parameterized tests, first you should define a fixture -// class. It is usually derived from testing::TestWithParam (see below for -// another inheritance scheme that's sometimes useful in more complicated -// class hierarchies), where the type of your parameter values. -// TestWithParam is itself derived from testing::Test. T can be any -// copyable type. If it's a raw pointer, you are responsible for managing the -// lifespan of the pointed values. - -class FooTest : public ::testing::TestWithParam { - // You can implement all the usual class fixture members here. -}; - -// Then, use the TEST_P macro to define as many parameterized tests -// for this fixture as you want. The _P suffix is for "parameterized" -// or "pattern", whichever you prefer to think. - -TEST_P(FooTest, DoesBlah) { - // Inside a test, access the test parameter with the GetParam() method - // of the TestWithParam class: - EXPECT_TRUE(foo.Blah(GetParam())); - ... -} - -TEST_P(FooTest, HasBlahBlah) { - ... -} - -// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test -// case with any set of parameters you want. Google Test defines a number -// of functions for generating test parameters. They return what we call -// (surprise!) parameter generators. Here is a summary of them, which -// are all in the testing namespace: -// -// -// Range(begin, end [, step]) - Yields values {begin, begin+step, -// begin+step+step, ...}. The values do not -// include end. step defaults to 1. -// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. -// ValuesIn(container) - Yields values from a C-style array, an STL -// ValuesIn(begin,end) container, or an iterator range [begin, end). -// Bool() - Yields sequence {false, true}. -// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product -// for the math savvy) of the values generated -// by the N generators. -// -// For more details, see comments at the definitions of these functions below -// in this file. -// -// The following statement will instantiate tests from the FooTest test case -// each with parameter values "meeny", "miny", and "moe". - -INSTANTIATE_TEST_CASE_P(InstantiationName, - FooTest, - Values("meeny", "miny", "moe")); - -// To distinguish different instances of the pattern, (yes, you -// can instantiate it more then once) the first argument to the -// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the -// actual test case name. Remember to pick unique prefixes for different -// instantiations. The tests from the instantiation above will have -// these names: -// -// * InstantiationName/FooTest.DoesBlah/0 for "meeny" -// * InstantiationName/FooTest.DoesBlah/1 for "miny" -// * InstantiationName/FooTest.DoesBlah/2 for "moe" -// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" -// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" -// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" -// -// You can use these names in --gtest_filter. -// -// This statement will instantiate all tests from FooTest again, each -// with parameter values "cat" and "dog": - -const char* pets[] = {"cat", "dog"}; -INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); - -// The tests from the instantiation above will have these names: -// -// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" -// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" -// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" -// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" -// -// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests -// in the given test case, whether their definitions come before or -// AFTER the INSTANTIATE_TEST_CASE_P statement. -// -// Please also note that generator expressions (including parameters to the -// generators) are evaluated in InitGoogleTest(), after main() has started. -// This allows the user on one hand, to adjust generator parameters in order -// to dynamically determine a set of tests to run and on the other hand, -// give the user a chance to inspect the generated tests with Google Test -// reflection API before RUN_ALL_TESTS() is executed. -// -// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc -// for more examples. -// -// In the future, we plan to publish the API for defining new parameter -// generators. But for now this interface remains part of the internal -// implementation and is subject to change. -// -// -// A parameterized test fixture must be derived from testing::Test and from -// testing::WithParamInterface, where T is the type of the parameter -// values. Inheriting from TestWithParam satisfies that requirement because -// TestWithParam inherits from both Test and WithParamInterface. In more -// complicated hierarchies, however, it is occasionally useful to inherit -// separately from Test and WithParamInterface. For example: - -class BaseTest : public ::testing::Test { - // You can inherit all the usual members for a non-parameterized test - // fixture here. -}; - -class DerivedTest : public BaseTest, public ::testing::WithParamInterface { - // The usual test fixture members go here too. -}; - -TEST_F(BaseTest, HasFoo) { - // This is an ordinary non-parameterized test. -} - -TEST_P(DerivedTest, DoesBlah) { - // GetParam works just the same here as if you inherit from TestWithParam. - EXPECT_TRUE(foo.Blah(GetParam())); -} - -#endif // 0 - -#include "gtest/internal/gtest-port.h" - -#if !GTEST_OS_SYMBIAN -# include -#endif - -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-param-util-generated.h" - -namespace testing { - -// Functions producing parameter generators. -// -// Google Test uses these generators to produce parameters for value- -// parameterized tests. When a parameterized test case is instantiated -// with a particular generator, Google Test creates and runs tests -// for each element in the sequence produced by the generator. -// -// In the following sample, tests from test case FooTest are instantiated -// each three times with parameter values 3, 5, and 8: -// -// class FooTest : public TestWithParam { ... }; -// -// TEST_P(FooTest, TestThis) { -// } -// TEST_P(FooTest, TestThat) { -// } -// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); -// - -// Range() returns generators providing sequences of values in a range. -// -// Synopsis: -// Range(start, end) -// - returns a generator producing a sequence of values {start, start+1, -// start+2, ..., }. -// Range(start, end, step) -// - returns a generator producing a sequence of values {start, start+step, -// start+step+step, ..., }. -// Notes: -// * The generated sequences never include end. For example, Range(1, 5) -// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) -// returns a generator producing {1, 3, 5, 7}. -// * start and end must have the same type. That type may be any integral or -// floating-point type or a user defined type satisfying these conditions: -// * It must be assignable (have operator=() defined). -// * It must have operator+() (operator+(int-compatible type) for -// two-operand version). -// * It must have operator<() defined. -// Elements in the resulting sequences will also have that type. -// * Condition start < end must be satisfied in order for resulting sequences -// to contain any elements. -// -template -internal::ParamGenerator Range(T start, T end, IncrementT step) { - return internal::ParamGenerator( - new internal::RangeGenerator(start, end, step)); -} - -template -internal::ParamGenerator Range(T start, T end) { - return Range(start, end, 1); -} - -// ValuesIn() function allows generation of tests with parameters coming from -// a container. -// -// Synopsis: -// ValuesIn(const T (&array)[N]) -// - returns a generator producing sequences with elements from -// a C-style array. -// ValuesIn(const Container& container) -// - returns a generator producing sequences with elements from -// an STL-style container. -// ValuesIn(Iterator begin, Iterator end) -// - returns a generator producing sequences with elements from -// a range [begin, end) defined by a pair of STL-style iterators. These -// iterators can also be plain C pointers. -// -// Please note that ValuesIn copies the values from the containers -// passed in and keeps them to generate tests in RUN_ALL_TESTS(). -// -// Examples: -// -// This instantiates tests from test case StringTest -// each with C-string values of "foo", "bar", and "baz": -// -// const char* strings[] = {"foo", "bar", "baz"}; -// INSTANTIATE_TEST_CASE_P(StringSequence, StringTest, ValuesIn(strings)); -// -// This instantiates tests from test case StlStringTest -// each with STL strings with values "a" and "b": -// -// ::std::vector< ::std::string> GetParameterStrings() { -// ::std::vector< ::std::string> v; -// v.push_back("a"); -// v.push_back("b"); -// return v; -// } -// -// INSTANTIATE_TEST_CASE_P(CharSequence, -// StlStringTest, -// ValuesIn(GetParameterStrings())); -// -// -// This will also instantiate tests from CharTest -// each with parameter values 'a' and 'b': -// -// ::std::list GetParameterChars() { -// ::std::list list; -// list.push_back('a'); -// list.push_back('b'); -// return list; -// } -// ::std::list l = GetParameterChars(); -// INSTANTIATE_TEST_CASE_P(CharSequence2, -// CharTest, -// ValuesIn(l.begin(), l.end())); -// -template -internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end) { - typedef typename ::testing::internal::IteratorTraits - ::value_type ParamType; - return internal::ParamGenerator( - new internal::ValuesInIteratorRangeGenerator(begin, end)); -} - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]) { - return ValuesIn(array, array + N); -} - -template -internal::ParamGenerator ValuesIn( - const Container& container) { - return ValuesIn(container.begin(), container.end()); -} - -// Values() allows generating tests from explicitly specified list of -// parameters. -// -// Synopsis: -// Values(T v1, T v2, ..., T vN) -// - returns a generator producing sequences with elements v1, v2, ..., vN. -// -// For example, this instantiates tests from test case BarTest each -// with values "one", "two", and "three": -// -// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); -// -// This instantiates tests from test case BazTest each with values 1, 2, 3.5. -// The exact type of values will depend on the type of parameter in BazTest. -// -// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); -// -// Currently, Values() supports from 1 to $n parameters. -// -$range i 1..n -$for i [[ -$range j 1..i - -template <$for j, [[typename T$j]]> -internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) { - return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]); -} - -]] - -// Bool() allows generating tests with parameters in a set of (false, true). -// -// Synopsis: -// Bool() -// - returns a generator producing sequences with elements {false, true}. -// -// It is useful when testing code that depends on Boolean flags. Combinations -// of multiple flags can be tested when several Bool()'s are combined using -// Combine() function. -// -// In the following example all tests in the test case FlagDependentTest -// will be instantiated twice with parameters false and true. -// -// class FlagDependentTest : public testing::TestWithParam { -// virtual void SetUp() { -// external_flag = GetParam(); -// } -// } -// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); -// -inline internal::ParamGenerator Bool() { - return Values(false, true); -} - -# if GTEST_HAS_COMBINE -// Combine() allows the user to combine two or more sequences to produce -// values of a Cartesian product of those sequences' elements. -// -// Synopsis: -// Combine(gen1, gen2, ..., genN) -// - returns a generator producing sequences with elements coming from -// the Cartesian product of elements from the sequences generated by -// gen1, gen2, ..., genN. The sequence elements will have a type of -// tuple where T1, T2, ..., TN are the types -// of elements from sequences produces by gen1, gen2, ..., genN. -// -// Combine can have up to $maxtuple arguments. This number is currently limited -// by the maximum number of elements in the tuple implementation used by Google -// Test. -// -// Example: -// -// This will instantiate tests in test case AnimalTest each one with -// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), -// tuple("dog", BLACK), and tuple("dog", WHITE): -// -// enum Color { BLACK, GRAY, WHITE }; -// class AnimalTest -// : public testing::TestWithParam > {...}; -// -// TEST_P(AnimalTest, AnimalLooksNice) {...} -// -// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, -// Combine(Values("cat", "dog"), -// Values(BLACK, WHITE))); -// -// This will instantiate tests in FlagDependentTest with all variations of two -// Boolean flags: -// -// class FlagDependentTest -// : public testing::TestWithParam > { -// virtual void SetUp() { -// // Assigns external_flag_1 and external_flag_2 values from the tuple. -// tie(external_flag_1, external_flag_2) = GetParam(); -// } -// }; -// -// TEST_P(FlagDependentTest, TestFeature1) { -// // Test your code using external_flag_1 and external_flag_2 here. -// } -// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, -// Combine(Bool(), Bool())); -// -$range i 2..maxtuple -$for i [[ -$range j 1..i - -template <$for j, [[typename Generator$j]]> -internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine( - $for j, [[const Generator$j& g$j]]) { - return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>( - $for j, [[g$j]]); -} - -]] -# endif // GTEST_HAS_COMBINE - -# define TEST_P(test_case_name, test_name) \ - class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ - : public test_case_name { \ - public: \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ - virtual void TestBody(); \ - private: \ - static int AddToRegistry() { \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, \ - ::testing::internal::CodeLocation(\ - __FILE__, __LINE__))->AddTestPattern(\ - GTEST_STRINGIFY_(test_case_name), \ - GTEST_STRINGIFY_(test_name), \ - new ::testing::internal::TestMetaFactory< \ - GTEST_TEST_CLASS_NAME_(\ - test_case_name, test_name)>()); \ - return 0; \ - } \ - static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ - }; \ - int GTEST_TEST_CLASS_NAME_(test_case_name, \ - test_name)::gtest_registering_dummy_ = \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ - void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() - -// The optional last argument to INSTANTIATE_TEST_CASE_P allows the user -// to specify a function or functor that generates custom test name suffixes -// based on the test parameters. The function should accept one argument of -// type testing::TestParamInfo, and return std::string. -// -// testing::PrintToStringParamName is a builtin test suffix generator that -// returns the value of testing::PrintToString(GetParam()). -// -// Note: test names must be non-empty, unique, and may only contain ASCII -// alphanumeric characters or underscore. Because PrintToString adds quotes -// to std::string and C strings, it won't work for these types. - -# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \ - static ::testing::internal::ParamGenerator \ - gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ - static ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \ - const ::testing::TestParamInfo& info) { \ - return ::testing::internal::GetParamNameGen \ - (__VA_ARGS__)(info); \ - } \ - static int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, \ - ::testing::internal::CodeLocation(\ - __FILE__, __LINE__))->AddTestCaseInstantiation(\ - #prefix, \ - >est_##prefix##test_case_name##_EvalGenerator_, \ - >est_##prefix##test_case_name##_EvalGenerateName_, \ - __FILE__, __LINE__) - -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-printers.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-printers.h deleted file mode 100644 index 56a05450ef5..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-printers.h +++ /dev/null @@ -1,928 +0,0 @@ -// Copyright 2007, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Google Test - The Google C++ Testing and Mocking Framework -// -// This file implements a universal value printer that can print a -// value of any type T: -// -// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); -// -// A user can teach this function how to print a class type T by -// defining either operator<<() or PrintTo() in the namespace that -// defines T. More specifically, the FIRST defined function in the -// following list will be used (assuming T is defined in namespace -// foo): -// -// 1. foo::PrintTo(const T&, ostream*) -// 2. operator<<(ostream&, const T&) defined in either foo or the -// global namespace. -// -// However if T is an STL-style container then it is printed element-wise -// unless foo::PrintTo(const T&, ostream*) is defined. Note that -// operator<<() is ignored for container types. -// -// If none of the above is defined, it will print the debug string of -// the value if it is a protocol buffer, or print the raw bytes in the -// value otherwise. -// -// To aid debugging: when T is a reference type, the address of the -// value is also printed; when T is a (const) char pointer, both the -// pointer value and the NUL-terminated string it points to are -// printed. -// -// We also provide some convenient wrappers: -// -// // Prints a value to a string. For a (const or not) char -// // pointer, the NUL-terminated string (but not the pointer) is -// // printed. -// std::string ::testing::PrintToString(const T& value); -// -// // Prints a value tersely: for a reference type, the referenced -// // value (but not the address) is printed; for a (const or not) char -// // pointer, the NUL-terminated string (but not the pointer) is -// // printed. -// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); -// -// // Prints value using the type inferred by the compiler. The difference -// // from UniversalTersePrint() is that this function prints both the -// // pointer and the NUL-terminated string for a (const or not) char pointer. -// void ::testing::internal::UniversalPrint(const T& value, ostream*); -// -// // Prints the fields of a tuple tersely to a string vector, one -// // element for each field. Tuple support must be enabled in -// // gtest-port.h. -// std::vector UniversalTersePrintTupleFieldsToStrings( -// const Tuple& value); -// -// Known limitation: -// -// The print primitives print the elements of an STL-style container -// using the compiler-inferred type of *iter where iter is a -// const_iterator of the container. When const_iterator is an input -// iterator but not a forward iterator, this inferred type may not -// match value_type, and the print output may be incorrect. In -// practice, this is rarely a problem as for most containers -// const_iterator is a forward iterator. We'll fix this if there's an -// actual need for it. Note that this fix cannot rely on value_type -// being defined as many user-defined container types don't have -// value_type. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ - -#include -#include // NOLINT -#include -#include -#include -#include -#include -#include -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-port.h" - -#if GTEST_HAS_ABSL -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" -#include "absl/types/variant.h" -#endif // GTEST_HAS_ABSL - -namespace testing { - -// Definitions in the 'internal' and 'internal2' name spaces are -// subject to change without notice. DO NOT USE THEM IN USER CODE! -namespace internal2 { - -// Prints the given number of bytes in the given object to the given -// ostream. -GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, - size_t count, - ::std::ostream* os); - -// For selecting which printer to use when a given type has neither << -// nor PrintTo(). -enum TypeKind { - kProtobuf, // a protobuf type - kConvertibleToInteger, // a type implicitly convertible to BiggestInt - // (e.g. a named or unnamed enum type) -#if GTEST_HAS_ABSL - kConvertibleToStringView, // a type implicitly convertible to - // absl::string_view -#endif - kOtherType // anything else -}; - -// TypeWithoutFormatter::PrintValue(value, os) is called -// by the universal printer to print a value of type T when neither -// operator<< nor PrintTo() is defined for T, where kTypeKind is the -// "kind" of T as defined by enum TypeKind. -template -class TypeWithoutFormatter { - public: - // This default version is called when kTypeKind is kOtherType. - static void PrintValue(const T& value, ::std::ostream* os) { - PrintBytesInObjectTo( - static_cast( - reinterpret_cast(std::addressof(value))), - sizeof(value), os); - } -}; - -// We print a protobuf using its ShortDebugString() when the string -// doesn't exceed this many characters; otherwise we print it using -// DebugString() for better readability. -const size_t kProtobufOneLinerMaxLength = 50; - -template -class TypeWithoutFormatter { - public: - static void PrintValue(const T& value, ::std::ostream* os) { - std::string pretty_str = value.ShortDebugString(); - if (pretty_str.length() > kProtobufOneLinerMaxLength) { - pretty_str = "\n" + value.DebugString(); - } - *os << ("<" + pretty_str + ">"); - } -}; - -template -class TypeWithoutFormatter { - public: - // Since T has no << operator or PrintTo() but can be implicitly - // converted to BiggestInt, we print it as a BiggestInt. - // - // Most likely T is an enum type (either named or unnamed), in which - // case printing it as an integer is the desired behavior. In case - // T is not an enum, printing it as an integer is the best we can do - // given that it has no user-defined printer. - static void PrintValue(const T& value, ::std::ostream* os) { - const internal::BiggestInt kBigInt = value; - *os << kBigInt; - } -}; - -#if GTEST_HAS_ABSL -template -class TypeWithoutFormatter { - public: - // Since T has neither operator<< nor PrintTo() but can be implicitly - // converted to absl::string_view, we print it as a absl::string_view. - // - // Note: the implementation is further below, as it depends on - // internal::PrintTo symbol which is defined later in the file. - static void PrintValue(const T& value, ::std::ostream* os); -}; -#endif - -// Prints the given value to the given ostream. If the value is a -// protocol message, its debug string is printed; if it's an enum or -// of a type implicitly convertible to BiggestInt, it's printed as an -// integer; otherwise the bytes in the value are printed. This is -// what UniversalPrinter::Print() does when it knows nothing about -// type T and T has neither << operator nor PrintTo(). -// -// A user can override this behavior for a class type Foo by defining -// a << operator in the namespace where Foo is defined. -// -// We put this operator in namespace 'internal2' instead of 'internal' -// to simplify the implementation, as much code in 'internal' needs to -// use << in STL, which would conflict with our own << were it defined -// in 'internal'. -// -// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If -// we define it to take an std::ostream instead, we'll get an -// "ambiguous overloads" compiler error when trying to print a type -// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether -// operator<<(std::ostream&, const T&) or -// operator<<(std::basic_stream, const Foo&) is more -// specific. -template -::std::basic_ostream& operator<<( - ::std::basic_ostream& os, const T& x) { - TypeWithoutFormatter::value - ? kProtobuf - : std::is_convertible< - const T&, internal::BiggestInt>::value - ? kConvertibleToInteger - : -#if GTEST_HAS_ABSL - std::is_convertible< - const T&, absl::string_view>::value - ? kConvertibleToStringView - : -#endif - kOtherType)>::PrintValue(x, &os); - return os; -} - -} // namespace internal2 -} // namespace testing - -// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up -// magic needed for implementing UniversalPrinter won't work. -namespace testing_internal { - -// Used to print a value that is not an STL-style container when the -// user doesn't define PrintTo() for it. -template -void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { - // With the following statement, during unqualified name lookup, - // testing::internal2::operator<< appears as if it was declared in - // the nearest enclosing namespace that contains both - // ::testing_internal and ::testing::internal2, i.e. the global - // namespace. For more details, refer to the C++ Standard section - // 7.3.4-1 [namespace.udir]. This allows us to fall back onto - // testing::internal2::operator<< in case T doesn't come with a << - // operator. - // - // We cannot write 'using ::testing::internal2::operator<<;', which - // gcc 3.3 fails to compile due to a compiler bug. - using namespace ::testing::internal2; // NOLINT - - // Assuming T is defined in namespace foo, in the next statement, - // the compiler will consider all of: - // - // 1. foo::operator<< (thanks to Koenig look-up), - // 2. ::operator<< (as the current namespace is enclosed in ::), - // 3. testing::internal2::operator<< (thanks to the using statement above). - // - // The operator<< whose type matches T best will be picked. - // - // We deliberately allow #2 to be a candidate, as sometimes it's - // impossible to define #1 (e.g. when foo is ::std, defining - // anything in it is undefined behavior unless you are a compiler - // vendor.). - *os << value; -} - -} // namespace testing_internal - -namespace testing { -namespace internal { - -// FormatForComparison::Format(value) formats a -// value of type ToPrint that is an operand of a comparison assertion -// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in -// the comparison, and is used to help determine the best way to -// format the value. In particular, when the value is a C string -// (char pointer) and the other operand is an STL string object, we -// want to format the C string as a string, since we know it is -// compared by value with the string object. If the value is a char -// pointer but the other operand is not an STL string object, we don't -// know whether the pointer is supposed to point to a NUL-terminated -// string, and thus want to print it as a pointer to be safe. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - -// The default case. -template -class FormatForComparison { - public: - static ::std::string Format(const ToPrint& value) { - return ::testing::PrintToString(value); - } -}; - -// Array. -template -class FormatForComparison { - public: - static ::std::string Format(const ToPrint* value) { - return FormatForComparison::Format(value); - } -}; - -// By default, print C string as pointers to be safe, as we don't know -// whether they actually point to a NUL-terminated string. - -#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ - template \ - class FormatForComparison { \ - public: \ - static ::std::string Format(CharType* value) { \ - return ::testing::PrintToString(static_cast(value)); \ - } \ - } - -GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); -GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); -GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); -GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); - -#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ - -// If a C string is compared with an STL string object, we know it's meant -// to point to a NUL-terminated string, and thus can print it as a string. - -#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ - template <> \ - class FormatForComparison { \ - public: \ - static ::std::string Format(CharType* value) { \ - return ::testing::PrintToString(value); \ - } \ - } - -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); - -#if GTEST_HAS_STD_WSTRING -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); -#endif - -#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ - -// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) -// operand to be used in a failure message. The type (but not value) -// of the other operand may affect the format. This allows us to -// print a char* as a raw pointer when it is compared against another -// char* or void*, and print it as a C string when it is compared -// against an std::string object, for example. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -template -std::string FormatForComparisonFailureMessage( - const T1& value, const T2& /* other_operand */) { - return FormatForComparison::Format(value); -} - -// UniversalPrinter::Print(value, ostream_ptr) prints the given -// value to the given ostream. The caller must ensure that -// 'ostream_ptr' is not NULL, or the behavior is undefined. -// -// We define UniversalPrinter as a class template (as opposed to a -// function template), as we need to partially specialize it for -// reference types, which cannot be done with function templates. -template -class UniversalPrinter; - -template -void UniversalPrint(const T& value, ::std::ostream* os); - -enum DefaultPrinterType { - kPrintContainer, - kPrintPointer, - kPrintFunctionPointer, - kPrintOther, -}; -template struct WrapPrinterType {}; - -// Used to print an STL-style container when the user doesn't define -// a PrintTo() for it. -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - const C& container, ::std::ostream* os) { - const size_t kMaxCount = 32; // The maximum number of elements to print. - *os << '{'; - size_t count = 0; - for (typename C::const_iterator it = container.begin(); - it != container.end(); ++it, ++count) { - if (count > 0) { - *os << ','; - if (count == kMaxCount) { // Enough has been printed. - *os << " ..."; - break; - } - } - *os << ' '; - // We cannot call PrintTo(*it, os) here as PrintTo() doesn't - // handle *it being a native array. - internal::UniversalPrint(*it, os); - } - - if (count > 0) { - *os << ' '; - } - *os << '}'; -} - -// Used to print a pointer that is neither a char pointer nor a member -// pointer, when the user doesn't define PrintTo() for it. (A member -// variable pointer or member function pointer doesn't really point to -// a location in the address space. Their representation is -// implementation-defined. Therefore they will be printed as raw -// bytes.) -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - T* p, ::std::ostream* os) { - if (p == nullptr) { - *os << "NULL"; - } else { - // T is not a function type. We just call << to print p, - // relying on ADL to pick up user-defined << for their pointer - // types, if any. - *os << p; - } -} -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - T* p, ::std::ostream* os) { - if (p == nullptr) { - *os << "NULL"; - } else { - // T is a function type, so '*os << p' doesn't do what we want - // (it just prints p as bool). We want to print p as a const - // void*. - *os << reinterpret_cast(p); - } -} - -// Used to print a non-container, non-pointer value when the user -// doesn't define PrintTo() for it. -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - const T& value, ::std::ostream* os) { - ::testing_internal::DefaultPrintNonContainerTo(value, os); -} - -// Prints the given value using the << operator if it has one; -// otherwise prints the bytes in it. This is what -// UniversalPrinter::Print() does when PrintTo() is not specialized -// or overloaded for type T. -// -// A user can override this behavior for a class type Foo by defining -// an overload of PrintTo() in the namespace where Foo is defined. We -// give the user this option as sometimes defining a << operator for -// Foo is not desirable (e.g. the coding style may prevent doing it, -// or there is already a << operator but it doesn't do what the user -// wants). -template -void PrintTo(const T& value, ::std::ostream* os) { - // DefaultPrintTo() is overloaded. The type of its first argument - // determines which version will be picked. - // - // Note that we check for container types here, prior to we check - // for protocol message types in our operator<<. The rationale is: - // - // For protocol messages, we want to give people a chance to - // override Google Mock's format by defining a PrintTo() or - // operator<<. For STL containers, other formats can be - // incompatible with Google Mock's format for the container - // elements; therefore we check for container types here to ensure - // that our format is used. - // - // Note that MSVC and clang-cl do allow an implicit conversion from - // pointer-to-function to pointer-to-object, but clang-cl warns on it. - // So don't use ImplicitlyConvertible if it can be helped since it will - // cause this warning, and use a separate overload of DefaultPrintTo for - // function pointers so that the `*os << p` in the object pointer overload - // doesn't cause that warning either. - DefaultPrintTo( - WrapPrinterType < - (sizeof(IsContainerTest(0)) == sizeof(IsContainer)) && - !IsRecursiveContainer::value - ? kPrintContainer - : !std::is_pointer::value - ? kPrintOther - : std::is_function::type>::value - ? kPrintFunctionPointer - : kPrintPointer > (), - value, os); -} - -// The following list of PrintTo() overloads tells -// UniversalPrinter::Print() how to print standard types (built-in -// types, strings, plain arrays, and pointers). - -// Overloads for various char types. -GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); -GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); -inline void PrintTo(char c, ::std::ostream* os) { - // When printing a plain char, we always treat it as unsigned. This - // way, the output won't be affected by whether the compiler thinks - // char is signed or not. - PrintTo(static_cast(c), os); -} - -// Overloads for other simple built-in types. -inline void PrintTo(bool x, ::std::ostream* os) { - *os << (x ? "true" : "false"); -} - -// Overload for wchar_t type. -// Prints a wchar_t as a symbol if it is printable or as its internal -// code otherwise and also as its decimal code (except for L'\0'). -// The L'\0' char is printed as "L'\\0'". The decimal code is printed -// as signed integer when wchar_t is implemented by the compiler -// as a signed type and is printed as an unsigned integer when wchar_t -// is implemented as an unsigned type. -GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); - -// Overloads for C strings. -GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); -inline void PrintTo(char* s, ::std::ostream* os) { - PrintTo(ImplicitCast_(s), os); -} - -// signed/unsigned char is often used for representing binary data, so -// we print pointers to it as void* to be safe. -inline void PrintTo(const signed char* s, ::std::ostream* os) { - PrintTo(ImplicitCast_(s), os); -} -inline void PrintTo(signed char* s, ::std::ostream* os) { - PrintTo(ImplicitCast_(s), os); -} -inline void PrintTo(const unsigned char* s, ::std::ostream* os) { - PrintTo(ImplicitCast_(s), os); -} -inline void PrintTo(unsigned char* s, ::std::ostream* os) { - PrintTo(ImplicitCast_(s), os); -} - -// MSVC can be configured to define wchar_t as a typedef of unsigned -// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native -// type. When wchar_t is a typedef, defining an overload for const -// wchar_t* would cause unsigned short* be printed as a wide string, -// possibly causing invalid memory accesses. -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) -// Overloads for wide C strings -GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); -inline void PrintTo(wchar_t* s, ::std::ostream* os) { - PrintTo(ImplicitCast_(s), os); -} -#endif - -// Overload for C arrays. Multi-dimensional arrays are printed -// properly. - -// Prints the given number of elements in an array, without printing -// the curly braces. -template -void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { - UniversalPrint(a[0], os); - for (size_t i = 1; i != count; i++) { - *os << ", "; - UniversalPrint(a[i], os); - } -} - -// Overloads for ::std::string. -GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); -inline void PrintTo(const ::std::string& s, ::std::ostream* os) { - PrintStringTo(s, os); -} - -// Overloads for ::std::wstring. -#if GTEST_HAS_STD_WSTRING -GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); -inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { - PrintWideStringTo(s, os); -} -#endif // GTEST_HAS_STD_WSTRING - -#if GTEST_HAS_ABSL -// Overload for absl::string_view. -inline void PrintTo(absl::string_view sp, ::std::ostream* os) { - PrintTo(::std::string(sp), os); -} -#endif // GTEST_HAS_ABSL - -inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } - -template -void PrintTo(std::reference_wrapper ref, ::std::ostream* os) { - UniversalPrinter::Print(ref.get(), os); -} - -// Helper function for printing a tuple. T must be instantiated with -// a tuple type. -template -void PrintTupleTo(const T&, std::integral_constant, - ::std::ostream*) {} - -template -void PrintTupleTo(const T& t, std::integral_constant, - ::std::ostream* os) { - PrintTupleTo(t, std::integral_constant(), os); - GTEST_INTENTIONAL_CONST_COND_PUSH_() - if (I > 1) { - GTEST_INTENTIONAL_CONST_COND_POP_() - *os << ", "; - } - UniversalPrinter::type>::Print( - std::get(t), os); -} - -template -void PrintTo(const ::std::tuple& t, ::std::ostream* os) { - *os << "("; - PrintTupleTo(t, std::integral_constant(), os); - *os << ")"; -} - -// Overload for std::pair. -template -void PrintTo(const ::std::pair& value, ::std::ostream* os) { - *os << '('; - // We cannot use UniversalPrint(value.first, os) here, as T1 may be - // a reference type. The same for printing value.second. - UniversalPrinter::Print(value.first, os); - *os << ", "; - UniversalPrinter::Print(value.second, os); - *os << ')'; -} - -// Implements printing a non-reference type T by letting the compiler -// pick the right overload of PrintTo() for T. -template -class UniversalPrinter { - public: - // MSVC warns about adding const to a function type, so we want to - // disable the warning. - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180) - - // Note: we deliberately don't call this PrintTo(), as that name - // conflicts with ::testing::internal::PrintTo in the body of the - // function. - static void Print(const T& value, ::std::ostream* os) { - // By default, ::testing::internal::PrintTo() is used for printing - // the value. - // - // Thanks to Koenig look-up, if T is a class and has its own - // PrintTo() function defined in its namespace, that function will - // be visible here. Since it is more specific than the generic ones - // in ::testing::internal, it will be picked by the compiler in the - // following statement - exactly what we want. - PrintTo(value, os); - } - - GTEST_DISABLE_MSC_WARNINGS_POP_() -}; - -#if GTEST_HAS_ABSL - -// Printer for absl::optional - -template -class UniversalPrinter<::absl::optional> { - public: - static void Print(const ::absl::optional& value, ::std::ostream* os) { - *os << '('; - if (!value) { - *os << "nullopt"; - } else { - UniversalPrint(*value, os); - } - *os << ')'; - } -}; - -// Printer for absl::variant - -template -class UniversalPrinter<::absl::variant> { - public: - static void Print(const ::absl::variant& value, ::std::ostream* os) { - *os << '('; - absl::visit(Visitor{os}, value); - *os << ')'; - } - - private: - struct Visitor { - template - void operator()(const U& u) const { - *os << "'" << GetTypeName() << "' with value "; - UniversalPrint(u, os); - } - ::std::ostream* os; - }; -}; - -#endif // GTEST_HAS_ABSL - -// UniversalPrintArray(begin, len, os) prints an array of 'len' -// elements, starting at address 'begin'. -template -void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { - if (len == 0) { - *os << "{}"; - } else { - *os << "{ "; - const size_t kThreshold = 18; - const size_t kChunkSize = 8; - // If the array has more than kThreshold elements, we'll have to - // omit some details by printing only the first and the last - // kChunkSize elements. - if (len <= kThreshold) { - PrintRawArrayTo(begin, len, os); - } else { - PrintRawArrayTo(begin, kChunkSize, os); - *os << ", ..., "; - PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); - } - *os << " }"; - } -} -// This overload prints a (const) char array compactly. -GTEST_API_ void UniversalPrintArray( - const char* begin, size_t len, ::std::ostream* os); - -// This overload prints a (const) wchar_t array compactly. -GTEST_API_ void UniversalPrintArray( - const wchar_t* begin, size_t len, ::std::ostream* os); - -// Implements printing an array type T[N]. -template -class UniversalPrinter { - public: - // Prints the given array, omitting some elements when there are too - // many. - static void Print(const T (&a)[N], ::std::ostream* os) { - UniversalPrintArray(a, N, os); - } -}; - -// Implements printing a reference type T&. -template -class UniversalPrinter { - public: - // MSVC warns about adding const to a function type, so we want to - // disable the warning. - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180) - - static void Print(const T& value, ::std::ostream* os) { - // Prints the address of the value. We use reinterpret_cast here - // as static_cast doesn't compile when T is a function type. - *os << "@" << reinterpret_cast(&value) << " "; - - // Then prints the value itself. - UniversalPrint(value, os); - } - - GTEST_DISABLE_MSC_WARNINGS_POP_() -}; - -// Prints a value tersely: for a reference type, the referenced value -// (but not the address) is printed; for a (const) char pointer, the -// NUL-terminated string (but not the pointer) is printed. - -template -class UniversalTersePrinter { - public: - static void Print(const T& value, ::std::ostream* os) { - UniversalPrint(value, os); - } -}; -template -class UniversalTersePrinter { - public: - static void Print(const T& value, ::std::ostream* os) { - UniversalPrint(value, os); - } -}; -template -class UniversalTersePrinter { - public: - static void Print(const T (&value)[N], ::std::ostream* os) { - UniversalPrinter::Print(value, os); - } -}; -template <> -class UniversalTersePrinter { - public: - static void Print(const char* str, ::std::ostream* os) { - if (str == nullptr) { - *os << "NULL"; - } else { - UniversalPrint(std::string(str), os); - } - } -}; -template <> -class UniversalTersePrinter { - public: - static void Print(char* str, ::std::ostream* os) { - UniversalTersePrinter::Print(str, os); - } -}; - -#if GTEST_HAS_STD_WSTRING -template <> -class UniversalTersePrinter { - public: - static void Print(const wchar_t* str, ::std::ostream* os) { - if (str == nullptr) { - *os << "NULL"; - } else { - UniversalPrint(::std::wstring(str), os); - } - } -}; -#endif - -template <> -class UniversalTersePrinter { - public: - static void Print(wchar_t* str, ::std::ostream* os) { - UniversalTersePrinter::Print(str, os); - } -}; - -template -void UniversalTersePrint(const T& value, ::std::ostream* os) { - UniversalTersePrinter::Print(value, os); -} - -// Prints a value using the type inferred by the compiler. The -// difference between this and UniversalTersePrint() is that for a -// (const) char pointer, this prints both the pointer and the -// NUL-terminated string. -template -void UniversalPrint(const T& value, ::std::ostream* os) { - // A workarond for the bug in VC++ 7.1 that prevents us from instantiating - // UniversalPrinter with T directly. - typedef T T1; - UniversalPrinter::Print(value, os); -} - -typedef ::std::vector< ::std::string> Strings; - - // Tersely prints the first N fields of a tuple to a string vector, - // one element for each field. -template -void TersePrintPrefixToStrings(const Tuple&, std::integral_constant, - Strings*) {} -template -void TersePrintPrefixToStrings(const Tuple& t, - std::integral_constant, - Strings* strings) { - TersePrintPrefixToStrings(t, std::integral_constant(), - strings); - ::std::stringstream ss; - UniversalTersePrint(std::get(t), &ss); - strings->push_back(ss.str()); -} - -// Prints the fields of a tuple tersely to a string vector, one -// element for each field. See the comment before -// UniversalTersePrint() for how we define "tersely". -template -Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { - Strings result; - TersePrintPrefixToStrings( - value, std::integral_constant::value>(), - &result); - return result; -} - -} // namespace internal - -#if GTEST_HAS_ABSL -namespace internal2 { -template -void TypeWithoutFormatter::PrintValue( - const T& value, ::std::ostream* os) { - internal::PrintTo(absl::string_view(value), os); -} -} // namespace internal2 -#endif - -template -::std::string PrintToString(const T& value) { - ::std::stringstream ss; - internal::UniversalTersePrinter::Print(value, &ss); - return ss.str(); -} - -} // namespace testing - -// Include any custom printer added by the local installation. -// We must include this header at the end to make sure it can use the -// declarations from this file. -#include "gtest/internal/custom/gtest-printers.h" - -#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-spi.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-spi.h deleted file mode 100644 index aa38870e8e1..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-spi.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2007, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// Utilities for testing Google Test itself and code that uses Google Test -// (e.g. frameworks built on top of Google Test). - -// GOOGLETEST_CM0004 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ -#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ - -#include "gtest/gtest.h" - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -namespace testing { - -// This helper class can be used to mock out Google Test failure reporting -// so that we can test Google Test or code that builds on Google Test. -// -// An object of this class appends a TestPartResult object to the -// TestPartResultArray object given in the constructor whenever a Google Test -// failure is reported. It can either intercept only failures that are -// generated in the same thread that created this object or it can intercept -// all generated failures. The scope of this mock object can be controlled with -// the second argument to the two arguments constructor. -class GTEST_API_ ScopedFakeTestPartResultReporter - : public TestPartResultReporterInterface { - public: - // The two possible mocking modes of this object. - enum InterceptMode { - INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. - INTERCEPT_ALL_THREADS // Intercepts all failures. - }; - - // The c'tor sets this object as the test part result reporter used - // by Google Test. The 'result' parameter specifies where to report the - // results. This reporter will only catch failures generated in the current - // thread. DEPRECATED - explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); - - // Same as above, but you can choose the interception scope of this object. - ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, - TestPartResultArray* result); - - // The d'tor restores the previous test part result reporter. - ~ScopedFakeTestPartResultReporter() override; - - // Appends the TestPartResult object to the TestPartResultArray - // received in the constructor. - // - // This method is from the TestPartResultReporterInterface - // interface. - void ReportTestPartResult(const TestPartResult& result) override; - - private: - void Init(); - - const InterceptMode intercept_mode_; - TestPartResultReporterInterface* old_reporter_; - TestPartResultArray* const result_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); -}; - -namespace internal { - -// A helper class for implementing EXPECT_FATAL_FAILURE() and -// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given -// TestPartResultArray contains exactly one failure that has the given -// type and contains the given substring. If that's not the case, a -// non-fatal failure will be generated. -class GTEST_API_ SingleFailureChecker { - public: - // The constructor remembers the arguments. - SingleFailureChecker(const TestPartResultArray* results, - TestPartResult::Type type, const std::string& substr); - ~SingleFailureChecker(); - private: - const TestPartResultArray* const results_; - const TestPartResult::Type type_; - const std::string substr_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); -}; - -} // namespace internal - -} // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -// A set of macros for testing Google Test assertions or code that's expected -// to generate Google Test fatal failures. It verifies that the given -// statement will cause exactly one fatal Google Test failure with 'substr' -// being part of the failure message. -// -// There are two different versions of this macro. EXPECT_FATAL_FAILURE only -// affects and considers failures generated in the current thread and -// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. -// -// The verification of the assertion is done correctly even when the statement -// throws an exception or aborts the current function. -// -// Known restrictions: -// - 'statement' cannot reference local non-static variables or -// non-static members of the current object. -// - 'statement' cannot return a value. -// - You cannot stream a failure message to this macro. -// -// Note that even though the implementations of the following two -// macros are much alike, we cannot refactor them to use a common -// helper macro, due to some peculiarity in how the preprocessor -// works. The AcceptsMacroThatExpandsToUnprotectedComma test in -// gtest_unittest.cc will fail to compile if we do that. -#define EXPECT_FATAL_FAILURE(statement, substr) \ - do { \ - class GTestExpectFatalFailureHelper {\ - public:\ - static void Execute() { statement; }\ - };\ - ::testing::TestPartResultArray gtest_failures;\ - ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ - {\ - ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ - ::testing::ScopedFakeTestPartResultReporter:: \ - INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ - GTestExpectFatalFailureHelper::Execute();\ - }\ - } while (::testing::internal::AlwaysFalse()) - -#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ - do { \ - class GTestExpectFatalFailureHelper {\ - public:\ - static void Execute() { statement; }\ - };\ - ::testing::TestPartResultArray gtest_failures;\ - ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ - {\ - ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ - ::testing::ScopedFakeTestPartResultReporter:: \ - INTERCEPT_ALL_THREADS, >est_failures);\ - GTestExpectFatalFailureHelper::Execute();\ - }\ - } while (::testing::internal::AlwaysFalse()) - -// A macro for testing Google Test assertions or code that's expected to -// generate Google Test non-fatal failures. It asserts that the given -// statement will cause exactly one non-fatal Google Test failure with 'substr' -// being part of the failure message. -// -// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only -// affects and considers failures generated in the current thread and -// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. -// -// 'statement' is allowed to reference local variables and members of -// the current object. -// -// The verification of the assertion is done correctly even when the statement -// throws an exception or aborts the current function. -// -// Known restrictions: -// - You cannot stream a failure message to this macro. -// -// Note that even though the implementations of the following two -// macros are much alike, we cannot refactor them to use a common -// helper macro, due to some peculiarity in how the preprocessor -// works. If we do that, the code won't compile when the user gives -// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that -// expands to code containing an unprotected comma. The -// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc -// catches that. -// -// For the same reason, we have to write -// if (::testing::internal::AlwaysTrue()) { statement; } -// instead of -// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) -// to avoid an MSVC warning on unreachable code. -#define EXPECT_NONFATAL_FAILURE(statement, substr) \ - do {\ - ::testing::TestPartResultArray gtest_failures;\ - ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ - (substr));\ - {\ - ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ - ::testing::ScopedFakeTestPartResultReporter:: \ - INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ - if (::testing::internal::AlwaysTrue()) { statement; }\ - }\ - } while (::testing::internal::AlwaysFalse()) - -#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ - do {\ - ::testing::TestPartResultArray gtest_failures;\ - ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ - (substr));\ - {\ - ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ - ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ - >est_failures);\ - if (::testing::internal::AlwaysTrue()) { statement; }\ - }\ - } while (::testing::internal::AlwaysFalse()) - -#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-test-part.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-test-part.h deleted file mode 100644 index 05a79853586..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-test-part.h +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ -#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ - -#include -#include -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-string.h" - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -namespace testing { - -// A copyable object representing the result of a test part (i.e. an -// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). -// -// Don't inherit from TestPartResult as its destructor is not virtual. -class GTEST_API_ TestPartResult { - public: - // The possible outcomes of a test part (i.e. an assertion or an - // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). - enum Type { - kSuccess, // Succeeded. - kNonFatalFailure, // Failed but the test can continue. - kFatalFailure, // Failed and the test should be terminated. - kSkip // Skipped. - }; - - // C'tor. TestPartResult does NOT have a default constructor. - // Always use this constructor (with parameters) to create a - // TestPartResult object. - TestPartResult(Type a_type, const char* a_file_name, int a_line_number, - const char* a_message) - : type_(a_type), - file_name_(a_file_name == nullptr ? "" : a_file_name), - line_number_(a_line_number), - summary_(ExtractSummary(a_message)), - message_(a_message) {} - - // Gets the outcome of the test part. - Type type() const { return type_; } - - // Gets the name of the source file where the test part took place, or - // NULL if it's unknown. - const char* file_name() const { - return file_name_.empty() ? nullptr : file_name_.c_str(); - } - - // Gets the line in the source file where the test part took place, - // or -1 if it's unknown. - int line_number() const { return line_number_; } - - // Gets the summary of the failure message. - const char* summary() const { return summary_.c_str(); } - - // Gets the message associated with the test part. - const char* message() const { return message_.c_str(); } - - // Returns true if and only if the test part was skipped. - bool skipped() const { return type_ == kSkip; } - - // Returns true if and only if the test part passed. - bool passed() const { return type_ == kSuccess; } - - // Returns true if and only if the test part non-fatally failed. - bool nonfatally_failed() const { return type_ == kNonFatalFailure; } - - // Returns true if and only if the test part fatally failed. - bool fatally_failed() const { return type_ == kFatalFailure; } - - // Returns true if and only if the test part failed. - bool failed() const { return fatally_failed() || nonfatally_failed(); } - - private: - Type type_; - - // Gets the summary of the failure message by omitting the stack - // trace in it. - static std::string ExtractSummary(const char* message); - - // The name of the source file where the test part took place, or - // "" if the source file is unknown. - std::string file_name_; - // The line in the source file where the test part took place, or -1 - // if the line number is unknown. - int line_number_; - std::string summary_; // The test failure summary. - std::string message_; // The test failure message. -}; - -// Prints a TestPartResult object. -std::ostream& operator<<(std::ostream& os, const TestPartResult& result); - -// An array of TestPartResult objects. -// -// Don't inherit from TestPartResultArray as its destructor is not -// virtual. -class GTEST_API_ TestPartResultArray { - public: - TestPartResultArray() {} - - // Appends the given TestPartResult to the array. - void Append(const TestPartResult& result); - - // Returns the TestPartResult at the given index (0-based). - const TestPartResult& GetTestPartResult(int index) const; - - // Returns the number of TestPartResult objects in the array. - int size() const; - - private: - std::vector array_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); -}; - -// This interface knows how to report a test part result. -class GTEST_API_ TestPartResultReporterInterface { - public: - virtual ~TestPartResultReporterInterface() {} - - virtual void ReportTestPartResult(const TestPartResult& result) = 0; -}; - -namespace internal { - -// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a -// statement generates new fatal failures. To do so it registers itself as the -// current test part result reporter. Besides checking if fatal failures were -// reported, it only delegates the reporting to the former result reporter. -// The original result reporter is restored in the destructor. -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -class GTEST_API_ HasNewFatalFailureHelper - : public TestPartResultReporterInterface { - public: - HasNewFatalFailureHelper(); - ~HasNewFatalFailureHelper() override; - void ReportTestPartResult(const TestPartResult& result) override; - bool has_new_fatal_failure() const { return has_new_fatal_failure_; } - private: - bool has_new_fatal_failure_; - TestPartResultReporterInterface* original_reporter_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); -}; - -} // namespace internal - -} // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-typed-test.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-typed-test.h deleted file mode 100644 index 095ce058022..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest-typed-test.h +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ - -// This header implements typed tests and type-parameterized tests. - -// Typed (aka type-driven) tests repeat the same test for types in a -// list. You must know which types you want to test with when writing -// typed tests. Here's how you do it: - -#if 0 - -// First, define a fixture class template. It should be parameterized -// by a type. Remember to derive it from testing::Test. -template -class FooTest : public testing::Test { - public: - ... - typedef std::list List; - static T shared_; - T value_; -}; - -// Next, associate a list of types with the test suite, which will be -// repeated for each type in the list. The typedef is necessary for -// the macro to parse correctly. -typedef testing::Types MyTypes; -TYPED_TEST_SUITE(FooTest, MyTypes); - -// If the type list contains only one type, you can write that type -// directly without Types<...>: -// TYPED_TEST_SUITE(FooTest, int); - -// Then, use TYPED_TEST() instead of TEST_F() to define as many typed -// tests for this test suite as you want. -TYPED_TEST(FooTest, DoesBlah) { - // Inside a test, refer to the special name TypeParam to get the type - // parameter. Since we are inside a derived class template, C++ requires - // us to visit the members of FooTest via 'this'. - TypeParam n = this->value_; - - // To visit static members of the fixture, add the TestFixture:: - // prefix. - n += TestFixture::shared_; - - // To refer to typedefs in the fixture, add the "typename - // TestFixture::" prefix. - typename TestFixture::List values; - values.push_back(n); - ... -} - -TYPED_TEST(FooTest, HasPropertyA) { ... } - -// TYPED_TEST_SUITE takes an optional third argument which allows to specify a -// class that generates custom test name suffixes based on the type. This should -// be a class which has a static template function GetName(int index) returning -// a string for each type. The provided integer index equals the index of the -// type in the provided type list. In many cases the index can be ignored. -// -// For example: -// class MyTypeNames { -// public: -// template -// static std::string GetName(int) { -// if (std::is_same()) return "char"; -// if (std::is_same()) return "int"; -// if (std::is_same()) return "unsignedInt"; -// } -// }; -// TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames); - -#endif // 0 - -// Type-parameterized tests are abstract test patterns parameterized -// by a type. Compared with typed tests, type-parameterized tests -// allow you to define the test pattern without knowing what the type -// parameters are. The defined pattern can be instantiated with -// different types any number of times, in any number of translation -// units. -// -// If you are designing an interface or concept, you can define a -// suite of type-parameterized tests to verify properties that any -// valid implementation of the interface/concept should have. Then, -// each implementation can easily instantiate the test suite to verify -// that it conforms to the requirements, without having to write -// similar tests repeatedly. Here's an example: - -#if 0 - -// First, define a fixture class template. It should be parameterized -// by a type. Remember to derive it from testing::Test. -template -class FooTest : public testing::Test { - ... -}; - -// Next, declare that you will define a type-parameterized test suite -// (the _P suffix is for "parameterized" or "pattern", whichever you -// prefer): -TYPED_TEST_SUITE_P(FooTest); - -// Then, use TYPED_TEST_P() to define as many type-parameterized tests -// for this type-parameterized test suite as you want. -TYPED_TEST_P(FooTest, DoesBlah) { - // Inside a test, refer to TypeParam to get the type parameter. - TypeParam n = 0; - ... -} - -TYPED_TEST_P(FooTest, HasPropertyA) { ... } - -// Now the tricky part: you need to register all test patterns before -// you can instantiate them. The first argument of the macro is the -// test suite name; the rest are the names of the tests in this test -// case. -REGISTER_TYPED_TEST_SUITE_P(FooTest, - DoesBlah, HasPropertyA); - -// Finally, you are free to instantiate the pattern with the types you -// want. If you put the above code in a header file, you can #include -// it in multiple C++ source files and instantiate it multiple times. -// -// To distinguish different instances of the pattern, the first -// argument to the INSTANTIATE_* macro is a prefix that will be added -// to the actual test suite name. Remember to pick unique prefixes for -// different instances. -typedef testing::Types MyTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); - -// If the type list contains only one type, you can write that type -// directly without Types<...>: -// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int); -// -// Similar to the optional argument of TYPED_TEST_SUITE above, -// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to -// generate custom names. -// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames); - -#endif // 0 - -#include "gtest/internal/gtest-port.h" -#include "gtest/internal/gtest-type-util.h" - -// Implements typed tests. - -#if GTEST_HAS_TYPED_TEST - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Expands to the name of the typedef for the type parameters of the -// given test suite. -#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_ - -// Expands to the name of the typedef for the NameGenerator, responsible for -// creating the suffixes of the name. -#define GTEST_NAME_GENERATOR_(TestSuiteName) \ - gtest_type_params_##TestSuiteName##_NameGenerator - -#define TYPED_TEST_SUITE(CaseName, Types, ...) \ - typedef ::testing::internal::TypeList::type GTEST_TYPE_PARAMS_( \ - CaseName); \ - typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ - GTEST_NAME_GENERATOR_(CaseName) - -# define TYPED_TEST(CaseName, TestName) \ - template \ - class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ - : public CaseName { \ - private: \ - typedef CaseName TestFixture; \ - typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ - }; \ - static bool gtest_##CaseName##_##TestName##_registered_ \ - GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::internal::TypeParameterizedTest< \ - CaseName, \ - ::testing::internal::TemplateSel, \ - GTEST_TYPE_PARAMS_( \ - CaseName)>::Register("", \ - ::testing::internal::CodeLocation( \ - __FILE__, __LINE__), \ - #CaseName, #TestName, 0, \ - ::testing::internal::GenerateNames< \ - GTEST_NAME_GENERATOR_(CaseName), \ - GTEST_TYPE_PARAMS_(CaseName)>()); \ - template \ - void GTEST_TEST_CLASS_NAME_(CaseName, \ - TestName)::TestBody() - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#define TYPED_TEST_CASE \ - static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \ - TYPED_TEST_SUITE -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -#endif // GTEST_HAS_TYPED_TEST - -// Implements type-parameterized tests. - -#if GTEST_HAS_TYPED_TEST_P - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Expands to the namespace name that the type-parameterized tests for -// the given type-parameterized test suite are defined in. The exact -// name of the namespace is subject to change without notice. -#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_ - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Expands to the name of the variable used to remember the names of -// the defined tests in the given test suite. -#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \ - gtest_typed_test_suite_p_state_##TestSuiteName##_ - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. -// -// Expands to the name of the variable used to remember the names of -// the registered tests in the given test suite. -#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \ - gtest_registered_test_names_##TestSuiteName##_ - -// The variables defined in the type-parameterized test macros are -// static as typically these macros are used in a .h file that can be -// #included in multiple translation units linked together. -#define TYPED_TEST_SUITE_P(SuiteName) \ - static ::testing::internal::TypedTestSuitePState \ - GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName) - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#define TYPED_TEST_CASE_P \ - static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \ - TYPED_TEST_SUITE_P -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -#define TYPED_TEST_P(SuiteName, TestName) \ - namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ - template \ - class TestName : public SuiteName { \ - private: \ - typedef SuiteName TestFixture; \ - typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ - }; \ - static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ - GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \ - __FILE__, __LINE__, #SuiteName, #TestName); \ - } \ - template \ - void GTEST_SUITE_NAMESPACE_( \ - SuiteName)::TestName::TestBody() - -#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \ - namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ - typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ - } \ - static const char* const GTEST_REGISTERED_TEST_NAMES_( \ - SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ - GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ - __FILE__, __LINE__, #__VA_ARGS__) - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#define REGISTER_TYPED_TEST_CASE_P \ - static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \ - ""); \ - REGISTER_TYPED_TEST_SUITE_P -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \ - static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::internal::TypeParameterizedTestSuite< \ - SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \ - ::testing::internal::TypeList::type>:: \ - Register(#Prefix, \ - ::testing::internal::CodeLocation(__FILE__, __LINE__), \ - >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \ - GTEST_REGISTERED_TEST_NAMES_(SuiteName), \ - ::testing::internal::GenerateNames< \ - ::testing::internal::NameGeneratorSelector< \ - __VA_ARGS__>::type, \ - ::testing::internal::TypeList::type>()) - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#define INSTANTIATE_TYPED_TEST_CASE_P \ - static_assert( \ - ::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \ - INSTANTIATE_TYPED_TEST_SUITE_P -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -#endif // GTEST_HAS_TYPED_TEST_P - -#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest.h deleted file mode 100644 index dbe5b1c2c3f..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest.h +++ /dev/null @@ -1,2478 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file defines the public API for Google Test. It should be -// included by any test program that uses Google Test. -// -// IMPORTANT NOTE: Due to limitation of the C++ language, we have to -// leave some internal implementation details in this header file. -// They are clearly marked by comments like this: -// -// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -// -// Such code is NOT meant to be used by a user directly, and is subject -// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user -// program! -// -// Acknowledgment: Google Test borrowed the idea of automatic test -// registration from Barthelemy Dagenais' (barthelemy@prologique.com) -// easyUnit framework. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_H_ - -#include -#include -#include -#include -#include -#include - -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-string.h" -#include "gtest/gtest-death-test.h" -#include "gtest/gtest-matchers.h" -#include "gtest/gtest-message.h" -#include "gtest/gtest-param-test.h" -#include "gtest/gtest-printers.h" -#include "gtest/gtest_prod.h" -#include "gtest/gtest-test-part.h" -#include "gtest/gtest-typed-test.h" - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -namespace testing { - -// Silence C4100 (unreferenced formal parameter) and 4805 -// unsafe mix of type 'const int' and type 'const bool' -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4805) -# pragma warning(disable:4100) -#endif - - -// Declares the flags. - -// This flag temporary enables the disabled tests. -GTEST_DECLARE_bool_(also_run_disabled_tests); - -// This flag brings the debugger on an assertion failure. -GTEST_DECLARE_bool_(break_on_failure); - -// This flag controls whether Google Test catches all test-thrown exceptions -// and logs them as failures. -GTEST_DECLARE_bool_(catch_exceptions); - -// This flag enables using colors in terminal output. Available values are -// "yes" to enable colors, "no" (disable colors), or "auto" (the default) -// to let Google Test decide. -GTEST_DECLARE_string_(color); - -// This flag sets up the filter to select by name using a glob pattern -// the tests to run. If the filter is not given all tests are executed. -GTEST_DECLARE_string_(filter); - -// This flag controls whether Google Test installs a signal handler that dumps -// debugging information when fatal signals are raised. -GTEST_DECLARE_bool_(install_failure_signal_handler); - -// This flag causes the Google Test to list tests. None of the tests listed -// are actually run if the flag is provided. -GTEST_DECLARE_bool_(list_tests); - -// This flag controls whether Google Test emits a detailed XML report to a file -// in addition to its normal textual output. -GTEST_DECLARE_string_(output); - -// This flags control whether Google Test prints the elapsed time for each -// test. -GTEST_DECLARE_bool_(print_time); - -// This flags control whether Google Test prints UTF8 characters as text. -GTEST_DECLARE_bool_(print_utf8); - -// This flag specifies the random number seed. -GTEST_DECLARE_int32_(random_seed); - -// This flag sets how many times the tests are repeated. The default value -// is 1. If the value is -1 the tests are repeating forever. -GTEST_DECLARE_int32_(repeat); - -// This flag controls whether Google Test includes Google Test internal -// stack frames in failure stack traces. -GTEST_DECLARE_bool_(show_internal_stack_frames); - -// When this flag is specified, tests' order is randomized on every iteration. -GTEST_DECLARE_bool_(shuffle); - -// This flag specifies the maximum number of stack frames to be -// printed in a failure message. -GTEST_DECLARE_int32_(stack_trace_depth); - -// When this flag is specified, a failed assertion will throw an -// exception if exceptions are enabled, or exit the program with a -// non-zero code otherwise. For use with an external test framework. -GTEST_DECLARE_bool_(throw_on_failure); - -// When this flag is set with a "host:port" string, on supported -// platforms test results are streamed to the specified port on -// the specified host machine. -GTEST_DECLARE_string_(stream_result_to); - -#if GTEST_USE_OWN_FLAGFILE_FLAG_ -GTEST_DECLARE_string_(flagfile); -#endif // GTEST_USE_OWN_FLAGFILE_FLAG_ - -// The upper limit for valid stack trace depths. -const int kMaxStackTraceDepth = 100; - -namespace internal { - -class AssertHelper; -class DefaultGlobalTestPartResultReporter; -class ExecDeathTest; -class NoExecDeathTest; -class FinalSuccessChecker; -class GTestFlagSaver; -class StreamingListenerTest; -class TestResultAccessor; -class TestEventListenersAccessor; -class TestEventRepeater; -class UnitTestRecordPropertyTestHelper; -class WindowsDeathTest; -class FuchsiaDeathTest; -class UnitTestImpl* GetUnitTestImpl(); -void ReportFailureInUnknownLocation(TestPartResult::Type result_type, - const std::string& message); - -} // namespace internal - -// The friend relationship of some of these classes is cyclic. -// If we don't forward declare them the compiler might confuse the classes -// in friendship clauses with same named classes on the scope. -class Test; -class TestSuite; - -// Old API is still available but deprecated -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -using TestCase = TestSuite; -#endif -class TestInfo; -class UnitTest; - -// A class for indicating whether an assertion was successful. When -// the assertion wasn't successful, the AssertionResult object -// remembers a non-empty message that describes how it failed. -// -// To create an instance of this class, use one of the factory functions -// (AssertionSuccess() and AssertionFailure()). -// -// This class is useful for two purposes: -// 1. Defining predicate functions to be used with Boolean test assertions -// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts -// 2. Defining predicate-format functions to be -// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). -// -// For example, if you define IsEven predicate: -// -// testing::AssertionResult IsEven(int n) { -// if ((n % 2) == 0) -// return testing::AssertionSuccess(); -// else -// return testing::AssertionFailure() << n << " is odd"; -// } -// -// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) -// will print the message -// -// Value of: IsEven(Fib(5)) -// Actual: false (5 is odd) -// Expected: true -// -// instead of a more opaque -// -// Value of: IsEven(Fib(5)) -// Actual: false -// Expected: true -// -// in case IsEven is a simple Boolean predicate. -// -// If you expect your predicate to be reused and want to support informative -// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up -// about half as often as positive ones in our tests), supply messages for -// both success and failure cases: -// -// testing::AssertionResult IsEven(int n) { -// if ((n % 2) == 0) -// return testing::AssertionSuccess() << n << " is even"; -// else -// return testing::AssertionFailure() << n << " is odd"; -// } -// -// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print -// -// Value of: IsEven(Fib(6)) -// Actual: true (8 is even) -// Expected: false -// -// NB: Predicates that support negative Boolean assertions have reduced -// performance in positive ones so be careful not to use them in tests -// that have lots (tens of thousands) of positive Boolean assertions. -// -// To use this class with EXPECT_PRED_FORMAT assertions such as: -// -// // Verifies that Foo() returns an even number. -// EXPECT_PRED_FORMAT1(IsEven, Foo()); -// -// you need to define: -// -// testing::AssertionResult IsEven(const char* expr, int n) { -// if ((n % 2) == 0) -// return testing::AssertionSuccess(); -// else -// return testing::AssertionFailure() -// << "Expected: " << expr << " is even\n Actual: it's " << n; -// } -// -// If Foo() returns 5, you will see the following message: -// -// Expected: Foo() is even -// Actual: it's 5 -// -class GTEST_API_ AssertionResult { - public: - // Copy constructor. - // Used in EXPECT_TRUE/FALSE(assertion_result). - AssertionResult(const AssertionResult& other); - -#if defined(_MSC_VER) && _MSC_VER < 1910 - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */) -#endif - - // Used in the EXPECT_TRUE/FALSE(bool_expression). - // - // T must be contextually convertible to bool. - // - // The second parameter prevents this overload from being considered if - // the argument is implicitly convertible to AssertionResult. In that case - // we want AssertionResult's copy constructor to be used. - template - explicit AssertionResult( - const T& success, - typename std::enable_if< - !std::is_convertible::value>::type* - /*enabler*/ - = nullptr) - : success_(success) {} - -#if defined(_MSC_VER) && _MSC_VER < 1910 - GTEST_DISABLE_MSC_WARNINGS_POP_() -#endif - - // Assignment operator. - AssertionResult& operator=(AssertionResult other) { - swap(other); - return *this; - } - - // Returns true if and only if the assertion succeeded. - operator bool() const { return success_; } // NOLINT - - // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. - AssertionResult operator!() const; - - // Returns the text streamed into this AssertionResult. Test assertions - // use it when they fail (i.e., the predicate's outcome doesn't match the - // assertion's expectation). When nothing has been streamed into the - // object, returns an empty string. - const char* message() const { - return message_.get() != nullptr ? message_->c_str() : ""; - } - // Deprecated; please use message() instead. - const char* failure_message() const { return message(); } - - // Streams a custom failure message into this object. - template AssertionResult& operator<<(const T& value) { - AppendMessage(Message() << value); - return *this; - } - - // Allows streaming basic output manipulators such as endl or flush into - // this object. - AssertionResult& operator<<( - ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { - AppendMessage(Message() << basic_manipulator); - return *this; - } - - private: - // Appends the contents of message to message_. - void AppendMessage(const Message& a_message) { - if (message_.get() == nullptr) message_.reset(new ::std::string); - message_->append(a_message.GetString().c_str()); - } - - // Swap the contents of this AssertionResult with other. - void swap(AssertionResult& other); - - // Stores result of the assertion predicate. - bool success_; - // Stores the message describing the condition in case the expectation - // construct is not satisfied with the predicate's outcome. - // Referenced via a pointer to avoid taking too much stack frame space - // with test assertions. - std::unique_ptr< ::std::string> message_; -}; - -// Makes a successful assertion result. -GTEST_API_ AssertionResult AssertionSuccess(); - -// Makes a failed assertion result. -GTEST_API_ AssertionResult AssertionFailure(); - -// Makes a failed assertion result with the given failure message. -// Deprecated; use AssertionFailure() << msg. -GTEST_API_ AssertionResult AssertionFailure(const Message& msg); - -} // namespace testing - -// Includes the auto-generated header that implements a family of generic -// predicate assertion macros. This include comes late because it relies on -// APIs declared above. -#include "gtest/gtest_pred_impl.h" - -namespace testing { - -// The abstract class that all tests inherit from. -// -// In Google Test, a unit test program contains one or many TestSuites, and -// each TestSuite contains one or many Tests. -// -// When you define a test using the TEST macro, you don't need to -// explicitly derive from Test - the TEST macro automatically does -// this for you. -// -// The only time you derive from Test is when defining a test fixture -// to be used in a TEST_F. For example: -// -// class FooTest : public testing::Test { -// protected: -// void SetUp() override { ... } -// void TearDown() override { ... } -// ... -// }; -// -// TEST_F(FooTest, Bar) { ... } -// TEST_F(FooTest, Baz) { ... } -// -// Test is not copyable. -class GTEST_API_ Test { - public: - friend class TestInfo; - - // The d'tor is virtual as we intend to inherit from Test. - virtual ~Test(); - - // Sets up the stuff shared by all tests in this test case. - // - // Google Test will call Foo::SetUpTestSuite() before running the first - // test in test case Foo. Hence a sub-class can define its own - // SetUpTestSuite() method to shadow the one defined in the super - // class. - // Failures that happen during SetUpTestSuite are logged but otherwise - // ignored. - static void SetUpTestSuite() {} - - // Tears down the stuff shared by all tests in this test suite. - // - // Google Test will call Foo::TearDownTestSuite() after running the last - // test in test case Foo. Hence a sub-class can define its own - // TearDownTestSuite() method to shadow the one defined in the super - // class. - // Failures that happen during TearDownTestSuite are logged but otherwise - // ignored. - static void TearDownTestSuite() {} - - // Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - static void TearDownTestCase() {} - static void SetUpTestCase() {} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Returns true if and only if the current test has a fatal failure. - static bool HasFatalFailure(); - - // Returns true if and only if the current test has a non-fatal failure. - static bool HasNonfatalFailure(); - - // Returns true if and only if the current test was skipped. - static bool IsSkipped(); - - // Returns true if and only if the current test has a (either fatal or - // non-fatal) failure. - static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } - - // Logs a property for the current test, test suite, or for the entire - // invocation of the test program when used outside of the context of a - // test suite. Only the last value for a given key is remembered. These - // are public static so they can be called from utility functions that are - // not members of the test fixture. Calls to RecordProperty made during - // lifespan of the test (from the moment its constructor starts to the - // moment its destructor finishes) will be output in XML as attributes of - // the element. Properties recorded from fixture's - // SetUpTestSuite or TearDownTestSuite are logged as attributes of the - // corresponding element. Calls to RecordProperty made in the - // global context (before or after invocation of RUN_ALL_TESTS and from - // SetUp/TearDown method of Environment objects registered with Google - // Test) will be output as attributes of the element. - static void RecordProperty(const std::string& key, const std::string& value); - static void RecordProperty(const std::string& key, int value); - - protected: - // Creates a Test object. - Test(); - - // Sets up the test fixture. - virtual void SetUp(); - - // Tears down the test fixture. - virtual void TearDown(); - - private: - // Returns true if and only if the current test has the same fixture class - // as the first test in the current test suite. - static bool HasSameFixtureClass(); - - // Runs the test after the test fixture has been set up. - // - // A sub-class must implement this to define the test logic. - // - // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. - // Instead, use the TEST or TEST_F macro. - virtual void TestBody() = 0; - - // Sets up, executes, and tears down the test. - void Run(); - - // Deletes self. We deliberately pick an unusual name for this - // internal method to avoid clashing with names used in user TESTs. - void DeleteSelf_() { delete this; } - - const std::unique_ptr gtest_flag_saver_; - - // Often a user misspells SetUp() as Setup() and spends a long time - // wondering why it is never called by Google Test. The declaration of - // the following method is solely for catching such an error at - // compile time: - // - // - The return type is deliberately chosen to be not void, so it - // will be a conflict if void Setup() is declared in the user's - // test fixture. - // - // - This method is private, so it will be another compiler error - // if the method is called from the user's test fixture. - // - // DO NOT OVERRIDE THIS FUNCTION. - // - // If you see an error about overriding the following function or - // about it being private, you have mis-spelled SetUp() as Setup(). - struct Setup_should_be_spelled_SetUp {}; - virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; } - - // We disallow copying Tests. - GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); -}; - -typedef internal::TimeInMillis TimeInMillis; - -// A copyable object representing a user specified test property which can be -// output as a key/value string pair. -// -// Don't inherit from TestProperty as its destructor is not virtual. -class TestProperty { - public: - // C'tor. TestProperty does NOT have a default constructor. - // Always use this constructor (with parameters) to create a - // TestProperty object. - TestProperty(const std::string& a_key, const std::string& a_value) : - key_(a_key), value_(a_value) { - } - - // Gets the user supplied key. - const char* key() const { - return key_.c_str(); - } - - // Gets the user supplied value. - const char* value() const { - return value_.c_str(); - } - - // Sets a new value, overriding the one supplied in the constructor. - void SetValue(const std::string& new_value) { - value_ = new_value; - } - - private: - // The key supplied by the user. - std::string key_; - // The value supplied by the user. - std::string value_; -}; - -// The result of a single Test. This includes a list of -// TestPartResults, a list of TestProperties, a count of how many -// death tests there are in the Test, and how much time it took to run -// the Test. -// -// TestResult is not copyable. -class GTEST_API_ TestResult { - public: - // Creates an empty TestResult. - TestResult(); - - // D'tor. Do not inherit from TestResult. - ~TestResult(); - - // Gets the number of all test parts. This is the sum of the number - // of successful test parts and the number of failed test parts. - int total_part_count() const; - - // Returns the number of the test properties. - int test_property_count() const; - - // Returns true if and only if the test passed (i.e. no test part failed). - bool Passed() const { return !Skipped() && !Failed(); } - - // Returns true if and only if the test was skipped. - bool Skipped() const; - - // Returns true if and only if the test failed. - bool Failed() const; - - // Returns true if and only if the test fatally failed. - bool HasFatalFailure() const; - - // Returns true if and only if the test has a non-fatal failure. - bool HasNonfatalFailure() const; - - // Returns the elapsed time, in milliseconds. - TimeInMillis elapsed_time() const { return elapsed_time_; } - - // Gets the time of the test case start, in ms from the start of the - // UNIX epoch. - TimeInMillis start_timestamp() const { return start_timestamp_; } - - // Returns the i-th test part result among all the results. i can range from 0 - // to total_part_count() - 1. If i is not in that range, aborts the program. - const TestPartResult& GetTestPartResult(int i) const; - - // Returns the i-th test property. i can range from 0 to - // test_property_count() - 1. If i is not in that range, aborts the - // program. - const TestProperty& GetTestProperty(int i) const; - - private: - friend class TestInfo; - friend class TestSuite; - friend class UnitTest; - friend class internal::DefaultGlobalTestPartResultReporter; - friend class internal::ExecDeathTest; - friend class internal::TestResultAccessor; - friend class internal::UnitTestImpl; - friend class internal::WindowsDeathTest; - friend class internal::FuchsiaDeathTest; - - // Gets the vector of TestPartResults. - const std::vector& test_part_results() const { - return test_part_results_; - } - - // Gets the vector of TestProperties. - const std::vector& test_properties() const { - return test_properties_; - } - - // Sets the start time. - void set_start_timestamp(TimeInMillis start) { start_timestamp_ = start; } - - // Sets the elapsed time. - void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } - - // Adds a test property to the list. The property is validated and may add - // a non-fatal failure if invalid (e.g., if it conflicts with reserved - // key names). If a property is already recorded for the same key, the - // value will be updated, rather than storing multiple values for the same - // key. xml_element specifies the element for which the property is being - // recorded and is used for validation. - void RecordProperty(const std::string& xml_element, - const TestProperty& test_property); - - // Adds a failure if the key is a reserved attribute of Google Test - // testsuite tags. Returns true if the property is valid. - // FIXME: Validate attribute names are legal and human readable. - static bool ValidateTestProperty(const std::string& xml_element, - const TestProperty& test_property); - - // Adds a test part result to the list. - void AddTestPartResult(const TestPartResult& test_part_result); - - // Returns the death test count. - int death_test_count() const { return death_test_count_; } - - // Increments the death test count, returning the new count. - int increment_death_test_count() { return ++death_test_count_; } - - // Clears the test part results. - void ClearTestPartResults(); - - // Clears the object. - void Clear(); - - // Protects mutable state of the property vector and of owned - // properties, whose values may be updated. - internal::Mutex test_properites_mutex_; - - // The vector of TestPartResults - std::vector test_part_results_; - // The vector of TestProperties - std::vector test_properties_; - // Running count of death tests. - int death_test_count_; - // The start time, in milliseconds since UNIX Epoch. - TimeInMillis start_timestamp_; - // The elapsed time, in milliseconds. - TimeInMillis elapsed_time_; - - // We disallow copying TestResult. - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); -}; // class TestResult - -// A TestInfo object stores the following information about a test: -// -// Test suite name -// Test name -// Whether the test should be run -// A function pointer that creates the test object when invoked -// Test result -// -// The constructor of TestInfo registers itself with the UnitTest -// singleton such that the RUN_ALL_TESTS() macro knows which tests to -// run. -class GTEST_API_ TestInfo { - public: - // Destructs a TestInfo object. This function is not virtual, so - // don't inherit from TestInfo. - ~TestInfo(); - - // Returns the test suite name. - const char* test_suite_name() const { return test_suite_name_.c_str(); } - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - const char* test_case_name() const { return test_suite_name(); } -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Returns the test name. - const char* name() const { return name_.c_str(); } - - // Returns the name of the parameter type, or NULL if this is not a typed - // or a type-parameterized test. - const char* type_param() const { - if (type_param_.get() != nullptr) return type_param_->c_str(); - return nullptr; - } - - // Returns the text representation of the value parameter, or NULL if this - // is not a value-parameterized test. - const char* value_param() const { - if (value_param_.get() != nullptr) return value_param_->c_str(); - return nullptr; - } - - // Returns the file name where this test is defined. - const char* file() const { return location_.file.c_str(); } - - // Returns the line where this test is defined. - int line() const { return location_.line; } - - // Return true if this test should not be run because it's in another shard. - bool is_in_another_shard() const { return is_in_another_shard_; } - - // Returns true if this test should run, that is if the test is not - // disabled (or it is disabled but the also_run_disabled_tests flag has - // been specified) and its full name matches the user-specified filter. - // - // Google Test allows the user to filter the tests by their full names. - // The full name of a test Bar in test suite Foo is defined as - // "Foo.Bar". Only the tests that match the filter will run. - // - // A filter is a colon-separated list of glob (not regex) patterns, - // optionally followed by a '-' and a colon-separated list of - // negative patterns (tests to exclude). A test is run if it - // matches one of the positive patterns and does not match any of - // the negative patterns. - // - // For example, *A*:Foo.* is a filter that matches any string that - // contains the character 'A' or starts with "Foo.". - bool should_run() const { return should_run_; } - - // Returns true if and only if this test will appear in the XML report. - bool is_reportable() const { - // The XML report includes tests matching the filter, excluding those - // run in other shards. - return matches_filter_ && !is_in_another_shard_; - } - - // Returns the result of the test. - const TestResult* result() const { return &result_; } - - private: -#if GTEST_HAS_DEATH_TEST - friend class internal::DefaultDeathTestFactory; -#endif // GTEST_HAS_DEATH_TEST - friend class Test; - friend class TestSuite; - friend class internal::UnitTestImpl; - friend class internal::StreamingListenerTest; - friend TestInfo* internal::MakeAndRegisterTestInfo( - const char* test_suite_name, const char* name, const char* type_param, - const char* value_param, internal::CodeLocation code_location, - internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc, - internal::TestFactoryBase* factory); - - // Constructs a TestInfo object. The newly constructed instance assumes - // ownership of the factory object. - TestInfo(const std::string& test_suite_name, const std::string& name, - const char* a_type_param, // NULL if not a type-parameterized test - const char* a_value_param, // NULL if not a value-parameterized test - internal::CodeLocation a_code_location, - internal::TypeId fixture_class_id, - internal::TestFactoryBase* factory); - - // Increments the number of death tests encountered in this test so - // far. - int increment_death_test_count() { - return result_.increment_death_test_count(); - } - - // Creates the test object, runs it, records its result, and then - // deletes it. - void Run(); - - static void ClearTestResult(TestInfo* test_info) { - test_info->result_.Clear(); - } - - // These fields are immutable properties of the test. - const std::string test_suite_name_; // test suite name - const std::string name_; // Test name - // Name of the parameter type, or NULL if this is not a typed or a - // type-parameterized test. - const std::unique_ptr type_param_; - // Text representation of the value parameter, or NULL if this is not a - // value-parameterized test. - const std::unique_ptr value_param_; - internal::CodeLocation location_; - const internal::TypeId fixture_class_id_; // ID of the test fixture class - bool should_run_; // True if and only if this test should run - bool is_disabled_; // True if and only if this test is disabled - bool matches_filter_; // True if this test matches the - // user-specified filter. - bool is_in_another_shard_; // Will be run in another shard. - internal::TestFactoryBase* const factory_; // The factory that creates - // the test object - - // This field is mutable and needs to be reset before running the - // test for the second time. - TestResult result_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); -}; - -// A test suite, which consists of a vector of TestInfos. -// -// TestSuite is not copyable. -class GTEST_API_ TestSuite { - public: - // Creates a TestSuite with the given name. - // - // TestSuite does NOT have a default constructor. Always use this - // constructor to create a TestSuite object. - // - // Arguments: - // - // name: name of the test suite - // a_type_param: the name of the test's type parameter, or NULL if - // this is not a type-parameterized test. - // set_up_tc: pointer to the function that sets up the test suite - // tear_down_tc: pointer to the function that tears down the test suite - TestSuite(const char* name, const char* a_type_param, - internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc); - - // Destructor of TestSuite. - virtual ~TestSuite(); - - // Gets the name of the TestSuite. - const char* name() const { return name_.c_str(); } - - // Returns the name of the parameter type, or NULL if this is not a - // type-parameterized test suite. - const char* type_param() const { - if (type_param_.get() != nullptr) return type_param_->c_str(); - return nullptr; - } - - // Returns true if any test in this test suite should run. - bool should_run() const { return should_run_; } - - // Gets the number of successful tests in this test suite. - int successful_test_count() const; - - // Gets the number of skipped tests in this test suite. - int skipped_test_count() const; - - // Gets the number of failed tests in this test suite. - int failed_test_count() const; - - // Gets the number of disabled tests that will be reported in the XML report. - int reportable_disabled_test_count() const; - - // Gets the number of disabled tests in this test suite. - int disabled_test_count() const; - - // Gets the number of tests to be printed in the XML report. - int reportable_test_count() const; - - // Get the number of tests in this test suite that should run. - int test_to_run_count() const; - - // Gets the number of all tests in this test suite. - int total_test_count() const; - - // Returns true if and only if the test suite passed. - bool Passed() const { return !Failed(); } - - // Returns true if and only if the test suite failed. - bool Failed() const { return failed_test_count() > 0; } - - // Returns the elapsed time, in milliseconds. - TimeInMillis elapsed_time() const { return elapsed_time_; } - - // Gets the time of the test suite start, in ms from the start of the - // UNIX epoch. - TimeInMillis start_timestamp() const { return start_timestamp_; } - - // Returns the i-th test among all the tests. i can range from 0 to - // total_test_count() - 1. If i is not in that range, returns NULL. - const TestInfo* GetTestInfo(int i) const; - - // Returns the TestResult that holds test properties recorded during - // execution of SetUpTestSuite and TearDownTestSuite. - const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } - - private: - friend class Test; - friend class internal::UnitTestImpl; - - // Gets the (mutable) vector of TestInfos in this TestSuite. - std::vector& test_info_list() { return test_info_list_; } - - // Gets the (immutable) vector of TestInfos in this TestSuite. - const std::vector& test_info_list() const { - return test_info_list_; - } - - // Returns the i-th test among all the tests. i can range from 0 to - // total_test_count() - 1. If i is not in that range, returns NULL. - TestInfo* GetMutableTestInfo(int i); - - // Sets the should_run member. - void set_should_run(bool should) { should_run_ = should; } - - // Adds a TestInfo to this test suite. Will delete the TestInfo upon - // destruction of the TestSuite object. - void AddTestInfo(TestInfo * test_info); - - // Clears the results of all tests in this test suite. - void ClearResult(); - - // Clears the results of all tests in the given test suite. - static void ClearTestSuiteResult(TestSuite* test_suite) { - test_suite->ClearResult(); - } - - // Runs every test in this TestSuite. - void Run(); - - // Runs SetUpTestSuite() for this TestSuite. This wrapper is needed - // for catching exceptions thrown from SetUpTestSuite(). - void RunSetUpTestSuite() { - if (set_up_tc_ != nullptr) { - (*set_up_tc_)(); - } - } - - // Runs TearDownTestSuite() for this TestSuite. This wrapper is - // needed for catching exceptions thrown from TearDownTestSuite(). - void RunTearDownTestSuite() { - if (tear_down_tc_ != nullptr) { - (*tear_down_tc_)(); - } - } - - // Returns true if and only if test passed. - static bool TestPassed(const TestInfo* test_info) { - return test_info->should_run() && test_info->result()->Passed(); - } - - // Returns true if and only if test skipped. - static bool TestSkipped(const TestInfo* test_info) { - return test_info->should_run() && test_info->result()->Skipped(); - } - - // Returns true if and only if test failed. - static bool TestFailed(const TestInfo* test_info) { - return test_info->should_run() && test_info->result()->Failed(); - } - - // Returns true if and only if the test is disabled and will be reported in - // the XML report. - static bool TestReportableDisabled(const TestInfo* test_info) { - return test_info->is_reportable() && test_info->is_disabled_; - } - - // Returns true if and only if test is disabled. - static bool TestDisabled(const TestInfo* test_info) { - return test_info->is_disabled_; - } - - // Returns true if and only if this test will appear in the XML report. - static bool TestReportable(const TestInfo* test_info) { - return test_info->is_reportable(); - } - - // Returns true if the given test should run. - static bool ShouldRunTest(const TestInfo* test_info) { - return test_info->should_run(); - } - - // Shuffles the tests in this test suite. - void ShuffleTests(internal::Random* random); - - // Restores the test order to before the first shuffle. - void UnshuffleTests(); - - // Name of the test suite. - std::string name_; - // Name of the parameter type, or NULL if this is not a typed or a - // type-parameterized test. - const std::unique_ptr type_param_; - // The vector of TestInfos in their original order. It owns the - // elements in the vector. - std::vector test_info_list_; - // Provides a level of indirection for the test list to allow easy - // shuffling and restoring the test order. The i-th element in this - // vector is the index of the i-th test in the shuffled test list. - std::vector test_indices_; - // Pointer to the function that sets up the test suite. - internal::SetUpTestSuiteFunc set_up_tc_; - // Pointer to the function that tears down the test suite. - internal::TearDownTestSuiteFunc tear_down_tc_; - // True if and only if any test in this test suite should run. - bool should_run_; - // The start time, in milliseconds since UNIX Epoch. - TimeInMillis start_timestamp_; - // Elapsed time, in milliseconds. - TimeInMillis elapsed_time_; - // Holds test properties recorded during execution of SetUpTestSuite and - // TearDownTestSuite. - TestResult ad_hoc_test_result_; - - // We disallow copying TestSuites. - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestSuite); -}; - -// An Environment object is capable of setting up and tearing down an -// environment. You should subclass this to define your own -// environment(s). -// -// An Environment object does the set-up and tear-down in virtual -// methods SetUp() and TearDown() instead of the constructor and the -// destructor, as: -// -// 1. You cannot safely throw from a destructor. This is a problem -// as in some cases Google Test is used where exceptions are enabled, and -// we may want to implement ASSERT_* using exceptions where they are -// available. -// 2. You cannot use ASSERT_* directly in a constructor or -// destructor. -class Environment { - public: - // The d'tor is virtual as we need to subclass Environment. - virtual ~Environment() {} - - // Override this to define how to set up the environment. - virtual void SetUp() {} - - // Override this to define how to tear down the environment. - virtual void TearDown() {} - private: - // If you see an error about overriding the following function or - // about it being private, you have mis-spelled SetUp() as Setup(). - struct Setup_should_be_spelled_SetUp {}; - virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; } -}; - -#if GTEST_HAS_EXCEPTIONS - -// Exception which can be thrown from TestEventListener::OnTestPartResult. -class GTEST_API_ AssertionException - : public internal::GoogleTestFailureException { - public: - explicit AssertionException(const TestPartResult& result) - : GoogleTestFailureException(result) {} -}; - -#endif // GTEST_HAS_EXCEPTIONS - -// The interface for tracing execution of tests. The methods are organized in -// the order the corresponding events are fired. -class TestEventListener { - public: - virtual ~TestEventListener() {} - - // Fired before any test activity starts. - virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; - - // Fired before each iteration of tests starts. There may be more than - // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration - // index, starting from 0. - virtual void OnTestIterationStart(const UnitTest& unit_test, - int iteration) = 0; - - // Fired before environment set-up for each iteration of tests starts. - virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; - - // Fired after environment set-up for each iteration of tests ends. - virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; - - // Fired before the test suite starts. - virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {} - - // Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Fired before the test starts. - virtual void OnTestStart(const TestInfo& test_info) = 0; - - // Fired after a failed assertion or a SUCCEED() invocation. - // If you want to throw an exception from this function to skip to the next - // TEST, it must be AssertionException defined above, or inherited from it. - virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; - - // Fired after the test ends. - virtual void OnTestEnd(const TestInfo& test_info) = 0; - - // Fired after the test suite ends. - virtual void OnTestSuiteEnd(const TestSuite& /*test_suite*/) {} - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Fired before environment tear-down for each iteration of tests starts. - virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; - - // Fired after environment tear-down for each iteration of tests ends. - virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; - - // Fired after each iteration of tests finishes. - virtual void OnTestIterationEnd(const UnitTest& unit_test, - int iteration) = 0; - - // Fired after all test activities have ended. - virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; -}; - -// The convenience class for users who need to override just one or two -// methods and are not concerned that a possible change to a signature of -// the methods they override will not be caught during the build. For -// comments about each method please see the definition of TestEventListener -// above. -class EmptyTestEventListener : public TestEventListener { - public: - void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} - void OnTestIterationStart(const UnitTest& /*unit_test*/, - int /*iteration*/) override {} - void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {} - void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} - void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {} -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestCaseStart(const TestCase& /*test_case*/) override {} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - void OnTestStart(const TestInfo& /*test_info*/) override {} - void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {} - void OnTestEnd(const TestInfo& /*test_info*/) override {} - void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {} -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestCaseEnd(const TestCase& /*test_case*/) override {} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {} - void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} - void OnTestIterationEnd(const UnitTest& /*unit_test*/, - int /*iteration*/) override {} - void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} -}; - -// TestEventListeners lets users add listeners to track events in Google Test. -class GTEST_API_ TestEventListeners { - public: - TestEventListeners(); - ~TestEventListeners(); - - // Appends an event listener to the end of the list. Google Test assumes - // the ownership of the listener (i.e. it will delete the listener when - // the test program finishes). - void Append(TestEventListener* listener); - - // Removes the given event listener from the list and returns it. It then - // becomes the caller's responsibility to delete the listener. Returns - // NULL if the listener is not found in the list. - TestEventListener* Release(TestEventListener* listener); - - // Returns the standard listener responsible for the default console - // output. Can be removed from the listeners list to shut down default - // console output. Note that removing this object from the listener list - // with Release transfers its ownership to the caller and makes this - // function return NULL the next time. - TestEventListener* default_result_printer() const { - return default_result_printer_; - } - - // Returns the standard listener responsible for the default XML output - // controlled by the --gtest_output=xml flag. Can be removed from the - // listeners list by users who want to shut down the default XML output - // controlled by this flag and substitute it with custom one. Note that - // removing this object from the listener list with Release transfers its - // ownership to the caller and makes this function return NULL the next - // time. - TestEventListener* default_xml_generator() const { - return default_xml_generator_; - } - - private: - friend class TestSuite; - friend class TestInfo; - friend class internal::DefaultGlobalTestPartResultReporter; - friend class internal::NoExecDeathTest; - friend class internal::TestEventListenersAccessor; - friend class internal::UnitTestImpl; - - // Returns repeater that broadcasts the TestEventListener events to all - // subscribers. - TestEventListener* repeater(); - - // Sets the default_result_printer attribute to the provided listener. - // The listener is also added to the listener list and previous - // default_result_printer is removed from it and deleted. The listener can - // also be NULL in which case it will not be added to the list. Does - // nothing if the previous and the current listener objects are the same. - void SetDefaultResultPrinter(TestEventListener* listener); - - // Sets the default_xml_generator attribute to the provided listener. The - // listener is also added to the listener list and previous - // default_xml_generator is removed from it and deleted. The listener can - // also be NULL in which case it will not be added to the list. Does - // nothing if the previous and the current listener objects are the same. - void SetDefaultXmlGenerator(TestEventListener* listener); - - // Controls whether events will be forwarded by the repeater to the - // listeners in the list. - bool EventForwardingEnabled() const; - void SuppressEventForwarding(); - - // The actual list of listeners. - internal::TestEventRepeater* repeater_; - // Listener responsible for the standard result output. - TestEventListener* default_result_printer_; - // Listener responsible for the creation of the XML output file. - TestEventListener* default_xml_generator_; - - // We disallow copying TestEventListeners. - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); -}; - -// A UnitTest consists of a vector of TestSuites. -// -// This is a singleton class. The only instance of UnitTest is -// created when UnitTest::GetInstance() is first called. This -// instance is never deleted. -// -// UnitTest is not copyable. -// -// This class is thread-safe as long as the methods are called -// according to their specification. -class GTEST_API_ UnitTest { - public: - // Gets the singleton UnitTest object. The first time this method - // is called, a UnitTest object is constructed and returned. - // Consecutive calls will return the same object. - static UnitTest* GetInstance(); - - // Runs all tests in this UnitTest object and prints the result. - // Returns 0 if successful, or 1 otherwise. - // - // This method can only be called from the main thread. - // - // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - int Run() GTEST_MUST_USE_RESULT_; - - // Returns the working directory when the first TEST() or TEST_F() - // was executed. The UnitTest object owns the string. - const char* original_working_dir() const; - - // Returns the TestSuite object for the test that's currently running, - // or NULL if no test is running. - const TestSuite* current_test_suite() const GTEST_LOCK_EXCLUDED_(mutex_); - -// Legacy API is still available but deprecated -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - const TestCase* current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_); -#endif - - // Returns the TestInfo object for the test that's currently running, - // or NULL if no test is running. - const TestInfo* current_test_info() const - GTEST_LOCK_EXCLUDED_(mutex_); - - // Returns the random seed used at the start of the current test run. - int random_seed() const; - - // Returns the ParameterizedTestSuiteRegistry object used to keep track of - // value-parameterized tests and instantiate and register them. - // - // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() - GTEST_LOCK_EXCLUDED_(mutex_); - - // Gets the number of successful test suites. - int successful_test_suite_count() const; - - // Gets the number of failed test suites. - int failed_test_suite_count() const; - - // Gets the number of all test suites. - int total_test_suite_count() const; - - // Gets the number of all test suites that contain at least one test - // that should run. - int test_suite_to_run_count() const; - - // Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - int successful_test_case_count() const; - int failed_test_case_count() const; - int total_test_case_count() const; - int test_case_to_run_count() const; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Gets the number of successful tests. - int successful_test_count() const; - - // Gets the number of skipped tests. - int skipped_test_count() const; - - // Gets the number of failed tests. - int failed_test_count() const; - - // Gets the number of disabled tests that will be reported in the XML report. - int reportable_disabled_test_count() const; - - // Gets the number of disabled tests. - int disabled_test_count() const; - - // Gets the number of tests to be printed in the XML report. - int reportable_test_count() const; - - // Gets the number of all tests. - int total_test_count() const; - - // Gets the number of tests that should run. - int test_to_run_count() const; - - // Gets the time of the test program start, in ms from the start of the - // UNIX epoch. - TimeInMillis start_timestamp() const; - - // Gets the elapsed time, in milliseconds. - TimeInMillis elapsed_time() const; - - // Returns true if and only if the unit test passed (i.e. all test suites - // passed). - bool Passed() const; - - // Returns true if and only if the unit test failed (i.e. some test suite - // failed or something outside of all tests failed). - bool Failed() const; - - // Gets the i-th test suite among all the test suites. i can range from 0 to - // total_test_suite_count() - 1. If i is not in that range, returns NULL. - const TestSuite* GetTestSuite(int i) const; - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - const TestCase* GetTestCase(int i) const; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Returns the TestResult containing information on test failures and - // properties logged outside of individual test suites. - const TestResult& ad_hoc_test_result() const; - - // Returns the list of event listeners that can be used to track events - // inside Google Test. - TestEventListeners& listeners(); - - private: - // Registers and returns a global test environment. When a test - // program is run, all global test environments will be set-up in - // the order they were registered. After all tests in the program - // have finished, all global test environments will be torn-down in - // the *reverse* order they were registered. - // - // The UnitTest object takes ownership of the given environment. - // - // This method can only be called from the main thread. - Environment* AddEnvironment(Environment* env); - - // Adds a TestPartResult to the current TestResult object. All - // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) - // eventually call this to report their results. The user code - // should use the assertion macros instead of calling this directly. - void AddTestPartResult(TestPartResult::Type result_type, - const char* file_name, - int line_number, - const std::string& message, - const std::string& os_stack_trace) - GTEST_LOCK_EXCLUDED_(mutex_); - - // Adds a TestProperty to the current TestResult object when invoked from - // inside a test, to current TestSuite's ad_hoc_test_result_ when invoked - // from SetUpTestSuite or TearDownTestSuite, or to the global property set - // when invoked elsewhere. If the result already contains a property with - // the same key, the value will be updated. - void RecordProperty(const std::string& key, const std::string& value); - - // Gets the i-th test suite among all the test suites. i can range from 0 to - // total_test_suite_count() - 1. If i is not in that range, returns NULL. - TestSuite* GetMutableTestSuite(int i); - - // Accessors for the implementation object. - internal::UnitTestImpl* impl() { return impl_; } - const internal::UnitTestImpl* impl() const { return impl_; } - - // These classes and functions are friends as they need to access private - // members of UnitTest. - friend class ScopedTrace; - friend class Test; - friend class internal::AssertHelper; - friend class internal::StreamingListenerTest; - friend class internal::UnitTestRecordPropertyTestHelper; - friend Environment* AddGlobalTestEnvironment(Environment* env); - friend internal::UnitTestImpl* internal::GetUnitTestImpl(); - friend void internal::ReportFailureInUnknownLocation( - TestPartResult::Type result_type, - const std::string& message); - - // Creates an empty UnitTest. - UnitTest(); - - // D'tor - virtual ~UnitTest(); - - // Pushes a trace defined by SCOPED_TRACE() on to the per-thread - // Google Test trace stack. - void PushGTestTrace(const internal::TraceInfo& trace) - GTEST_LOCK_EXCLUDED_(mutex_); - - // Pops a trace from the per-thread Google Test trace stack. - void PopGTestTrace() - GTEST_LOCK_EXCLUDED_(mutex_); - - // Protects mutable state in *impl_. This is mutable as some const - // methods need to lock it too. - mutable internal::Mutex mutex_; - - // Opaque implementation object. This field is never changed once - // the object is constructed. We don't mark it as const here, as - // doing so will cause a warning in the constructor of UnitTest. - // Mutable state in *impl_ is protected by mutex_. - internal::UnitTestImpl* impl_; - - // We disallow copying UnitTest. - GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); -}; - -// A convenient wrapper for adding an environment for the test -// program. -// -// You should call this before RUN_ALL_TESTS() is called, probably in -// main(). If you use gtest_main, you need to call this before main() -// starts for it to take effect. For example, you can define a global -// variable like this: -// -// testing::Environment* const foo_env = -// testing::AddGlobalTestEnvironment(new FooEnvironment); -// -// However, we strongly recommend you to write your own main() and -// call AddGlobalTestEnvironment() there, as relying on initialization -// of global variables makes the code harder to read and may cause -// problems when you register multiple environments from different -// translation units and the environments have dependencies among them -// (remember that the compiler doesn't guarantee the order in which -// global variables from different translation units are initialized). -inline Environment* AddGlobalTestEnvironment(Environment* env) { - return UnitTest::GetInstance()->AddEnvironment(env); -} - -// Initializes Google Test. This must be called before calling -// RUN_ALL_TESTS(). In particular, it parses a command line for the -// flags that Google Test recognizes. Whenever a Google Test flag is -// seen, it is removed from argv, and *argc is decremented. -// -// No value is returned. Instead, the Google Test flag variables are -// updated. -// -// Calling the function for the second time has no user-visible effect. -GTEST_API_ void InitGoogleTest(int* argc, char** argv); - -// This overloaded version can be used in Windows programs compiled in -// UNICODE mode. -GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); - -// This overloaded version can be used on Arduino/embedded platforms where -// there is no argc/argv. -GTEST_API_ void InitGoogleTest(); - -namespace internal { - -// Separate the error generating code from the code path to reduce the stack -// frame size of CmpHelperEQ. This helps reduce the overhead of some sanitizers -// when calling EXPECT_* in a tight loop. -template -AssertionResult CmpHelperEQFailure(const char* lhs_expression, - const char* rhs_expression, - const T1& lhs, const T2& rhs) { - return EqFailure(lhs_expression, - rhs_expression, - FormatForComparisonFailureMessage(lhs, rhs), - FormatForComparisonFailureMessage(rhs, lhs), - false); -} - -// This block of code defines operator==/!= -// to block lexical scope lookup. -// It prevents using invalid operator==/!= defined at namespace scope. -struct faketype {}; -inline bool operator==(faketype, faketype) { return true; } -inline bool operator!=(faketype, faketype) { return false; } - -// The helper function for {ASSERT|EXPECT}_EQ. -template -AssertionResult CmpHelperEQ(const char* lhs_expression, - const char* rhs_expression, - const T1& lhs, - const T2& rhs) { - if (lhs == rhs) { - return AssertionSuccess(); - } - - return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs); -} - -// With this overloaded version, we allow anonymous enums to be used -// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums -// can be implicitly cast to BiggestInt. -GTEST_API_ AssertionResult CmpHelperEQ(const char* lhs_expression, - const char* rhs_expression, - BiggestInt lhs, - BiggestInt rhs); - -class EqHelper { - public: - // This templatized version is for the general case. - template < - typename T1, typename T2, - // Disable this overload for cases where one argument is a pointer - // and the other is the null pointer constant. - typename std::enable_if::value || - !std::is_pointer::value>::type* = nullptr> - static AssertionResult Compare(const char* lhs_expression, - const char* rhs_expression, const T1& lhs, - const T2& rhs) { - return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs); - } - - // With this overloaded version, we allow anonymous enums to be used - // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous - // enums can be implicitly cast to BiggestInt. - // - // Even though its body looks the same as the above version, we - // cannot merge the two, as it will make anonymous enums unhappy. - static AssertionResult Compare(const char* lhs_expression, - const char* rhs_expression, - BiggestInt lhs, - BiggestInt rhs) { - return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs); - } - - template - static AssertionResult Compare( - const char* lhs_expression, const char* rhs_expression, - // Handle cases where '0' is used as a null pointer literal. - std::nullptr_t /* lhs */, T* rhs) { - // We already know that 'lhs' is a null pointer. - return CmpHelperEQ(lhs_expression, rhs_expression, static_cast(nullptr), - rhs); - } -}; - -// Separate the error generating code from the code path to reduce the stack -// frame size of CmpHelperOP. This helps reduce the overhead of some sanitizers -// when calling EXPECT_OP in a tight loop. -template -AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2, - const T1& val1, const T2& val2, - const char* op) { - return AssertionFailure() - << "Expected: (" << expr1 << ") " << op << " (" << expr2 - << "), actual: " << FormatForComparisonFailureMessage(val1, val2) - << " vs " << FormatForComparisonFailureMessage(val2, val1); -} - -// A macro for implementing the helper functions needed to implement -// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste -// of similar code. -// -// For each templatized helper function, we also define an overloaded -// version for BiggestInt in order to reduce code bloat and allow -// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled -// with gcc 4. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - -#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ -template \ -AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ - const T1& val1, const T2& val2) {\ - if (val1 op val2) {\ - return AssertionSuccess();\ - } else {\ - return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\ - }\ -}\ -GTEST_API_ AssertionResult CmpHelper##op_name(\ - const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) - -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - -// Implements the helper function for {ASSERT|EXPECT}_NE -GTEST_IMPL_CMP_HELPER_(NE, !=); -// Implements the helper function for {ASSERT|EXPECT}_LE -GTEST_IMPL_CMP_HELPER_(LE, <=); -// Implements the helper function for {ASSERT|EXPECT}_LT -GTEST_IMPL_CMP_HELPER_(LT, <); -// Implements the helper function for {ASSERT|EXPECT}_GE -GTEST_IMPL_CMP_HELPER_(GE, >=); -// Implements the helper function for {ASSERT|EXPECT}_GT -GTEST_IMPL_CMP_HELPER_(GT, >); - -#undef GTEST_IMPL_CMP_HELPER_ - -// The helper function for {ASSERT|EXPECT}_STREQ. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2); - -// The helper function for {ASSERT|EXPECT}_STRCASEEQ. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2); - -// The helper function for {ASSERT|EXPECT}_STRNE. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2); - -// The helper function for {ASSERT|EXPECT}_STRCASENE. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2); - - -// Helper function for *_STREQ on wide strings. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression, - const char* s2_expression, - const wchar_t* s1, - const wchar_t* s2); - -// Helper function for *_STRNE on wide strings. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, - const char* s2_expression, - const wchar_t* s1, - const wchar_t* s2); - -} // namespace internal - -// IsSubstring() and IsNotSubstring() are intended to be used as the -// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by -// themselves. They check whether needle is a substring of haystack -// (NULL is considered a substring of itself only), and return an -// appropriate error message when they fail. -// -// The {needle,haystack}_expr arguments are the stringified -// expressions that generated the two real arguments. -GTEST_API_ AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const char* needle, const char* haystack); -GTEST_API_ AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const wchar_t* needle, const wchar_t* haystack); -GTEST_API_ AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const char* needle, const char* haystack); -GTEST_API_ AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const wchar_t* needle, const wchar_t* haystack); -GTEST_API_ AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::string& needle, const ::std::string& haystack); -GTEST_API_ AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::string& needle, const ::std::string& haystack); - -#if GTEST_HAS_STD_WSTRING -GTEST_API_ AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::wstring& needle, const ::std::wstring& haystack); -GTEST_API_ AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::wstring& needle, const ::std::wstring& haystack); -#endif // GTEST_HAS_STD_WSTRING - -namespace internal { - -// Helper template function for comparing floating-points. -// -// Template parameter: -// -// RawType: the raw floating-point type (either float or double) -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -template -AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression, - const char* rhs_expression, - RawType lhs_value, - RawType rhs_value) { - const FloatingPoint lhs(lhs_value), rhs(rhs_value); - - if (lhs.AlmostEquals(rhs)) { - return AssertionSuccess(); - } - - ::std::stringstream lhs_ss; - lhs_ss << std::setprecision(std::numeric_limits::digits10 + 2) - << lhs_value; - - ::std::stringstream rhs_ss; - rhs_ss << std::setprecision(std::numeric_limits::digits10 + 2) - << rhs_value; - - return EqFailure(lhs_expression, - rhs_expression, - StringStreamToString(&lhs_ss), - StringStreamToString(&rhs_ss), - false); -} - -// Helper function for implementing ASSERT_NEAR. -// -// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, - const char* expr2, - const char* abs_error_expr, - double val1, - double val2, - double abs_error); - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// A class that enables one to stream messages to assertion macros -class GTEST_API_ AssertHelper { - public: - // Constructor. - AssertHelper(TestPartResult::Type type, - const char* file, - int line, - const char* message); - ~AssertHelper(); - - // Message assignment is a semantic trick to enable assertion - // streaming; see the GTEST_MESSAGE_ macro below. - void operator=(const Message& message) const; - - private: - // We put our data in a struct so that the size of the AssertHelper class can - // be as small as possible. This is important because gcc is incapable of - // re-using stack space even for temporary variables, so every EXPECT_EQ - // reserves stack space for another AssertHelper. - struct AssertHelperData { - AssertHelperData(TestPartResult::Type t, - const char* srcfile, - int line_num, - const char* msg) - : type(t), file(srcfile), line(line_num), message(msg) { } - - TestPartResult::Type const type; - const char* const file; - int const line; - std::string const message; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); - }; - - AssertHelperData* const data_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); -}; - -enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; - -GTEST_API_ GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color, - const char* fmt, - ...); - -} // namespace internal - -// The pure interface class that all value-parameterized tests inherit from. -// A value-parameterized class must inherit from both ::testing::Test and -// ::testing::WithParamInterface. In most cases that just means inheriting -// from ::testing::TestWithParam, but more complicated test hierarchies -// may need to inherit from Test and WithParamInterface at different levels. -// -// This interface has support for accessing the test parameter value via -// the GetParam() method. -// -// Use it with one of the parameter generator defining functions, like Range(), -// Values(), ValuesIn(), Bool(), and Combine(). -// -// class FooTest : public ::testing::TestWithParam { -// protected: -// FooTest() { -// // Can use GetParam() here. -// } -// ~FooTest() override { -// // Can use GetParam() here. -// } -// void SetUp() override { -// // Can use GetParam() here. -// } -// void TearDown override { -// // Can use GetParam() here. -// } -// }; -// TEST_P(FooTest, DoesBar) { -// // Can use GetParam() method here. -// Foo foo; -// ASSERT_TRUE(foo.DoesBar(GetParam())); -// } -// INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); - -template -class WithParamInterface { - public: - typedef T ParamType; - virtual ~WithParamInterface() {} - - // The current parameter value. Is also available in the test fixture's - // constructor. - static const ParamType& GetParam() { - GTEST_CHECK_(parameter_ != nullptr) - << "GetParam() can only be called inside a value-parameterized test " - << "-- did you intend to write TEST_P instead of TEST_F?"; - return *parameter_; - } - - private: - // Sets parameter value. The caller is responsible for making sure the value - // remains alive and unchanged throughout the current test. - static void SetParam(const ParamType* parameter) { - parameter_ = parameter; - } - - // Static value used for accessing parameter during a test lifetime. - static const ParamType* parameter_; - - // TestClass must be a subclass of WithParamInterface and Test. - template friend class internal::ParameterizedTestFactory; -}; - -template -const T* WithParamInterface::parameter_ = nullptr; - -// Most value-parameterized classes can ignore the existence of -// WithParamInterface, and can just inherit from ::testing::TestWithParam. - -template -class TestWithParam : public Test, public WithParamInterface { -}; - -// Macros for indicating success/failure in test code. - -// Skips test in runtime. -// Skipping test aborts current function. -// Skipped tests are neither successful nor failed. -#define GTEST_SKIP() GTEST_SKIP_("Skipped") - -// ADD_FAILURE unconditionally adds a failure to the current test. -// SUCCEED generates a success - it doesn't automatically make the -// current test successful, as a test is only successful when it has -// no failure. -// -// EXPECT_* verifies that a certain condition is satisfied. If not, -// it behaves like ADD_FAILURE. In particular: -// -// EXPECT_TRUE verifies that a Boolean condition is true. -// EXPECT_FALSE verifies that a Boolean condition is false. -// -// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except -// that they will also abort the current function on failure. People -// usually want the fail-fast behavior of FAIL and ASSERT_*, but those -// writing data-driven tests often find themselves using ADD_FAILURE -// and EXPECT_* more. - -// Generates a nonfatal failure with a generic message. -#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") - -// Generates a nonfatal failure at the given source file location with -// a generic message. -#define ADD_FAILURE_AT(file, line) \ - GTEST_MESSAGE_AT_(file, line, "Failed", \ - ::testing::TestPartResult::kNonFatalFailure) - -// Generates a fatal failure with a generic message. -#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") - -// Like GTEST_FAIL(), but at the given source file location. -#define GTEST_FAIL_AT(file, line) \ - GTEST_MESSAGE_AT_(file, line, "Failed", \ - ::testing::TestPartResult::kFatalFailure) - -// Define this macro to 1 to omit the definition of FAIL(), which is a -// generic name and clashes with some other libraries. -#if !GTEST_DONT_DEFINE_FAIL -# define FAIL() GTEST_FAIL() -#endif - -// Generates a success with a generic message. -#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") - -// Define this macro to 1 to omit the definition of SUCCEED(), which -// is a generic name and clashes with some other libraries. -#if !GTEST_DONT_DEFINE_SUCCEED -# define SUCCEED() GTEST_SUCCEED() -#endif - -// Macros for testing exceptions. -// -// * {ASSERT|EXPECT}_THROW(statement, expected_exception): -// Tests that the statement throws the expected exception. -// * {ASSERT|EXPECT}_NO_THROW(statement): -// Tests that the statement doesn't throw any exception. -// * {ASSERT|EXPECT}_ANY_THROW(statement): -// Tests that the statement throws an exception. - -#define EXPECT_THROW(statement, expected_exception) \ - GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) -#define EXPECT_NO_THROW(statement) \ - GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) -#define EXPECT_ANY_THROW(statement) \ - GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) -#define ASSERT_THROW(statement, expected_exception) \ - GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) -#define ASSERT_NO_THROW(statement) \ - GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) -#define ASSERT_ANY_THROW(statement) \ - GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) - -// Boolean assertions. Condition can be either a Boolean expression or an -// AssertionResult. For more information on how to use AssertionResult with -// these macros see comments on that class. -#define EXPECT_TRUE(condition) \ - GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ - GTEST_NONFATAL_FAILURE_) -#define EXPECT_FALSE(condition) \ - GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ - GTEST_NONFATAL_FAILURE_) -#define ASSERT_TRUE(condition) \ - GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ - GTEST_FATAL_FAILURE_) -#define ASSERT_FALSE(condition) \ - GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ - GTEST_FATAL_FAILURE_) - -// Macros for testing equalities and inequalities. -// -// * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2 -// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 -// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 -// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 -// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 -// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 -// -// When they are not, Google Test prints both the tested expressions and -// their actual values. The values must be compatible built-in types, -// or you will get a compiler error. By "compatible" we mean that the -// values can be compared by the respective operator. -// -// Note: -// -// 1. It is possible to make a user-defined type work with -// {ASSERT|EXPECT}_??(), but that requires overloading the -// comparison operators and is thus discouraged by the Google C++ -// Usage Guide. Therefore, you are advised to use the -// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are -// equal. -// -// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on -// pointers (in particular, C strings). Therefore, if you use it -// with two C strings, you are testing how their locations in memory -// are related, not how their content is related. To compare two C -// strings by content, use {ASSERT|EXPECT}_STR*(). -// -// 3. {ASSERT|EXPECT}_EQ(v1, v2) is preferred to -// {ASSERT|EXPECT}_TRUE(v1 == v2), as the former tells you -// what the actual value is when it fails, and similarly for the -// other comparisons. -// -// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() -// evaluate their arguments, which is undefined. -// -// 5. These macros evaluate their arguments exactly once. -// -// Examples: -// -// EXPECT_NE(Foo(), 5); -// EXPECT_EQ(a_pointer, NULL); -// ASSERT_LT(i, array_size); -// ASSERT_GT(records.size(), 0) << "There is no record left."; - -#define EXPECT_EQ(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) -#define EXPECT_NE(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) -#define EXPECT_LE(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) -#define EXPECT_LT(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) -#define EXPECT_GE(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) -#define EXPECT_GT(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) - -#define GTEST_ASSERT_EQ(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) -#define GTEST_ASSERT_NE(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) -#define GTEST_ASSERT_LE(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) -#define GTEST_ASSERT_LT(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) -#define GTEST_ASSERT_GE(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) -#define GTEST_ASSERT_GT(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) - -// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of -// ASSERT_XY(), which clashes with some users' own code. - -#if !GTEST_DONT_DEFINE_ASSERT_EQ -# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) -#endif - -#if !GTEST_DONT_DEFINE_ASSERT_NE -# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) -#endif - -#if !GTEST_DONT_DEFINE_ASSERT_LE -# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) -#endif - -#if !GTEST_DONT_DEFINE_ASSERT_LT -# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) -#endif - -#if !GTEST_DONT_DEFINE_ASSERT_GE -# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) -#endif - -#if !GTEST_DONT_DEFINE_ASSERT_GT -# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) -#endif - -// C-string Comparisons. All tests treat NULL and any non-NULL string -// as different. Two NULLs are equal. -// -// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 -// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 -// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case -// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case -// -// For wide or narrow string objects, you can use the -// {ASSERT|EXPECT}_??() macros. -// -// Don't depend on the order in which the arguments are evaluated, -// which is undefined. -// -// These macros evaluate their arguments exactly once. - -#define EXPECT_STREQ(s1, s2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2) -#define EXPECT_STRNE(s1, s2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) -#define EXPECT_STRCASEEQ(s1, s2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2) -#define EXPECT_STRCASENE(s1, s2)\ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) - -#define ASSERT_STREQ(s1, s2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2) -#define ASSERT_STRNE(s1, s2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) -#define ASSERT_STRCASEEQ(s1, s2) \ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2) -#define ASSERT_STRCASENE(s1, s2)\ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) - -// Macros for comparing floating-point numbers. -// -// * {ASSERT|EXPECT}_FLOAT_EQ(val1, val2): -// Tests that two float values are almost equal. -// * {ASSERT|EXPECT}_DOUBLE_EQ(val1, val2): -// Tests that two double values are almost equal. -// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): -// Tests that v1 and v2 are within the given distance to each other. -// -// Google Test uses ULP-based comparison to automatically pick a default -// error bound that is appropriate for the operands. See the -// FloatingPoint template class in gtest-internal.h if you are -// interested in the implementation details. - -#define EXPECT_FLOAT_EQ(val1, val2)\ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ - val1, val2) - -#define EXPECT_DOUBLE_EQ(val1, val2)\ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ - val1, val2) - -#define ASSERT_FLOAT_EQ(val1, val2)\ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ - val1, val2) - -#define ASSERT_DOUBLE_EQ(val1, val2)\ - ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ - val1, val2) - -#define EXPECT_NEAR(val1, val2, abs_error)\ - EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ - val1, val2, abs_error) - -#define ASSERT_NEAR(val1, val2, abs_error)\ - ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ - val1, val2, abs_error) - -// These predicate format functions work on floating-point values, and -// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. -// -// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); - -// Asserts that val1 is less than, or almost equal to, val2. Fails -// otherwise. In particular, it fails if either val1 or val2 is NaN. -GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, - float val1, float val2); -GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, - double val1, double val2); - - -#if GTEST_OS_WINDOWS - -// Macros that test for HRESULT failure and success, these are only useful -// on Windows, and rely on Windows SDK macros and APIs to compile. -// -// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) -// -// When expr unexpectedly fails or succeeds, Google Test prints the -// expected result and the actual result with both a human-readable -// string representation of the error, if available, as well as the -// hex result code. -# define EXPECT_HRESULT_SUCCEEDED(expr) \ - EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) - -# define ASSERT_HRESULT_SUCCEEDED(expr) \ - ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) - -# define EXPECT_HRESULT_FAILED(expr) \ - EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) - -# define ASSERT_HRESULT_FAILED(expr) \ - ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) - -#endif // GTEST_OS_WINDOWS - -// Macros that execute statement and check that it doesn't generate new fatal -// failures in the current thread. -// -// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); -// -// Examples: -// -// EXPECT_NO_FATAL_FAILURE(Process()); -// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; -// -#define ASSERT_NO_FATAL_FAILURE(statement) \ - GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) -#define EXPECT_NO_FATAL_FAILURE(statement) \ - GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) - -// Causes a trace (including the given source file path and line number, -// and the given message) to be included in every test failure message generated -// by code in the scope of the lifetime of an instance of this class. The effect -// is undone with the destruction of the instance. -// -// The message argument can be anything streamable to std::ostream. -// -// Example: -// testing::ScopedTrace trace("file.cc", 123, "message"); -// -class GTEST_API_ ScopedTrace { - public: - // The c'tor pushes the given source file location and message onto - // a trace stack maintained by Google Test. - - // Template version. Uses Message() to convert the values into strings. - // Slow, but flexible. - template - ScopedTrace(const char* file, int line, const T& message) { - PushTrace(file, line, (Message() << message).GetString()); - } - - // Optimize for some known types. - ScopedTrace(const char* file, int line, const char* message) { - PushTrace(file, line, message ? message : "(null)"); - } - - ScopedTrace(const char* file, int line, const std::string& message) { - PushTrace(file, line, message); - } - - // The d'tor pops the info pushed by the c'tor. - // - // Note that the d'tor is not virtual in order to be efficient. - // Don't inherit from ScopedTrace! - ~ScopedTrace(); - - private: - void PushTrace(const char* file, int line, std::string message); - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); -} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its - // c'tor and d'tor. Therefore it doesn't - // need to be used otherwise. - -// Causes a trace (including the source file path, the current line -// number, and the given message) to be included in every test failure -// message generated by code in the current scope. The effect is -// undone when the control leaves the current scope. -// -// The message argument can be anything streamable to std::ostream. -// -// In the implementation, we include the current line number as part -// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s -// to appear in the same block - as long as they are on different -// lines. -// -// Assuming that each thread maintains its own stack of traces. -// Therefore, a SCOPED_TRACE() would (correctly) only affect the -// assertions in its own thread. -#define SCOPED_TRACE(message) \ - ::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ - __FILE__, __LINE__, (message)) - -// Compile-time assertion for type equality. -// StaticAssertTypeEq() compiles if and only if type1 and type2 -// are the same type. The value it returns is not interesting. -// -// Instead of making StaticAssertTypeEq a class template, we make it a -// function template that invokes a helper class template. This -// prevents a user from misusing StaticAssertTypeEq by -// defining objects of that type. -// -// CAVEAT: -// -// When used inside a method of a class template, -// StaticAssertTypeEq() is effective ONLY IF the method is -// instantiated. For example, given: -// -// template class Foo { -// public: -// void Bar() { testing::StaticAssertTypeEq(); } -// }; -// -// the code: -// -// void Test1() { Foo foo; } -// -// will NOT generate a compiler error, as Foo::Bar() is never -// actually instantiated. Instead, you need: -// -// void Test2() { Foo foo; foo.Bar(); } -// -// to cause a compiler error. -template -constexpr bool StaticAssertTypeEq() noexcept { - static_assert(std::is_same::value, - "type1 and type2 are not the same type"); - return true; -} - -// Defines a test. -// -// The first parameter is the name of the test suite, and the second -// parameter is the name of the test within the test suite. -// -// The convention is to end the test suite name with "Test". For -// example, a test suite for the Foo class can be named FooTest. -// -// Test code should appear between braces after an invocation of -// this macro. Example: -// -// TEST(FooTest, InitializesCorrectly) { -// Foo foo; -// EXPECT_TRUE(foo.StatusIsOK()); -// } - -// Note that we call GetTestTypeId() instead of GetTypeId< -// ::testing::Test>() here to get the type ID of testing::Test. This -// is to work around a suspected linker bug when using Google Test as -// a framework on Mac OS X. The bug causes GetTypeId< -// ::testing::Test>() to return different values depending on whether -// the call is from the Google Test framework itself or from user test -// code. GetTestTypeId() is guaranteed to always return the same -// value, as it always calls GetTypeId<>() from the Google Test -// framework. -#define GTEST_TEST(test_suite_name, test_name) \ - GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \ - ::testing::internal::GetTestTypeId()) - -// Define this macro to 1 to omit the definition of TEST(), which -// is a generic name and clashes with some other libraries. -#if !GTEST_DONT_DEFINE_TEST -#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name) -#endif - -// Defines a test that uses a test fixture. -// -// The first parameter is the name of the test fixture class, which -// also doubles as the test suite name. The second parameter is the -// name of the test within the test suite. -// -// A test fixture class must be declared earlier. The user should put -// the test code between braces after using this macro. Example: -// -// class FooTest : public testing::Test { -// protected: -// void SetUp() override { b_.AddElement(3); } -// -// Foo a_; -// Foo b_; -// }; -// -// TEST_F(FooTest, InitializesCorrectly) { -// EXPECT_TRUE(a_.StatusIsOK()); -// } -// -// TEST_F(FooTest, ReturnsElementCountCorrectly) { -// EXPECT_EQ(a_.size(), 0); -// EXPECT_EQ(b_.size(), 1); -// } -// -// GOOGLETEST_CM0011 DO NOT DELETE -#define TEST_F(test_fixture, test_name)\ - GTEST_TEST_(test_fixture, test_name, test_fixture, \ - ::testing::internal::GetTypeId()) - -// Returns a path to temporary directory. -// Tries to determine an appropriate directory for the platform. -GTEST_API_ std::string TempDir(); - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -// Dynamically registers a test with the framework. -// -// This is an advanced API only to be used when the `TEST` macros are -// insufficient. The macros should be preferred when possible, as they avoid -// most of the complexity of calling this function. -// -// The `factory` argument is a factory callable (move-constructible) object or -// function pointer that creates a new instance of the Test object. It -// handles ownership to the caller. The signature of the callable is -// `Fixture*()`, where `Fixture` is the test fixture class for the test. All -// tests registered with the same `test_suite_name` must return the same -// fixture type. This is checked at runtime. -// -// The framework will infer the fixture class from the factory and will call -// the `SetUpTestSuite` and `TearDownTestSuite` for it. -// -// Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is -// undefined. -// -// Use case example: -// -// class MyFixture : public ::testing::Test { -// public: -// // All of these optional, just like in regular macro usage. -// static void SetUpTestSuite() { ... } -// static void TearDownTestSuite() { ... } -// void SetUp() override { ... } -// void TearDown() override { ... } -// }; -// -// class MyTest : public MyFixture { -// public: -// explicit MyTest(int data) : data_(data) {} -// void TestBody() override { ... } -// -// private: -// int data_; -// }; -// -// void RegisterMyTests(const std::vector& values) { -// for (int v : values) { -// ::testing::RegisterTest( -// "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr, -// std::to_string(v).c_str(), -// __FILE__, __LINE__, -// // Important to use the fixture type as the return type here. -// [=]() -> MyFixture* { return new MyTest(v); }); -// } -// } -// ... -// int main(int argc, char** argv) { -// std::vector values_to_test = LoadValuesFromConfig(); -// RegisterMyTests(values_to_test); -// ... -// return RUN_ALL_TESTS(); -// } -// -template -TestInfo* RegisterTest(const char* test_suite_name, const char* test_name, - const char* type_param, const char* value_param, - const char* file, int line, Factory factory) { - using TestT = typename std::remove_pointer::type; - - class FactoryImpl : public internal::TestFactoryBase { - public: - explicit FactoryImpl(Factory f) : factory_(std::move(f)) {} - Test* CreateTest() override { return factory_(); } - - private: - Factory factory_; - }; - - return internal::MakeAndRegisterTestInfo( - test_suite_name, test_name, type_param, value_param, - internal::CodeLocation(file, line), internal::GetTypeId(), - internal::SuiteApiResolver::GetSetUpCaseOrSuite(file, line), - internal::SuiteApiResolver::GetTearDownCaseOrSuite(file, line), - new FactoryImpl{std::move(factory)}); -} - -} // namespace testing - -// Use this function in main() to run all tests. It returns 0 if all -// tests are successful, or 1 otherwise. -// -// RUN_ALL_TESTS() should be invoked after the command line has been -// parsed by InitGoogleTest(). -// -// This function was formerly a macro; thus, it is in the global -// namespace and has an all-caps name. -int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; - -inline int RUN_ALL_TESTS() { - return ::testing::UnitTest::GetInstance()->Run(); -} - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest_pred_impl.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest_pred_impl.h deleted file mode 100644 index d514255c733..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest_pred_impl.h +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2006, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command -// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! -// -// Implements a family of generic predicate assertion macros. -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ - -#include "gtest/gtest.h" - -namespace testing { - -// This header implements a family of generic predicate assertion -// macros: -// -// ASSERT_PRED_FORMAT1(pred_format, v1) -// ASSERT_PRED_FORMAT2(pred_format, v1, v2) -// ... -// -// where pred_format is a function or functor that takes n (in the -// case of ASSERT_PRED_FORMATn) values and their source expression -// text, and returns a testing::AssertionResult. See the definition -// of ASSERT_EQ in gtest.h for an example. -// -// If you don't care about formatting, you can use the more -// restrictive version: -// -// ASSERT_PRED1(pred, v1) -// ASSERT_PRED2(pred, v1, v2) -// ... -// -// where pred is an n-ary function or functor that returns bool, -// and the values v1, v2, ..., must support the << operator for -// streaming to std::ostream. -// -// We also define the EXPECT_* variations. -// -// For now we only support predicates whose arity is at most 5. -// Please email googletestframework@googlegroups.com if you need -// support for higher arities. - -// GTEST_ASSERT_ is the basic statement to which all of the assertions -// in this file reduce. Don't use this in your code. - -#define GTEST_ASSERT_(expression, on_failure) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (const ::testing::AssertionResult gtest_ar = (expression)) \ - ; \ - else \ - on_failure(gtest_ar.failure_message()) - - -// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use -// this in your code. -template -AssertionResult AssertPred1Helper(const char* pred_text, - const char* e1, - Pred pred, - const T1& v1) { - if (pred(v1)) return AssertionSuccess(); - - return AssertionFailure() - << pred_text << "(" << e1 << ") evaluates to false, where" - << "\n" - << e1 << " evaluates to " << ::testing::PrintToString(v1); -} - -// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. -// Don't use this in your code. -#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ - GTEST_ASSERT_(pred_format(#v1, v1), \ - on_failure) - -// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use -// this in your code. -#define GTEST_PRED1_(pred, v1, on_failure)\ - GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ - #v1, \ - pred, \ - v1), on_failure) - -// Unary predicate assertion macros. -#define EXPECT_PRED_FORMAT1(pred_format, v1) \ - GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) -#define EXPECT_PRED1(pred, v1) \ - GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) -#define ASSERT_PRED_FORMAT1(pred_format, v1) \ - GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) -#define ASSERT_PRED1(pred, v1) \ - GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) - - - -// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use -// this in your code. -template -AssertionResult AssertPred2Helper(const char* pred_text, - const char* e1, - const char* e2, - Pred pred, - const T1& v1, - const T2& v2) { - if (pred(v1, v2)) return AssertionSuccess(); - - return AssertionFailure() - << pred_text << "(" << e1 << ", " << e2 - << ") evaluates to false, where" - << "\n" - << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" - << e2 << " evaluates to " << ::testing::PrintToString(v2); -} - -// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. -// Don't use this in your code. -#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ - GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ - on_failure) - -// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use -// this in your code. -#define GTEST_PRED2_(pred, v1, v2, on_failure)\ - GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ - #v1, \ - #v2, \ - pred, \ - v1, \ - v2), on_failure) - -// Binary predicate assertion macros. -#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ - GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) -#define EXPECT_PRED2(pred, v1, v2) \ - GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) -#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ - GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) -#define ASSERT_PRED2(pred, v1, v2) \ - GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) - - - -// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use -// this in your code. -template -AssertionResult AssertPred3Helper(const char* pred_text, - const char* e1, - const char* e2, - const char* e3, - Pred pred, - const T1& v1, - const T2& v2, - const T3& v3) { - if (pred(v1, v2, v3)) return AssertionSuccess(); - - return AssertionFailure() - << pred_text << "(" << e1 << ", " << e2 << ", " << e3 - << ") evaluates to false, where" - << "\n" - << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" - << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n" - << e3 << " evaluates to " << ::testing::PrintToString(v3); -} - -// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. -// Don't use this in your code. -#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ - GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ - on_failure) - -// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use -// this in your code. -#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ - GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ - #v1, \ - #v2, \ - #v3, \ - pred, \ - v1, \ - v2, \ - v3), on_failure) - -// Ternary predicate assertion macros. -#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ - GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) -#define EXPECT_PRED3(pred, v1, v2, v3) \ - GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) -#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ - GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) -#define ASSERT_PRED3(pred, v1, v2, v3) \ - GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) - - - -// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use -// this in your code. -template -AssertionResult AssertPred4Helper(const char* pred_text, - const char* e1, - const char* e2, - const char* e3, - const char* e4, - Pred pred, - const T1& v1, - const T2& v2, - const T3& v3, - const T4& v4) { - if (pred(v1, v2, v3, v4)) return AssertionSuccess(); - - return AssertionFailure() - << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4 - << ") evaluates to false, where" - << "\n" - << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" - << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n" - << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n" - << e4 << " evaluates to " << ::testing::PrintToString(v4); -} - -// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. -// Don't use this in your code. -#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ - GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ - on_failure) - -// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use -// this in your code. -#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ - GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ - #v1, \ - #v2, \ - #v3, \ - #v4, \ - pred, \ - v1, \ - v2, \ - v3, \ - v4), on_failure) - -// 4-ary predicate assertion macros. -#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ - GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) -#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ - GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) -#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ - GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) -#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ - GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) - - - -// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use -// this in your code. -template -AssertionResult AssertPred5Helper(const char* pred_text, - const char* e1, - const char* e2, - const char* e3, - const char* e4, - const char* e5, - Pred pred, - const T1& v1, - const T2& v2, - const T3& v3, - const T4& v4, - const T5& v5) { - if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); - - return AssertionFailure() - << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4 - << ", " << e5 << ") evaluates to false, where" - << "\n" - << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" - << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n" - << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n" - << e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n" - << e5 << " evaluates to " << ::testing::PrintToString(v5); -} - -// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. -// Don't use this in your code. -#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ - GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ - on_failure) - -// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use -// this in your code. -#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ - GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ - #v1, \ - #v2, \ - #v3, \ - #v4, \ - #v5, \ - pred, \ - v1, \ - v2, \ - v3, \ - v4, \ - v5), on_failure) - -// 5-ary predicate assertion macros. -#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ - GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) -#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ - GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) -#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ - GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) -#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ - GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) - - - -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest_prod.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest_prod.h deleted file mode 100644 index e651671ebde..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/gtest_prod.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2006, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// Google C++ Testing and Mocking Framework definitions useful in production code. -// GOOGLETEST_CM0003 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ - -// When you need to test the private or protected members of a class, -// use the FRIEND_TEST macro to declare your tests as friends of the -// class. For example: -// -// class MyClass { -// private: -// void PrivateMethod(); -// FRIEND_TEST(MyClassTest, PrivateMethodWorks); -// }; -// -// class MyClassTest : public testing::Test { -// // ... -// }; -// -// TEST_F(MyClassTest, PrivateMethodWorks) { -// // Can call MyClass::PrivateMethod() here. -// } -// -// Note: The test class must be in the same namespace as the class being tested. -// For example, putting MyClassTest in an anonymous namespace will not work. - -#define FRIEND_TEST(test_case_name, test_name)\ -friend class test_case_name##_##test_name##_Test - -#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/README.md b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/README.md deleted file mode 100644 index ff391fb4e2b..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Customization Points - -The custom directory is an injection point for custom user configurations. - -## Header `gtest.h` - -### The following macros can be defined: - -* `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of - `OsStackTraceGetterInterface`. -* `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See - `testing::TempDir` for semantics and signature. - -## Header `gtest-port.h` - -The following macros can be defined: - -### Flag related macros: - -* `GTEST_FLAG(flag_name)` -* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its - own flagfile flag parsing. -* `GTEST_DECLARE_bool_(name)` -* `GTEST_DECLARE_int32_(name)` -* `GTEST_DECLARE_string_(name)` -* `GTEST_DEFINE_bool_(name, default_val, doc)` -* `GTEST_DEFINE_int32_(name, default_val, doc)` -* `GTEST_DEFINE_string_(name, default_val, doc)` - -### Logging: - -* `GTEST_LOG_(severity)` -* `GTEST_CHECK_(condition)` -* Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too. - -### Threading: - -* `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided. -* `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal` - are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)` - and `GTEST_DEFINE_STATIC_MUTEX_(mutex)` -* `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)` -* `GTEST_LOCK_EXCLUDED_(locks)` - -### Underlying library support features - -* `GTEST_HAS_CXXABI_H_` - -### Exporting API symbols: - -* `GTEST_API_` - Specifier for exported symbols. - -## Header `gtest-printers.h` - -* See documentation at `gtest/gtest-printers.h` for details on how to define a - custom printer. diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest-port.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest-port.h deleted file mode 100644 index cd85d956d2d..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest-port.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// Injection point for custom user configurations. See README for details -// -// ** Custom implementation starts here ** - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest-printers.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest-printers.h deleted file mode 100644 index eb4467abcab..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest-printers.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// This file provides an injection point for custom printers in a local -// installation of gTest. -// It will be included from gtest-printers.h and the overrides in this file -// will be visible to everyone. -// -// Injection point for custom user configurations. See README for details -// -// ** Custom implementation starts here ** - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest.h deleted file mode 100644 index 4c8e07be23f..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/custom/gtest.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// Injection point for custom user configurations. See README for details -// -// ** Custom implementation starts here ** - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-death-test-internal.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-death-test-internal.h deleted file mode 100644 index 68bd3530618..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-death-test-internal.h +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file defines internal utilities needed for implementing -// death tests. They are subject to change without notice. -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ - -#include "gtest/gtest-matchers.h" -#include "gtest/internal/gtest-internal.h" - -#include -#include - -namespace testing { -namespace internal { - -GTEST_DECLARE_string_(internal_run_death_test); - -// Names of the flags (needed for parsing Google Test flags). -const char kDeathTestStyleFlag[] = "death_test_style"; -const char kDeathTestUseFork[] = "death_test_use_fork"; -const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; - -#if GTEST_HAS_DEATH_TEST - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -// DeathTest is a class that hides much of the complexity of the -// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method -// returns a concrete class that depends on the prevailing death test -// style, as defined by the --gtest_death_test_style and/or -// --gtest_internal_run_death_test flags. - -// In describing the results of death tests, these terms are used with -// the corresponding definitions: -// -// exit status: The integer exit information in the format specified -// by wait(2) -// exit code: The integer code passed to exit(3), _exit(2), or -// returned from main() -class GTEST_API_ DeathTest { - public: - // Create returns false if there was an error determining the - // appropriate action to take for the current death test; for example, - // if the gtest_death_test_style flag is set to an invalid value. - // The LastMessage method will return a more detailed message in that - // case. Otherwise, the DeathTest pointer pointed to by the "test" - // argument is set. If the death test should be skipped, the pointer - // is set to NULL; otherwise, it is set to the address of a new concrete - // DeathTest object that controls the execution of the current test. - static bool Create(const char* statement, Matcher matcher, - const char* file, int line, DeathTest** test); - DeathTest(); - virtual ~DeathTest() { } - - // A helper class that aborts a death test when it's deleted. - class ReturnSentinel { - public: - explicit ReturnSentinel(DeathTest* test) : test_(test) { } - ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } - private: - DeathTest* const test_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); - } GTEST_ATTRIBUTE_UNUSED_; - - // An enumeration of possible roles that may be taken when a death - // test is encountered. EXECUTE means that the death test logic should - // be executed immediately. OVERSEE means that the program should prepare - // the appropriate environment for a child process to execute the death - // test, then wait for it to complete. - enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; - - // An enumeration of the three reasons that a test might be aborted. - enum AbortReason { - TEST_ENCOUNTERED_RETURN_STATEMENT, - TEST_THREW_EXCEPTION, - TEST_DID_NOT_DIE - }; - - // Assumes one of the above roles. - virtual TestRole AssumeRole() = 0; - - // Waits for the death test to finish and returns its status. - virtual int Wait() = 0; - - // Returns true if the death test passed; that is, the test process - // exited during the test, its exit status matches a user-supplied - // predicate, and its stderr output matches a user-supplied regular - // expression. - // The user-supplied predicate may be a macro expression rather - // than a function pointer or functor, or else Wait and Passed could - // be combined. - virtual bool Passed(bool exit_status_ok) = 0; - - // Signals that the death test did not die as expected. - virtual void Abort(AbortReason reason) = 0; - - // Returns a human-readable outcome message regarding the outcome of - // the last death test. - static const char* LastMessage(); - - static void set_last_death_test_message(const std::string& message); - - private: - // A string containing a description of the outcome of the last death test. - static std::string last_death_test_message_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); -}; - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -// Factory interface for death tests. May be mocked out for testing. -class DeathTestFactory { - public: - virtual ~DeathTestFactory() { } - virtual bool Create(const char* statement, - Matcher matcher, const char* file, - int line, DeathTest** test) = 0; -}; - -// A concrete DeathTestFactory implementation for normal use. -class DefaultDeathTestFactory : public DeathTestFactory { - public: - bool Create(const char* statement, Matcher matcher, - const char* file, int line, DeathTest** test) override; -}; - -// Returns true if exit_status describes a process that was terminated -// by a signal, or exited normally with a nonzero exit code. -GTEST_API_ bool ExitedUnsuccessfully(int exit_status); - -// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads -// and interpreted as a regex (rather than an Eq matcher) for legacy -// compatibility. -inline Matcher MakeDeathTestMatcher( - ::testing::internal::RE regex) { - return ContainsRegex(regex.pattern()); -} -inline Matcher MakeDeathTestMatcher(const char* regex) { - return ContainsRegex(regex); -} -inline Matcher MakeDeathTestMatcher( - const ::std::string& regex) { - return ContainsRegex(regex); -} - -// If a Matcher is passed to EXPECT_DEATH (etc.), it's -// used directly. -inline Matcher MakeDeathTestMatcher( - Matcher matcher) { - return matcher; -} - -// Traps C++ exceptions escaping statement and reports them as test -// failures. Note that trapping SEH exceptions is not implemented here. -# if GTEST_HAS_EXCEPTIONS -# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ - try { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } catch (const ::std::exception& gtest_exception) { \ - fprintf(\ - stderr, \ - "\n%s: Caught std::exception-derived exception escaping the " \ - "death test statement. Exception message: %s\n", \ - ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ - gtest_exception.what()); \ - fflush(stderr); \ - death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ - } catch (...) { \ - death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ - } - -# else -# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) - -# endif - -// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, -// ASSERT_EXIT*, and EXPECT_EXIT*. -#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - ::testing::internal::DeathTest* gtest_dt; \ - if (!::testing::internal::DeathTest::Create( \ - #statement, \ - ::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \ - __FILE__, __LINE__, >est_dt)) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ - } \ - if (gtest_dt != nullptr) { \ - std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \ - switch (gtest_dt->AssumeRole()) { \ - case ::testing::internal::DeathTest::OVERSEE_TEST: \ - if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ - } \ - break; \ - case ::testing::internal::DeathTest::EXECUTE_TEST: { \ - ::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \ - gtest_dt); \ - GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ - gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ - break; \ - } \ - default: \ - break; \ - } \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \ - : fail(::testing::internal::DeathTest::LastMessage()) -// The symbol "fail" here expands to something into which a message -// can be streamed. - -// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in -// NDEBUG mode. In this case we need the statements to be executed and the macro -// must accept a streamed message even though the message is never printed. -// The regex object is not evaluated, but it is used to prevent "unused" -// warnings and to avoid an expression that doesn't compile in debug mode. -#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } else if (!::testing::internal::AlwaysTrue()) { \ - ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \ - } else \ - ::testing::Message() - -// A class representing the parsed contents of the -// --gtest_internal_run_death_test flag, as it existed when -// RUN_ALL_TESTS was called. -class InternalRunDeathTestFlag { - public: - InternalRunDeathTestFlag(const std::string& a_file, - int a_line, - int an_index, - int a_write_fd) - : file_(a_file), line_(a_line), index_(an_index), - write_fd_(a_write_fd) {} - - ~InternalRunDeathTestFlag() { - if (write_fd_ >= 0) - posix::Close(write_fd_); - } - - const std::string& file() const { return file_; } - int line() const { return line_; } - int index() const { return index_; } - int write_fd() const { return write_fd_; } - - private: - std::string file_; - int line_; - int index_; - int write_fd_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); -}; - -// Returns a newly created InternalRunDeathTestFlag object with fields -// initialized from the GTEST_FLAG(internal_run_death_test) flag if -// the flag is specified; otherwise returns NULL. -InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); - -#endif // GTEST_HAS_DEATH_TEST - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-filepath.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-filepath.h deleted file mode 100644 index c11b101516e..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-filepath.h +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// Google Test filepath utilities -// -// This header file declares classes and functions used internally by -// Google Test. They are subject to change without notice. -// -// This file is #included in gtest/internal/gtest-internal.h. -// Do not include this header file separately! - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ - -#include "gtest/internal/gtest-string.h" - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -namespace testing { -namespace internal { - -// FilePath - a class for file and directory pathname manipulation which -// handles platform-specific conventions (like the pathname separator). -// Used for helper functions for naming files in a directory for xml output. -// Except for Set methods, all methods are const or static, which provides an -// "immutable value object" -- useful for peace of mind. -// A FilePath with a value ending in a path separator ("like/this/") represents -// a directory, otherwise it is assumed to represent a file. In either case, -// it may or may not represent an actual file or directory in the file system. -// Names are NOT checked for syntax correctness -- no checking for illegal -// characters, malformed paths, etc. - -class GTEST_API_ FilePath { - public: - FilePath() : pathname_("") { } - FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } - - explicit FilePath(const std::string& pathname) : pathname_(pathname) { - Normalize(); - } - - FilePath& operator=(const FilePath& rhs) { - Set(rhs); - return *this; - } - - void Set(const FilePath& rhs) { - pathname_ = rhs.pathname_; - } - - const std::string& string() const { return pathname_; } - const char* c_str() const { return pathname_.c_str(); } - - // Returns the current working directory, or "" if unsuccessful. - static FilePath GetCurrentDir(); - - // Given directory = "dir", base_name = "test", number = 0, - // extension = "xml", returns "dir/test.xml". If number is greater - // than zero (e.g., 12), returns "dir/test_12.xml". - // On Windows platform, uses \ as the separator rather than /. - static FilePath MakeFileName(const FilePath& directory, - const FilePath& base_name, - int number, - const char* extension); - - // Given directory = "dir", relative_path = "test.xml", - // returns "dir/test.xml". - // On Windows, uses \ as the separator rather than /. - static FilePath ConcatPaths(const FilePath& directory, - const FilePath& relative_path); - - // Returns a pathname for a file that does not currently exist. The pathname - // will be directory/base_name.extension or - // directory/base_name_.extension if directory/base_name.extension - // already exists. The number will be incremented until a pathname is found - // that does not already exist. - // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. - // There could be a race condition if two or more processes are calling this - // function at the same time -- they could both pick the same filename. - static FilePath GenerateUniqueFileName(const FilePath& directory, - const FilePath& base_name, - const char* extension); - - // Returns true if and only if the path is "". - bool IsEmpty() const { return pathname_.empty(); } - - // If input name has a trailing separator character, removes it and returns - // the name, otherwise return the name string unmodified. - // On Windows platform, uses \ as the separator, other platforms use /. - FilePath RemoveTrailingPathSeparator() const; - - // Returns a copy of the FilePath with the directory part removed. - // Example: FilePath("path/to/file").RemoveDirectoryName() returns - // FilePath("file"). If there is no directory part ("just_a_file"), it returns - // the FilePath unmodified. If there is no file part ("just_a_dir/") it - // returns an empty FilePath (""). - // On Windows platform, '\' is the path separator, otherwise it is '/'. - FilePath RemoveDirectoryName() const; - - // RemoveFileName returns the directory path with the filename removed. - // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". - // If the FilePath is "a_file" or "/a_file", RemoveFileName returns - // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does - // not have a file, like "just/a/dir/", it returns the FilePath unmodified. - // On Windows platform, '\' is the path separator, otherwise it is '/'. - FilePath RemoveFileName() const; - - // Returns a copy of the FilePath with the case-insensitive extension removed. - // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns - // FilePath("dir/file"). If a case-insensitive extension is not - // found, returns a copy of the original FilePath. - FilePath RemoveExtension(const char* extension) const; - - // Creates directories so that path exists. Returns true if successful or if - // the directories already exist; returns false if unable to create - // directories for any reason. Will also return false if the FilePath does - // not represent a directory (that is, it doesn't end with a path separator). - bool CreateDirectoriesRecursively() const; - - // Create the directory so that path exists. Returns true if successful or - // if the directory already exists; returns false if unable to create the - // directory for any reason, including if the parent directory does not - // exist. Not named "CreateDirectory" because that's a macro on Windows. - bool CreateFolder() const; - - // Returns true if FilePath describes something in the file-system, - // either a file, directory, or whatever, and that something exists. - bool FileOrDirectoryExists() const; - - // Returns true if pathname describes a directory in the file-system - // that exists. - bool DirectoryExists() const; - - // Returns true if FilePath ends with a path separator, which indicates that - // it is intended to represent a directory. Returns false otherwise. - // This does NOT check that a directory (or file) actually exists. - bool IsDirectory() const; - - // Returns true if pathname describes a root directory. (Windows has one - // root directory per disk drive.) - bool IsRootDirectory() const; - - // Returns true if pathname describes an absolute path. - bool IsAbsolutePath() const; - - private: - // Replaces multiple consecutive separators with a single separator. - // For example, "bar///foo" becomes "bar/foo". Does not eliminate other - // redundancies that might be in a pathname involving "." or "..". - // - // A pathname with multiple consecutive separators may occur either through - // user error or as a result of some scripts or APIs that generate a pathname - // with a trailing separator. On other platforms the same API or script - // may NOT generate a pathname with a trailing "/". Then elsewhere that - // pathname may have another "/" and pathname components added to it, - // without checking for the separator already being there. - // The script language and operating system may allow paths like "foo//bar" - // but some of the functions in FilePath will not handle that correctly. In - // particular, RemoveTrailingPathSeparator() only removes one separator, and - // it is called in CreateDirectoriesRecursively() assuming that it will change - // a pathname from directory syntax (trailing separator) to filename syntax. - // - // On Windows this method also replaces the alternate path separator '/' with - // the primary path separator '\\', so that for example "bar\\/\\foo" becomes - // "bar\\foo". - - void Normalize(); - - // Returns a pointer to the last occurence of a valid path separator in - // the FilePath. On Windows, for example, both '/' and '\' are valid path - // separators. Returns NULL if no path separator was found. - const char* FindLastPathSeparator() const; - - std::string pathname_; -}; // class FilePath - -} // namespace internal -} // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-internal.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-internal.h deleted file mode 100644 index 94c816a28bd..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-internal.h +++ /dev/null @@ -1,1380 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file declares functions and macros used internally by -// Google Test. They are subject to change without notice. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ - -#include "gtest/internal/gtest-port.h" - -#if GTEST_OS_LINUX -# include -# include -# include -# include -#endif // GTEST_OS_LINUX - -#if GTEST_HAS_EXCEPTIONS -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gtest/gtest-message.h" -#include "gtest/internal/gtest-filepath.h" -#include "gtest/internal/gtest-string.h" -#include "gtest/internal/gtest-type-util.h" - -// Due to C++ preprocessor weirdness, we need double indirection to -// concatenate two tokens when one of them is __LINE__. Writing -// -// foo ## __LINE__ -// -// will result in the token foo__LINE__, instead of foo followed by -// the current line number. For more details, see -// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 -#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) -#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar - -// Stringifies its argument. -#define GTEST_STRINGIFY_(name) #name - -namespace proto2 { class Message; } - -namespace testing { - -// Forward declarations. - -class AssertionResult; // Result of an assertion. -class Message; // Represents a failure message. -class Test; // Represents a test. -class TestInfo; // Information about a test. -class TestPartResult; // Result of a test part. -class UnitTest; // A collection of test suites. - -template -::std::string PrintToString(const T& value); - -namespace internal { - -struct TraceInfo; // Information about a trace point. -class TestInfoImpl; // Opaque implementation of TestInfo -class UnitTestImpl; // Opaque implementation of UnitTest - -// The text used in failure messages to indicate the start of the -// stack trace. -GTEST_API_ extern const char kStackTraceMarker[]; - -// An IgnoredValue object can be implicitly constructed from ANY value. -class IgnoredValue { - struct Sink {}; - public: - // This constructor template allows any value to be implicitly - // converted to IgnoredValue. The object has no data member and - // doesn't try to remember anything about the argument. We - // deliberately omit the 'explicit' keyword in order to allow the - // conversion to be implicit. - // Disable the conversion if T already has a magical conversion operator. - // Otherwise we get ambiguity. - template ::value, - int>::type = 0> - IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit) -}; - -// Appends the user-supplied message to the Google-Test-generated message. -GTEST_API_ std::string AppendUserMessage( - const std::string& gtest_msg, const Message& user_msg); - -#if GTEST_HAS_EXCEPTIONS - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4275 \ -/* an exported class was derived from a class that was not exported */) - -// This exception is thrown by (and only by) a failed Google Test -// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions -// are enabled). We derive it from std::runtime_error, which is for -// errors presumably detectable only at run time. Since -// std::runtime_error inherits from std::exception, many testing -// frameworks know how to extract and print the message inside it. -class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { - public: - explicit GoogleTestFailureException(const TestPartResult& failure); -}; - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4275 - -#endif // GTEST_HAS_EXCEPTIONS - -namespace edit_distance { -// Returns the optimal edits to go from 'left' to 'right'. -// All edits cost the same, with replace having lower priority than -// add/remove. -// Simple implementation of the Wagner-Fischer algorithm. -// See http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm -enum EditType { kMatch, kAdd, kRemove, kReplace }; -GTEST_API_ std::vector CalculateOptimalEdits( - const std::vector& left, const std::vector& right); - -// Same as above, but the input is represented as strings. -GTEST_API_ std::vector CalculateOptimalEdits( - const std::vector& left, - const std::vector& right); - -// Create a diff of the input strings in Unified diff format. -GTEST_API_ std::string CreateUnifiedDiff(const std::vector& left, - const std::vector& right, - size_t context = 2); - -} // namespace edit_distance - -// Calculate the diff between 'left' and 'right' and return it in unified diff -// format. -// If not null, stores in 'total_line_count' the total number of lines found -// in left + right. -GTEST_API_ std::string DiffStrings(const std::string& left, - const std::string& right, - size_t* total_line_count); - -// Constructs and returns the message for an equality assertion -// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. -// -// The first four parameters are the expressions used in the assertion -// and their values, as strings. For example, for ASSERT_EQ(foo, bar) -// where foo is 5 and bar is 6, we have: -// -// expected_expression: "foo" -// actual_expression: "bar" -// expected_value: "5" -// actual_value: "6" -// -// The ignoring_case parameter is true if and only if the assertion is a -// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will -// be inserted into the message. -GTEST_API_ AssertionResult EqFailure(const char* expected_expression, - const char* actual_expression, - const std::string& expected_value, - const std::string& actual_value, - bool ignoring_case); - -// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. -GTEST_API_ std::string GetBoolAssertionFailureMessage( - const AssertionResult& assertion_result, - const char* expression_text, - const char* actual_predicate_value, - const char* expected_predicate_value); - -// This template class represents an IEEE floating-point number -// (either single-precision or double-precision, depending on the -// template parameters). -// -// The purpose of this class is to do more sophisticated number -// comparison. (Due to round-off error, etc, it's very unlikely that -// two floating-points will be equal exactly. Hence a naive -// comparison by the == operation often doesn't work.) -// -// Format of IEEE floating-point: -// -// The most-significant bit being the leftmost, an IEEE -// floating-point looks like -// -// sign_bit exponent_bits fraction_bits -// -// Here, sign_bit is a single bit that designates the sign of the -// number. -// -// For float, there are 8 exponent bits and 23 fraction bits. -// -// For double, there are 11 exponent bits and 52 fraction bits. -// -// More details can be found at -// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. -// -// Template parameter: -// -// RawType: the raw floating-point type (either float or double) -template -class FloatingPoint { - public: - // Defines the unsigned integer type that has the same size as the - // floating point number. - typedef typename TypeWithSize::UInt Bits; - - // Constants. - - // # of bits in a number. - static const size_t kBitCount = 8*sizeof(RawType); - - // # of fraction bits in a number. - static const size_t kFractionBitCount = - std::numeric_limits::digits - 1; - - // # of exponent bits in a number. - static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; - - // The mask for the sign bit. - static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); - - // The mask for the fraction bits. - static const Bits kFractionBitMask = - ~static_cast(0) >> (kExponentBitCount + 1); - - // The mask for the exponent bits. - static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); - - // How many ULP's (Units in the Last Place) we want to tolerate when - // comparing two numbers. The larger the value, the more error we - // allow. A 0 value means that two numbers must be exactly the same - // to be considered equal. - // - // The maximum error of a single floating-point operation is 0.5 - // units in the last place. On Intel CPU's, all floating-point - // calculations are done with 80-bit precision, while double has 64 - // bits. Therefore, 4 should be enough for ordinary use. - // - // See the following article for more details on ULP: - // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - static const size_t kMaxUlps = 4; - - // Constructs a FloatingPoint from a raw floating-point number. - // - // On an Intel CPU, passing a non-normalized NAN (Not a Number) - // around may change its bits, although the new value is guaranteed - // to be also a NAN. Therefore, don't expect this constructor to - // preserve the bits in x when x is a NAN. - explicit FloatingPoint(const RawType& x) { u_.value_ = x; } - - // Static methods - - // Reinterprets a bit pattern as a floating-point number. - // - // This function is needed to test the AlmostEquals() method. - static RawType ReinterpretBits(const Bits bits) { - FloatingPoint fp(0); - fp.u_.bits_ = bits; - return fp.u_.value_; - } - - // Returns the floating-point number that represent positive infinity. - static RawType Infinity() { - return ReinterpretBits(kExponentBitMask); - } - - // Returns the maximum representable finite floating-point number. - static RawType Max(); - - // Non-static methods - - // Returns the bits that represents this number. - const Bits &bits() const { return u_.bits_; } - - // Returns the exponent bits of this number. - Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } - - // Returns the fraction bits of this number. - Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } - - // Returns the sign bit of this number. - Bits sign_bit() const { return kSignBitMask & u_.bits_; } - - // Returns true if and only if this is NAN (not a number). - bool is_nan() const { - // It's a NAN if the exponent bits are all ones and the fraction - // bits are not entirely zeros. - return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); - } - - // Returns true if and only if this number is at most kMaxUlps ULP's away - // from rhs. In particular, this function: - // - // - returns false if either number is (or both are) NAN. - // - treats really large numbers as almost equal to infinity. - // - thinks +0.0 and -0.0 are 0 DLP's apart. - bool AlmostEquals(const FloatingPoint& rhs) const { - // The IEEE standard says that any comparison operation involving - // a NAN must return false. - if (is_nan() || rhs.is_nan()) return false; - - return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) - <= kMaxUlps; - } - - private: - // The data type used to store the actual floating-point number. - union FloatingPointUnion { - RawType value_; // The raw floating-point number. - Bits bits_; // The bits that represent the number. - }; - - // Converts an integer from the sign-and-magnitude representation to - // the biased representation. More precisely, let N be 2 to the - // power of (kBitCount - 1), an integer x is represented by the - // unsigned number x + N. - // - // For instance, - // - // -N + 1 (the most negative number representable using - // sign-and-magnitude) is represented by 1; - // 0 is represented by N; and - // N - 1 (the biggest number representable using - // sign-and-magnitude) is represented by 2N - 1. - // - // Read http://en.wikipedia.org/wiki/Signed_number_representations - // for more details on signed number representations. - static Bits SignAndMagnitudeToBiased(const Bits &sam) { - if (kSignBitMask & sam) { - // sam represents a negative number. - return ~sam + 1; - } else { - // sam represents a positive number. - return kSignBitMask | sam; - } - } - - // Given two numbers in the sign-and-magnitude representation, - // returns the distance between them as an unsigned number. - static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, - const Bits &sam2) { - const Bits biased1 = SignAndMagnitudeToBiased(sam1); - const Bits biased2 = SignAndMagnitudeToBiased(sam2); - return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); - } - - FloatingPointUnion u_; -}; - -// We cannot use std::numeric_limits::max() as it clashes with the max() -// macro defined by . -template <> -inline float FloatingPoint::Max() { return FLT_MAX; } -template <> -inline double FloatingPoint::Max() { return DBL_MAX; } - -// Typedefs the instances of the FloatingPoint template class that we -// care to use. -typedef FloatingPoint Float; -typedef FloatingPoint Double; - -// In order to catch the mistake of putting tests that use different -// test fixture classes in the same test suite, we need to assign -// unique IDs to fixture classes and compare them. The TypeId type is -// used to hold such IDs. The user should treat TypeId as an opaque -// type: the only operation allowed on TypeId values is to compare -// them for equality using the == operator. -typedef const void* TypeId; - -template -class TypeIdHelper { - public: - // dummy_ must not have a const type. Otherwise an overly eager - // compiler (e.g. MSVC 7.1 & 8.0) may try to merge - // TypeIdHelper::dummy_ for different Ts as an "optimization". - static bool dummy_; -}; - -template -bool TypeIdHelper::dummy_ = false; - -// GetTypeId() returns the ID of type T. Different values will be -// returned for different types. Calling the function twice with the -// same type argument is guaranteed to return the same ID. -template -TypeId GetTypeId() { - // The compiler is required to allocate a different - // TypeIdHelper::dummy_ variable for each T used to instantiate - // the template. Therefore, the address of dummy_ is guaranteed to - // be unique. - return &(TypeIdHelper::dummy_); -} - -// Returns the type ID of ::testing::Test. Always call this instead -// of GetTypeId< ::testing::Test>() to get the type ID of -// ::testing::Test, as the latter may give the wrong result due to a -// suspected linker bug when compiling Google Test as a Mac OS X -// framework. -GTEST_API_ TypeId GetTestTypeId(); - -// Defines the abstract factory interface that creates instances -// of a Test object. -class TestFactoryBase { - public: - virtual ~TestFactoryBase() {} - - // Creates a test instance to run. The instance is both created and destroyed - // within TestInfoImpl::Run() - virtual Test* CreateTest() = 0; - - protected: - TestFactoryBase() {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); -}; - -// This class provides implementation of TeastFactoryBase interface. -// It is used in TEST and TEST_F macros. -template -class TestFactoryImpl : public TestFactoryBase { - public: - Test* CreateTest() override { return new TestClass; } -}; - -#if GTEST_OS_WINDOWS - -// Predicate-formatters for implementing the HRESULT checking macros -// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} -// We pass a long instead of HRESULT to avoid causing an -// include dependency for the HRESULT type. -GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, - long hr); // NOLINT -GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, - long hr); // NOLINT - -#endif // GTEST_OS_WINDOWS - -// Types of SetUpTestSuite() and TearDownTestSuite() functions. -using SetUpTestSuiteFunc = void (*)(); -using TearDownTestSuiteFunc = void (*)(); - -struct CodeLocation { - CodeLocation(const std::string& a_file, int a_line) - : file(a_file), line(a_line) {} - - std::string file; - int line; -}; - -// Helper to identify which setup function for TestCase / TestSuite to call. -// Only one function is allowed, either TestCase or TestSute but not both. - -// Utility functions to help SuiteApiResolver -using SetUpTearDownSuiteFuncType = void (*)(); - -inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull( - SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) { - return a == def ? nullptr : a; -} - -template -// Note that SuiteApiResolver inherits from T because -// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way -// SuiteApiResolver can access them. -struct SuiteApiResolver : T { - // testing::Test is only forward declared at this point. So we make it a - // dependend class for the compiler to be OK with it. - using Test = - typename std::conditional::type; - - static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename, - int line_num) { - SetUpTearDownSuiteFuncType test_case_fp = - GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase); - SetUpTearDownSuiteFuncType test_suite_fp = - GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite); - - GTEST_CHECK_(!test_case_fp || !test_suite_fp) - << "Test can not provide both SetUpTestSuite and SetUpTestCase, please " - "make sure there is only one present at " - << filename << ":" << line_num; - - return test_case_fp != nullptr ? test_case_fp : test_suite_fp; - } - - static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename, - int line_num) { - SetUpTearDownSuiteFuncType test_case_fp = - GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase); - SetUpTearDownSuiteFuncType test_suite_fp = - GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite); - - GTEST_CHECK_(!test_case_fp || !test_suite_fp) - << "Test can not provide both TearDownTestSuite and TearDownTestCase," - " please make sure there is only one present at" - << filename << ":" << line_num; - - return test_case_fp != nullptr ? test_case_fp : test_suite_fp; - } -}; - -// Creates a new TestInfo object and registers it with Google Test; -// returns the created object. -// -// Arguments: -// -// test_suite_name: name of the test suite -// name: name of the test -// type_param the name of the test's type parameter, or NULL if -// this is not a typed or a type-parameterized test. -// value_param text representation of the test's value parameter, -// or NULL if this is not a type-parameterized test. -// code_location: code location where the test is defined -// fixture_class_id: ID of the test fixture class -// set_up_tc: pointer to the function that sets up the test suite -// tear_down_tc: pointer to the function that tears down the test suite -// factory: pointer to the factory that creates a test object. -// The newly created TestInfo instance will assume -// ownership of the factory object. -GTEST_API_ TestInfo* MakeAndRegisterTestInfo( - const char* test_suite_name, const char* name, const char* type_param, - const char* value_param, CodeLocation code_location, - TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, - TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); - -// If *pstr starts with the given prefix, modifies *pstr to be right -// past the prefix and returns true; otherwise leaves *pstr unchanged -// and returns false. None of pstr, *pstr, and prefix can be NULL. -GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); - -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -// State of the definition of a type-parameterized test suite. -class GTEST_API_ TypedTestSuitePState { - public: - TypedTestSuitePState() : registered_(false) {} - - // Adds the given test name to defined_test_names_ and return true - // if the test suite hasn't been registered; otherwise aborts the - // program. - bool AddTestName(const char* file, int line, const char* case_name, - const char* test_name) { - if (registered_) { - fprintf(stderr, - "%s Test %s must be defined before " - "REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n", - FormatFileLocation(file, line).c_str(), test_name, case_name); - fflush(stderr); - posix::Abort(); - } - registered_tests_.insert( - ::std::make_pair(test_name, CodeLocation(file, line))); - return true; - } - - bool TestExists(const std::string& test_name) const { - return registered_tests_.count(test_name) > 0; - } - - const CodeLocation& GetCodeLocation(const std::string& test_name) const { - RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name); - GTEST_CHECK_(it != registered_tests_.end()); - return it->second; - } - - // Verifies that registered_tests match the test names in - // defined_test_names_; returns registered_tests if successful, or - // aborts the program otherwise. - const char* VerifyRegisteredTestNames( - const char* file, int line, const char* registered_tests); - - private: - typedef ::std::map RegisteredTestsMap; - - bool registered_; - RegisteredTestsMap registered_tests_; -}; - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -using TypedTestCasePState = TypedTestSuitePState; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -// Skips to the first non-space char after the first comma in 'str'; -// returns NULL if no comma is found in 'str'. -inline const char* SkipComma(const char* str) { - const char* comma = strchr(str, ','); - if (comma == nullptr) { - return nullptr; - } - while (IsSpace(*(++comma))) {} - return comma; -} - -// Returns the prefix of 'str' before the first comma in it; returns -// the entire string if it contains no comma. -inline std::string GetPrefixUntilComma(const char* str) { - const char* comma = strchr(str, ','); - return comma == nullptr ? str : std::string(str, comma); -} - -// Splits a given string on a given delimiter, populating a given -// vector with the fields. -void SplitString(const ::std::string& str, char delimiter, - ::std::vector< ::std::string>* dest); - -// The default argument to the template below for the case when the user does -// not provide a name generator. -struct DefaultNameGenerator { - template - static std::string GetName(int i) { - return StreamableToString(i); - } -}; - -template -struct NameGeneratorSelector { - typedef Provided type; -}; - -template -void GenerateNamesRecursively(Types0, std::vector*, int) {} - -template -void GenerateNamesRecursively(Types, std::vector* result, int i) { - result->push_back(NameGenerator::template GetName(i)); - GenerateNamesRecursively(typename Types::Tail(), result, - i + 1); -} - -template -std::vector GenerateNames() { - std::vector result; - GenerateNamesRecursively(Types(), &result, 0); - return result; -} - -// TypeParameterizedTest::Register() -// registers a list of type-parameterized tests with Google Test. The -// return value is insignificant - we just need to return something -// such that we can call this function in a namespace scope. -// -// Implementation note: The GTEST_TEMPLATE_ macro declares a template -// template parameter. It's defined in gtest-type-util.h. -template -class TypeParameterizedTest { - public: - // 'index' is the index of the test in the type list 'Types' - // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite, - // Types). Valid values for 'index' are [0, N - 1] where N is the - // length of Types. - static bool Register(const char* prefix, const CodeLocation& code_location, - const char* case_name, const char* test_names, int index, - const std::vector& type_names = - GenerateNames()) { - typedef typename Types::Head Type; - typedef Fixture FixtureClass; - typedef typename GTEST_BIND_(TestSel, Type) TestClass; - - // First, registers the first type-parameterized test in the type - // list. - MakeAndRegisterTestInfo( - (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + - "/" + type_names[static_cast(index)]) - .c_str(), - StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(), - GetTypeName().c_str(), - nullptr, // No value parameter. - code_location, GetTypeId(), - SuiteApiResolver::GetSetUpCaseOrSuite( - code_location.file.c_str(), code_location.line), - SuiteApiResolver::GetTearDownCaseOrSuite( - code_location.file.c_str(), code_location.line), - new TestFactoryImpl); - - // Next, recurses (at compile time) with the tail of the type list. - return TypeParameterizedTest::Register(prefix, - code_location, - case_name, - test_names, - index + 1, - type_names); - } -}; - -// The base case for the compile time recursion. -template -class TypeParameterizedTest { - public: - static bool Register(const char* /*prefix*/, const CodeLocation&, - const char* /*case_name*/, const char* /*test_names*/, - int /*index*/, - const std::vector& = - std::vector() /*type_names*/) { - return true; - } -}; - -// TypeParameterizedTestSuite::Register() -// registers *all combinations* of 'Tests' and 'Types' with Google -// Test. The return value is insignificant - we just need to return -// something such that we can call this function in a namespace scope. -template -class TypeParameterizedTestSuite { - public: - static bool Register(const char* prefix, CodeLocation code_location, - const TypedTestSuitePState* state, const char* case_name, - const char* test_names, - const std::vector& type_names = - GenerateNames()) { - std::string test_name = StripTrailingSpaces( - GetPrefixUntilComma(test_names)); - if (!state->TestExists(test_name)) { - fprintf(stderr, "Failed to get code location for test %s.%s at %s.", - case_name, test_name.c_str(), - FormatFileLocation(code_location.file.c_str(), - code_location.line).c_str()); - fflush(stderr); - posix::Abort(); - } - const CodeLocation& test_location = state->GetCodeLocation(test_name); - - typedef typename Tests::Head Head; - - // First, register the first test in 'Test' for each type in 'Types'. - TypeParameterizedTest::Register( - prefix, test_location, case_name, test_names, 0, type_names); - - // Next, recurses (at compile time) with the tail of the test list. - return TypeParameterizedTestSuite::Register(prefix, code_location, - state, case_name, - SkipComma(test_names), - type_names); - } -}; - -// The base case for the compile time recursion. -template -class TypeParameterizedTestSuite { - public: - static bool Register(const char* /*prefix*/, const CodeLocation&, - const TypedTestSuitePState* /*state*/, - const char* /*case_name*/, const char* /*test_names*/, - const std::vector& = - std::vector() /*type_names*/) { - return true; - } -}; - -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -// Returns the current OS stack trace as an std::string. -// -// The maximum number of stack frames to be included is specified by -// the gtest_stack_trace_depth flag. The skip_count parameter -// specifies the number of top frames to be skipped, which doesn't -// count against the number of frames to be included. -// -// For example, if Foo() calls Bar(), which in turn calls -// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in -// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. -GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( - UnitTest* unit_test, int skip_count); - -// Helpers for suppressing warnings on unreachable code or constant -// condition. - -// Always returns true. -GTEST_API_ bool AlwaysTrue(); - -// Always returns false. -inline bool AlwaysFalse() { return !AlwaysTrue(); } - -// Helper for suppressing false warning from Clang on a const char* -// variable declared in a conditional expression always being NULL in -// the else branch. -struct GTEST_API_ ConstCharPtr { - ConstCharPtr(const char* str) : value(str) {} - operator bool() const { return true; } - const char* value; -}; - -// A simple Linear Congruential Generator for generating random -// numbers with a uniform distribution. Unlike rand() and srand(), it -// doesn't use global state (and therefore can't interfere with user -// code). Unlike rand_r(), it's portable. An LCG isn't very random, -// but it's good enough for our purposes. -class GTEST_API_ Random { - public: - static const UInt32 kMaxRange = 1u << 31; - - explicit Random(UInt32 seed) : state_(seed) {} - - void Reseed(UInt32 seed) { state_ = seed; } - - // Generates a random number from [0, range). Crashes if 'range' is - // 0 or greater than kMaxRange. - UInt32 Generate(UInt32 range); - - private: - UInt32 state_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); -}; - -// Turns const U&, U&, const U, and U all into U. -#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ - typename std::remove_const::type>::type - -// IsAProtocolMessage::value is a compile-time bool constant that's -// true if and only if T is type proto2::Message or a subclass of it. -template -struct IsAProtocolMessage - : public bool_constant< - std::is_convertible::value> {}; - -// When the compiler sees expression IsContainerTest(0), if C is an -// STL-style container class, the first overload of IsContainerTest -// will be viable (since both C::iterator* and C::const_iterator* are -// valid types and NULL can be implicitly converted to them). It will -// be picked over the second overload as 'int' is a perfect match for -// the type of argument 0. If C::iterator or C::const_iterator is not -// a valid type, the first overload is not viable, and the second -// overload will be picked. Therefore, we can determine whether C is -// a container class by checking the type of IsContainerTest(0). -// The value of the expression is insignificant. -// -// In C++11 mode we check the existence of a const_iterator and that an -// iterator is properly implemented for the container. -// -// For pre-C++11 that we look for both C::iterator and C::const_iterator. -// The reason is that C++ injects the name of a class as a member of the -// class itself (e.g. you can refer to class iterator as either -// 'iterator' or 'iterator::iterator'). If we look for C::iterator -// only, for example, we would mistakenly think that a class named -// iterator is an STL container. -// -// Also note that the simpler approach of overloading -// IsContainerTest(typename C::const_iterator*) and -// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. -typedef int IsContainer; -template ().begin()), - class = decltype(::std::declval().end()), - class = decltype(++::std::declval()), - class = decltype(*::std::declval()), - class = typename C::const_iterator> -IsContainer IsContainerTest(int /* dummy */) { - return 0; -} - -typedef char IsNotContainer; -template -IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } - -// Trait to detect whether a type T is a hash table. -// The heuristic used is that the type contains an inner type `hasher` and does -// not contain an inner type `reverse_iterator`. -// If the container is iterable in reverse, then order might actually matter. -template -struct IsHashTable { - private: - template - static char test(typename U::hasher*, typename U::reverse_iterator*); - template - static int test(typename U::hasher*, ...); - template - static char test(...); - - public: - static const bool value = sizeof(test(nullptr, nullptr)) == sizeof(int); -}; - -template -const bool IsHashTable::value; - -template (0)) == sizeof(IsContainer)> -struct IsRecursiveContainerImpl; - -template -struct IsRecursiveContainerImpl : public std::false_type {}; - -// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to -// obey the same inconsistencies as the IsContainerTest, namely check if -// something is a container is relying on only const_iterator in C++11 and -// is relying on both const_iterator and iterator otherwise -template -struct IsRecursiveContainerImpl { - using value_type = decltype(*std::declval()); - using type = - std::is_same::type>::type, - C>; -}; - -// IsRecursiveContainer is a unary compile-time predicate that -// evaluates whether C is a recursive container type. A recursive container -// type is a container type whose value_type is equal to the container type -// itself. An example for a recursive container type is -// boost::filesystem::path, whose iterator has a value_type that is equal to -// boost::filesystem::path. -template -struct IsRecursiveContainer : public IsRecursiveContainerImpl::type {}; - -// Utilities for native arrays. - -// ArrayEq() compares two k-dimensional native arrays using the -// elements' operator==, where k can be any integer >= 0. When k is -// 0, ArrayEq() degenerates into comparing a single pair of values. - -template -bool ArrayEq(const T* lhs, size_t size, const U* rhs); - -// This generic version is used when k is 0. -template -inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } - -// This overload is used when k >= 1. -template -inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { - return internal::ArrayEq(lhs, N, rhs); -} - -// This helper reduces code bloat. If we instead put its logic inside -// the previous ArrayEq() function, arrays with different sizes would -// lead to different copies of the template code. -template -bool ArrayEq(const T* lhs, size_t size, const U* rhs) { - for (size_t i = 0; i != size; i++) { - if (!internal::ArrayEq(lhs[i], rhs[i])) - return false; - } - return true; -} - -// Finds the first element in the iterator range [begin, end) that -// equals elem. Element may be a native array type itself. -template -Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { - for (Iter it = begin; it != end; ++it) { - if (internal::ArrayEq(*it, elem)) - return it; - } - return end; -} - -// CopyArray() copies a k-dimensional native array using the elements' -// operator=, where k can be any integer >= 0. When k is 0, -// CopyArray() degenerates into copying a single value. - -template -void CopyArray(const T* from, size_t size, U* to); - -// This generic version is used when k is 0. -template -inline void CopyArray(const T& from, U* to) { *to = from; } - -// This overload is used when k >= 1. -template -inline void CopyArray(const T(&from)[N], U(*to)[N]) { - internal::CopyArray(from, N, *to); -} - -// This helper reduces code bloat. If we instead put its logic inside -// the previous CopyArray() function, arrays with different sizes -// would lead to different copies of the template code. -template -void CopyArray(const T* from, size_t size, U* to) { - for (size_t i = 0; i != size; i++) { - internal::CopyArray(from[i], to + i); - } -} - -// The relation between an NativeArray object (see below) and the -// native array it represents. -// We use 2 different structs to allow non-copyable types to be used, as long -// as RelationToSourceReference() is passed. -struct RelationToSourceReference {}; -struct RelationToSourceCopy {}; - -// Adapts a native array to a read-only STL-style container. Instead -// of the complete STL container concept, this adaptor only implements -// members useful for Google Mock's container matchers. New members -// should be added as needed. To simplify the implementation, we only -// support Element being a raw type (i.e. having no top-level const or -// reference modifier). It's the client's responsibility to satisfy -// this requirement. Element can be an array type itself (hence -// multi-dimensional arrays are supported). -template -class NativeArray { - public: - // STL-style container typedefs. - typedef Element value_type; - typedef Element* iterator; - typedef const Element* const_iterator; - - // Constructs from a native array. References the source. - NativeArray(const Element* array, size_t count, RelationToSourceReference) { - InitRef(array, count); - } - - // Constructs from a native array. Copies the source. - NativeArray(const Element* array, size_t count, RelationToSourceCopy) { - InitCopy(array, count); - } - - // Copy constructor. - NativeArray(const NativeArray& rhs) { - (this->*rhs.clone_)(rhs.array_, rhs.size_); - } - - ~NativeArray() { - if (clone_ != &NativeArray::InitRef) - delete[] array_; - } - - // STL-style container methods. - size_t size() const { return size_; } - const_iterator begin() const { return array_; } - const_iterator end() const { return array_ + size_; } - bool operator==(const NativeArray& rhs) const { - return size() == rhs.size() && - ArrayEq(begin(), size(), rhs.begin()); - } - - private: - static_assert(!std::is_const::value, "Type must not be const"); - static_assert(!std::is_reference::value, - "Type must not be a reference"); - - // Initializes this object with a copy of the input. - void InitCopy(const Element* array, size_t a_size) { - Element* const copy = new Element[a_size]; - CopyArray(array, a_size, copy); - array_ = copy; - size_ = a_size; - clone_ = &NativeArray::InitCopy; - } - - // Initializes this object with a reference of the input. - void InitRef(const Element* array, size_t a_size) { - array_ = array; - size_ = a_size; - clone_ = &NativeArray::InitRef; - } - - const Element* array_; - size_t size_; - void (NativeArray::*clone_)(const Element*, size_t); - - GTEST_DISALLOW_ASSIGN_(NativeArray); -}; - -// Backport of std::index_sequence. -template -struct IndexSequence { - using type = IndexSequence; -}; - -// Double the IndexSequence, and one if plus_one is true. -template -struct DoubleSequence; -template -struct DoubleSequence, sizeofT> { - using type = IndexSequence; -}; -template -struct DoubleSequence, sizeofT> { - using type = IndexSequence; -}; - -// Backport of std::make_index_sequence. -// It uses O(ln(N)) instantiation depth. -template -struct MakeIndexSequence - : DoubleSequence::type, - N / 2>::type {}; - -template <> -struct MakeIndexSequence<0> : IndexSequence<> {}; - -// FIXME: This implementation of ElemFromList is O(1) in instantiation depth, -// but it is O(N^2) in total instantiations. Not sure if this is the best -// tradeoff, as it will make it somewhat slow to compile. -template -struct ElemFromListImpl {}; - -template -struct ElemFromListImpl { - using type = T; -}; - -// Get the Nth element from T... -// It uses O(1) instantiation depth. -template -struct ElemFromList; - -template -struct ElemFromList, T...> - : ElemFromListImpl... {}; - -template -class FlatTuple; - -template -struct FlatTupleElemBase; - -template -struct FlatTupleElemBase, I> { - using value_type = - typename ElemFromList::type, - T...>::type; - FlatTupleElemBase() = default; - explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} - value_type value; -}; - -template -struct FlatTupleBase; - -template -struct FlatTupleBase, IndexSequence> - : FlatTupleElemBase, Idx>... { - using Indices = IndexSequence; - FlatTupleBase() = default; - explicit FlatTupleBase(T... t) - : FlatTupleElemBase, Idx>(std::move(t))... {} -}; - -// Analog to std::tuple but with different tradeoffs. -// This class minimizes the template instantiation depth, thus allowing more -// elements that std::tuple would. std::tuple has been seen to require an -// instantiation depth of more than 10x the number of elements in some -// implementations. -// FlatTuple and ElemFromList are not recursive and have a fixed depth -// regardless of T... -// MakeIndexSequence, on the other hand, it is recursive but with an -// instantiation depth of O(ln(N)). -template -class FlatTuple - : private FlatTupleBase, - typename MakeIndexSequence::type> { - using Indices = typename FlatTuple::FlatTupleBase::Indices; - - public: - FlatTuple() = default; - explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {} - - template - const typename ElemFromList::type& Get() const { - return static_cast*>(this)->value; - } - - template - typename ElemFromList::type& Get() { - return static_cast*>(this)->value; - } -}; - -// Utility functions to be called with static_assert to induce deprecation -// warnings. -GTEST_INTERNAL_DEPRECATED( - "INSTANTIATE_TEST_CASE_P is deprecated, please use " - "INSTANTIATE_TEST_SUITE_P") -constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; } - -GTEST_INTERNAL_DEPRECATED( - "TYPED_TEST_CASE_P is deprecated, please use " - "TYPED_TEST_SUITE_P") -constexpr bool TypedTestCase_P_IsDeprecated() { return true; } - -GTEST_INTERNAL_DEPRECATED( - "TYPED_TEST_CASE is deprecated, please use " - "TYPED_TEST_SUITE") -constexpr bool TypedTestCaseIsDeprecated() { return true; } - -GTEST_INTERNAL_DEPRECATED( - "REGISTER_TYPED_TEST_CASE_P is deprecated, please use " - "REGISTER_TYPED_TEST_SUITE_P") -constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; } - -GTEST_INTERNAL_DEPRECATED( - "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use " - "INSTANTIATE_TYPED_TEST_SUITE_P") -constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } - -} // namespace internal -} // namespace testing - -#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ - ::testing::internal::AssertHelper(result_type, file, line, message) \ - = ::testing::Message() - -#define GTEST_MESSAGE_(message, result_type) \ - GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) - -#define GTEST_FATAL_FAILURE_(message) \ - return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) - -#define GTEST_NONFATAL_FAILURE_(message) \ - GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) - -#define GTEST_SUCCESS_(message) \ - GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) - -#define GTEST_SKIP_(message) \ - return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip) - -// Suppress MSVC warning 4072 (unreachable code) for the code following -// statement if it returns or throws (or doesn't return or throw in some -// situations). -#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ - if (::testing::internal::AlwaysTrue()) { statement; } - -#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::ConstCharPtr gtest_msg = "") { \ - bool gtest_caught_expected = false; \ - try { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } \ - catch (expected_exception const&) { \ - gtest_caught_expected = true; \ - } \ - catch (...) { \ - gtest_msg.value = \ - "Expected: " #statement " throws an exception of type " \ - #expected_exception ".\n Actual: it throws a different type."; \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ - } \ - if (!gtest_caught_expected) { \ - gtest_msg.value = \ - "Expected: " #statement " throws an exception of type " \ - #expected_exception ".\n Actual: it throws nothing."; \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ - fail(gtest_msg.value) - -#define GTEST_TEST_NO_THROW_(statement, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - try { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } \ - catch (...) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ - fail("Expected: " #statement " doesn't throw an exception.\n" \ - " Actual: it throws.") - -#define GTEST_TEST_ANY_THROW_(statement, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - bool gtest_caught_any = false; \ - try { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } \ - catch (...) { \ - gtest_caught_any = true; \ - } \ - if (!gtest_caught_any) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ - fail("Expected: " #statement " throws an exception.\n" \ - " Actual: it doesn't.") - - -// Implements Boolean test assertions such as EXPECT_TRUE. expression can be -// either a boolean expression or an AssertionResult. text is a textual -// represenation of expression as it was passed into the EXPECT_TRUE. -#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (const ::testing::AssertionResult gtest_ar_ = \ - ::testing::AssertionResult(expression)) \ - ; \ - else \ - fail(::testing::internal::GetBoolAssertionFailureMessage(\ - gtest_ar_, text, #actual, #expected).c_str()) - -#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ - fail("Expected: " #statement " doesn't generate new fatal " \ - "failures in the current thread.\n" \ - " Actual: it does.") - -// Expands to the name of the class that implements the given test. -#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ - test_suite_name##_##test_name##_Test - -// Helper macro for defining tests. -#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \ - static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ - "test_suite_name must not be empty"); \ - static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ - "test_name must not be empty"); \ - class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ - : public parent_class { \ - public: \ - GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ - \ - private: \ - virtual void TestBody(); \ - static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ - test_name)); \ - }; \ - \ - ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ - test_name)::test_info_ = \ - ::testing::internal::MakeAndRegisterTestInfo( \ - #test_suite_name, #test_name, nullptr, nullptr, \ - ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \ - ::testing::internal::SuiteApiResolver< \ - parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \ - ::testing::internal::SuiteApiResolver< \ - parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \ - new ::testing::internal::TestFactoryImpl); \ - void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-linked_ptr.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-linked_ptr.h deleted file mode 100644 index 082b87289ae..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-linked_ptr.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2003 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// A "smart" pointer type with reference tracking. Every pointer to a -// particular object is kept on a circular linked list. When the last pointer -// to an object is destroyed or reassigned, the object is deleted. -// -// Used properly, this deletes the object when the last reference goes away. -// There are several caveats: -// - Like all reference counting schemes, cycles lead to leaks. -// - Each smart pointer is actually two pointers (8 bytes instead of 4). -// - Every time a pointer is assigned, the entire list of pointers to that -// object is traversed. This class is therefore NOT SUITABLE when there -// will often be more than two or three pointers to a particular object. -// - References are only tracked as long as linked_ptr<> objects are copied. -// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS -// will happen (double deletion). -// -// A good use of this class is storing object references in STL containers. -// You can safely put linked_ptr<> in a vector<>. -// Other uses may not be as good. -// -// Note: If you use an incomplete type with linked_ptr<>, the class -// *containing* linked_ptr<> must have a constructor and destructor (even -// if they do nothing!). -// -// Bill Gibbons suggested we use something like this. -// -// Thread Safety: -// Unlike other linked_ptr implementations, in this implementation -// a linked_ptr object is thread-safe in the sense that: -// - it's safe to copy linked_ptr objects concurrently, -// - it's safe to copy *from* a linked_ptr and read its underlying -// raw pointer (e.g. via get()) concurrently, and -// - it's safe to write to two linked_ptrs that point to the same -// shared object concurrently. -// FIXME: rename this to safe_linked_ptr to avoid -// confusion with normal linked_ptr. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ - -#include -#include - -#include "gtest/internal/gtest-port.h" - -namespace testing { -namespace internal { - -// Protects copying of all linked_ptr objects. -GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); - -// This is used internally by all instances of linked_ptr<>. It needs to be -// a non-template class because different types of linked_ptr<> can refer to -// the same object (linked_ptr(obj) vs linked_ptr(obj)). -// So, it needs to be possible for different types of linked_ptr to participate -// in the same circular linked list, so we need a single class type here. -// -// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. -class linked_ptr_internal { - public: - // Create a new circle that includes only this instance. - void join_new() { - next_ = this; - } - - // Many linked_ptr operations may change p.link_ for some linked_ptr - // variable p in the same circle as this object. Therefore we need - // to prevent two such operations from occurring concurrently. - // - // Note that different types of linked_ptr objects can coexist in a - // circle (e.g. linked_ptr, linked_ptr, and - // linked_ptr). Therefore we must use a single mutex to - // protect all linked_ptr objects. This can create serious - // contention in production code, but is acceptable in a testing - // framework. - - // Join an existing circle. - void join(linked_ptr_internal const* ptr) - GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { - MutexLock lock(&g_linked_ptr_mutex); - - linked_ptr_internal const* p = ptr; - while (p->next_ != ptr) { - assert(p->next_ != this && - "Trying to join() a linked ring we are already in. " - "Is GMock thread safety enabled?"); - p = p->next_; - } - p->next_ = this; - next_ = ptr; - } - - // Leave whatever circle we're part of. Returns true if we were the - // last member of the circle. Once this is done, you can join() another. - bool depart() - GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { - MutexLock lock(&g_linked_ptr_mutex); - - if (next_ == this) return true; - linked_ptr_internal const* p = next_; - while (p->next_ != this) { - assert(p->next_ != next_ && - "Trying to depart() a linked ring we are not in. " - "Is GMock thread safety enabled?"); - p = p->next_; - } - p->next_ = next_; - return false; - } - - private: - mutable linked_ptr_internal const* next_; -}; - -template -class linked_ptr { - public: - typedef T element_type; - - // Take over ownership of a raw pointer. This should happen as soon as - // possible after the object is created. - explicit linked_ptr(T* ptr = NULL) { capture(ptr); } - ~linked_ptr() { depart(); } - - // Copy an existing linked_ptr<>, adding ourselves to the list of references. - template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } - linked_ptr(linked_ptr const& ptr) { // NOLINT - assert(&ptr != this); - copy(&ptr); - } - - // Assignment releases the old value and acquires the new. - template linked_ptr& operator=(linked_ptr const& ptr) { - depart(); - copy(&ptr); - return *this; - } - - linked_ptr& operator=(linked_ptr const& ptr) { - if (&ptr != this) { - depart(); - copy(&ptr); - } - return *this; - } - - // Smart pointer members. - void reset(T* ptr = NULL) { - depart(); - capture(ptr); - } - T* get() const { return value_; } - T* operator->() const { return value_; } - T& operator*() const { return *value_; } - - bool operator==(T* p) const { return value_ == p; } - bool operator!=(T* p) const { return value_ != p; } - template - bool operator==(linked_ptr const& ptr) const { - return value_ == ptr.get(); - } - template - bool operator!=(linked_ptr const& ptr) const { - return value_ != ptr.get(); - } - - private: - template - friend class linked_ptr; - - T* value_; - linked_ptr_internal link_; - - void depart() { - if (link_.depart()) delete value_; - } - - void capture(T* ptr) { - value_ = ptr; - link_.join_new(); - } - - template void copy(linked_ptr const* ptr) { - value_ = ptr->get(); - if (value_) - link_.join(&ptr->link_); - else - link_.join_new(); - } -}; - -template inline -bool operator==(T* ptr, const linked_ptr& x) { - return ptr == x.get(); -} - -template inline -bool operator!=(T* ptr, const linked_ptr& x) { - return ptr != x.get(); -} - -// A function to convert T* into linked_ptr -// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation -// for linked_ptr >(new FooBarBaz(arg)) -template -linked_ptr make_linked_ptr(T* ptr) { - return linked_ptr(ptr); -} - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util-generated.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util-generated.h deleted file mode 100644 index 4fac8c02703..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util-generated.h +++ /dev/null @@ -1,5552 +0,0 @@ -// This file was GENERATED by command: -// pump.py gtest-param-util-generated.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Type and function utilities for implementing parameterized tests. -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently Google Test supports at most 50 arguments in Values, -// and at most 10 arguments in Combine. Please contact -// googletestframework@googlegroups.com if you need more. -// Please note that the number of arguments to Combine is limited -// by the maximum arity of the implementation of tuple which is -// currently set at 10. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ - -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-port.h" - -namespace testing { - -// Forward declarations of ValuesIn(), which is implemented in -// include/gtest/gtest-param-test.h. -template -internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end); - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]); - -template -internal::ParamGenerator ValuesIn( - const Container& container); - -namespace internal { - -// Used in the Values() function to provide polymorphic capabilities. -template -class ValueArray1 { - public: - explicit ValueArray1(T1 v1) : v1_(v1) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_)}; - return ValuesIn(array); - } - - ValueArray1(const ValueArray1& other) : v1_(other.v1_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray1& other); - - const T1 v1_; -}; - -template -class ValueArray2 { - public: - ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_)}; - return ValuesIn(array); - } - - ValueArray2(const ValueArray2& other) : v1_(other.v1_), v2_(other.v2_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray2& other); - - const T1 v1_; - const T2 v2_; -}; - -template -class ValueArray3 { - public: - ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_)}; - return ValuesIn(array); - } - - ValueArray3(const ValueArray3& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray3& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; -}; - -template -class ValueArray4 { - public: - ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_)}; - return ValuesIn(array); - } - - ValueArray4(const ValueArray4& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray4& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; -}; - -template -class ValueArray5 { - public: - ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_)}; - return ValuesIn(array); - } - - ValueArray5(const ValueArray5& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray5& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; -}; - -template -class ValueArray6 { - public: - ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_)}; - return ValuesIn(array); - } - - ValueArray6(const ValueArray6& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray6& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; -}; - -template -class ValueArray7 { - public: - ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_)}; - return ValuesIn(array); - } - - ValueArray7(const ValueArray7& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray7& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; -}; - -template -class ValueArray8 { - public: - ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_)}; - return ValuesIn(array); - } - - ValueArray8(const ValueArray8& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray8& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; -}; - -template -class ValueArray9 { - public: - ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, - T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_)}; - return ValuesIn(array); - } - - ValueArray9(const ValueArray9& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray9& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; -}; - -template -class ValueArray10 { - public: - ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_)}; - return ValuesIn(array); - } - - ValueArray10(const ValueArray10& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray10& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; -}; - -template -class ValueArray11 { - public: - ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_)}; - return ValuesIn(array); - } - - ValueArray11(const ValueArray11& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray11& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; -}; - -template -class ValueArray12 { - public: - ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_)}; - return ValuesIn(array); - } - - ValueArray12(const ValueArray12& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray12& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; -}; - -template -class ValueArray13 { - public: - ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_)}; - return ValuesIn(array); - } - - ValueArray13(const ValueArray13& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray13& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; -}; - -template -class ValueArray14 { - public: - ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_)}; - return ValuesIn(array); - } - - ValueArray14(const ValueArray14& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray14& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; -}; - -template -class ValueArray15 { - public: - ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_)}; - return ValuesIn(array); - } - - ValueArray15(const ValueArray15& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray15& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; -}; - -template -class ValueArray16 { - public: - ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_)}; - return ValuesIn(array); - } - - ValueArray16(const ValueArray16& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray16& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; -}; - -template -class ValueArray17 { - public: - ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, - T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_)}; - return ValuesIn(array); - } - - ValueArray17(const ValueArray17& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray17& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; -}; - -template -class ValueArray18 { - public: - ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_)}; - return ValuesIn(array); - } - - ValueArray18(const ValueArray18& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray18& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; -}; - -template -class ValueArray19 { - public: - ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_)}; - return ValuesIn(array); - } - - ValueArray19(const ValueArray19& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray19& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; -}; - -template -class ValueArray20 { - public: - ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_)}; - return ValuesIn(array); - } - - ValueArray20(const ValueArray20& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray20& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; -}; - -template -class ValueArray21 { - public: - ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_)}; - return ValuesIn(array); - } - - ValueArray21(const ValueArray21& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray21& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; -}; - -template -class ValueArray22 { - public: - ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_)}; - return ValuesIn(array); - } - - ValueArray22(const ValueArray22& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray22& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; -}; - -template -class ValueArray23 { - public: - ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_)}; - return ValuesIn(array); - } - - ValueArray23(const ValueArray23& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray23& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; -}; - -template -class ValueArray24 { - public: - ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_)}; - return ValuesIn(array); - } - - ValueArray24(const ValueArray24& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray24& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; -}; - -template -class ValueArray25 { - public: - ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, - T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_)}; - return ValuesIn(array); - } - - ValueArray25(const ValueArray25& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray25& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; -}; - -template -class ValueArray26 { - public: - ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_)}; - return ValuesIn(array); - } - - ValueArray26(const ValueArray26& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray26& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; -}; - -template -class ValueArray27 { - public: - ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), - v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), - v26_(v26), v27_(v27) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_)}; - return ValuesIn(array); - } - - ValueArray27(const ValueArray27& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray27& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; -}; - -template -class ValueArray28 { - public: - ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), - v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_)}; - return ValuesIn(array); - } - - ValueArray28(const ValueArray28& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray28& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; -}; - -template -class ValueArray29 { - public: - ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), - v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_)}; - return ValuesIn(array); - } - - ValueArray29(const ValueArray29& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray29& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; -}; - -template -class ValueArray30 { - public: - ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_)}; - return ValuesIn(array); - } - - ValueArray30(const ValueArray30& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray30& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; -}; - -template -class ValueArray31 { - public: - ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_)}; - return ValuesIn(array); - } - - ValueArray31(const ValueArray31& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray31& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; -}; - -template -class ValueArray32 { - public: - ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), - v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_)}; - return ValuesIn(array); - } - - ValueArray32(const ValueArray32& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray32& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; -}; - -template -class ValueArray33 { - public: - ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, - T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_)}; - return ValuesIn(array); - } - - ValueArray33(const ValueArray33& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray33& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; -}; - -template -class ValueArray34 { - public: - ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_)}; - return ValuesIn(array); - } - - ValueArray34(const ValueArray34& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray34& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; -}; - -template -class ValueArray35 { - public: - ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), - v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), - v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), - v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_)}; - return ValuesIn(array); - } - - ValueArray35(const ValueArray35& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray35& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; -}; - -template -class ValueArray36 { - public: - ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), - v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), - v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_)}; - return ValuesIn(array); - } - - ValueArray36(const ValueArray36& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray36& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; -}; - -template -class ValueArray37 { - public: - ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), - v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), - v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), - v36_(v36), v37_(v37) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_)}; - return ValuesIn(array); - } - - ValueArray37(const ValueArray37& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray37& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; -}; - -template -class ValueArray38 { - public: - ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_)}; - return ValuesIn(array); - } - - ValueArray38(const ValueArray38& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray38& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; -}; - -template -class ValueArray39 { - public: - ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_)}; - return ValuesIn(array); - } - - ValueArray39(const ValueArray39& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray39& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; -}; - -template -class ValueArray40 { - public: - ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), - v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), - v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), - v40_(v40) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_)}; - return ValuesIn(array); - } - - ValueArray40(const ValueArray40& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray40& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; -}; - -template -class ValueArray41 { - public: - ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, - T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_)}; - return ValuesIn(array); - } - - ValueArray41(const ValueArray41& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray41& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; -}; - -template -class ValueArray42 { - public: - ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_)}; - return ValuesIn(array); - } - - ValueArray42(const ValueArray42& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray42& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; -}; - -template -class ValueArray43 { - public: - ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), - v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), - v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), - v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), - v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_)}; - return ValuesIn(array); - } - - ValueArray43(const ValueArray43& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray43& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; -}; - -template -class ValueArray44 { - public: - ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), - v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), - v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), - v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), - v43_(v43), v44_(v44) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_)}; - return ValuesIn(array); - } - - ValueArray44(const ValueArray44& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray44& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; -}; - -template -class ValueArray45 { - public: - ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), - v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), - v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), - v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), - v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_)}; - return ValuesIn(array); - } - - ValueArray45(const ValueArray45& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_), v45_(other.v45_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray45& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; -}; - -template -class ValueArray46 { - public: - ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), - v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_)}; - return ValuesIn(array); - } - - ValueArray46(const ValueArray46& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_), v45_(other.v45_), v46_(other.v46_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray46& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; -}; - -template -class ValueArray47 { - public: - ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), - v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), - v47_(v47) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_)}; - return ValuesIn(array); - } - - ValueArray47(const ValueArray47& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_), v45_(other.v45_), v46_(other.v46_), - v47_(other.v47_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray47& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; -}; - -template -class ValueArray48 { - public: - ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), - v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), - v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), - v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), - v46_(v46), v47_(v47), v48_(v48) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_), - static_cast(v48_)}; - return ValuesIn(array); - } - - ValueArray48(const ValueArray48& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_), v45_(other.v45_), v46_(other.v46_), - v47_(other.v47_), v48_(other.v48_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray48& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; - const T48 v48_; -}; - -template -class ValueArray49 { - public: - ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, - T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), - v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_), - static_cast(v48_), static_cast(v49_)}; - return ValuesIn(array); - } - - ValueArray49(const ValueArray49& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_), v45_(other.v45_), v46_(other.v46_), - v47_(other.v47_), v48_(other.v48_), v49_(other.v49_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray49& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; - const T48 v48_; - const T49 v49_; -}; - -template -class ValueArray50 { - public: - ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, - T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), - v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_), - static_cast(v48_), static_cast(v49_), static_cast(v50_)}; - return ValuesIn(array); - } - - ValueArray50(const ValueArray50& other) : v1_(other.v1_), v2_(other.v2_), - v3_(other.v3_), v4_(other.v4_), v5_(other.v5_), v6_(other.v6_), - v7_(other.v7_), v8_(other.v8_), v9_(other.v9_), v10_(other.v10_), - v11_(other.v11_), v12_(other.v12_), v13_(other.v13_), v14_(other.v14_), - v15_(other.v15_), v16_(other.v16_), v17_(other.v17_), v18_(other.v18_), - v19_(other.v19_), v20_(other.v20_), v21_(other.v21_), v22_(other.v22_), - v23_(other.v23_), v24_(other.v24_), v25_(other.v25_), v26_(other.v26_), - v27_(other.v27_), v28_(other.v28_), v29_(other.v29_), v30_(other.v30_), - v31_(other.v31_), v32_(other.v32_), v33_(other.v33_), v34_(other.v34_), - v35_(other.v35_), v36_(other.v36_), v37_(other.v37_), v38_(other.v38_), - v39_(other.v39_), v40_(other.v40_), v41_(other.v41_), v42_(other.v42_), - v43_(other.v43_), v44_(other.v44_), v45_(other.v45_), v46_(other.v46_), - v47_(other.v47_), v48_(other.v48_), v49_(other.v49_), v50_(other.v50_) {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray50& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; - const T48 v48_; - const T49 v49_; - const T50 v50_; -}; - -# if GTEST_HAS_COMBINE -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Generates values from the Cartesian product of values produced -// by the argument generators. -// -template -class CartesianProductGenerator2 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator2(const ParamGenerator& g1, - const ParamGenerator& g2) - : g1_(g1), g2_(g2) {} - virtual ~CartesianProductGenerator2() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current2_; - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - linked_ptr current_value_; - }; // class CartesianProductGenerator2::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator2& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; -}; // class CartesianProductGenerator2 - - -template -class CartesianProductGenerator3 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator3(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3) - : g1_(g1), g2_(g2), g3_(g3) {} - virtual ~CartesianProductGenerator3() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current3_; - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - linked_ptr current_value_; - }; // class CartesianProductGenerator3::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator3& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; -}; // class CartesianProductGenerator3 - - -template -class CartesianProductGenerator4 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator4(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} - virtual ~CartesianProductGenerator4() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current4_; - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - linked_ptr current_value_; - }; // class CartesianProductGenerator4::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator4& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; -}; // class CartesianProductGenerator4 - - -template -class CartesianProductGenerator5 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator5(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} - virtual ~CartesianProductGenerator5() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current5_; - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - linked_ptr current_value_; - }; // class CartesianProductGenerator5::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator5& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; -}; // class CartesianProductGenerator5 - - -template -class CartesianProductGenerator6 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator6(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} - virtual ~CartesianProductGenerator6() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current6_; - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - linked_ptr current_value_; - }; // class CartesianProductGenerator6::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator6& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; -}; // class CartesianProductGenerator6 - - -template -class CartesianProductGenerator7 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator7(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} - virtual ~CartesianProductGenerator7() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current7_; - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - linked_ptr current_value_; - }; // class CartesianProductGenerator7::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator7& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; -}; // class CartesianProductGenerator7 - - -template -class CartesianProductGenerator8 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator8(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7, - const ParamGenerator& g8) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), - g8_(g8) {} - virtual ~CartesianProductGenerator8() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin(), g8_, g8_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, - g8_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7, - const ParamGenerator& g8, - const typename ParamGenerator::iterator& current8) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7), - begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current8_; - if (current8_ == end8_) { - current8_ = begin8_; - ++current7_; - } - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_ && - current8_ == typed_other->current8_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_), - begin8_(other.begin8_), - end8_(other.end8_), - current8_(other.current8_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_, *current8_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_ || - current8_ == end8_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - const typename ParamGenerator::iterator begin8_; - const typename ParamGenerator::iterator end8_; - typename ParamGenerator::iterator current8_; - linked_ptr current_value_; - }; // class CartesianProductGenerator8::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator8& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; - const ParamGenerator g8_; -}; // class CartesianProductGenerator8 - - -template -class CartesianProductGenerator9 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator9(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7, - const ParamGenerator& g8, const ParamGenerator& g9) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9) {} - virtual ~CartesianProductGenerator9() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, - g8_.end(), g9_, g9_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7, - const ParamGenerator& g8, - const typename ParamGenerator::iterator& current8, - const ParamGenerator& g9, - const typename ParamGenerator::iterator& current9) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7), - begin8_(g8.begin()), end8_(g8.end()), current8_(current8), - begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current9_; - if (current9_ == end9_) { - current9_ = begin9_; - ++current8_; - } - if (current8_ == end8_) { - current8_ = begin8_; - ++current7_; - } - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_ && - current8_ == typed_other->current8_ && - current9_ == typed_other->current9_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_), - begin8_(other.begin8_), - end8_(other.end8_), - current8_(other.current8_), - begin9_(other.begin9_), - end9_(other.end9_), - current9_(other.current9_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_, *current8_, - *current9_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_ || - current8_ == end8_ || - current9_ == end9_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - const typename ParamGenerator::iterator begin8_; - const typename ParamGenerator::iterator end8_; - typename ParamGenerator::iterator current8_; - const typename ParamGenerator::iterator begin9_; - const typename ParamGenerator::iterator end9_; - typename ParamGenerator::iterator current9_; - linked_ptr current_value_; - }; // class CartesianProductGenerator9::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator9& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; - const ParamGenerator g8_; - const ParamGenerator g9_; -}; // class CartesianProductGenerator9 - - -template -class CartesianProductGenerator10 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator10(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7, - const ParamGenerator& g8, const ParamGenerator& g9, - const ParamGenerator& g10) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9), g10_(g10) {} - virtual ~CartesianProductGenerator10() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, - g8_.end(), g9_, g9_.end(), g10_, g10_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7, - const ParamGenerator& g8, - const typename ParamGenerator::iterator& current8, - const ParamGenerator& g9, - const typename ParamGenerator::iterator& current9, - const ParamGenerator& g10, - const typename ParamGenerator::iterator& current10) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7), - begin8_(g8.begin()), end8_(g8.end()), current8_(current8), - begin9_(g9.begin()), end9_(g9.end()), current9_(current9), - begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current10_; - if (current10_ == end10_) { - current10_ = begin10_; - ++current9_; - } - if (current9_ == end9_) { - current9_ = begin9_; - ++current8_; - } - if (current8_ == end8_) { - current8_ = begin8_; - ++current7_; - } - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_ && - current8_ == typed_other->current8_ && - current9_ == typed_other->current9_ && - current10_ == typed_other->current10_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_), - begin8_(other.begin8_), - end8_(other.end8_), - current8_(other.current8_), - begin9_(other.begin9_), - end9_(other.end9_), - current9_(other.current9_), - begin10_(other.begin10_), - end10_(other.end10_), - current10_(other.current10_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_, *current8_, - *current9_, *current10_)); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_ || - current8_ == end8_ || - current9_ == end9_ || - current10_ == end10_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - const typename ParamGenerator::iterator begin8_; - const typename ParamGenerator::iterator end8_; - typename ParamGenerator::iterator current8_; - const typename ParamGenerator::iterator begin9_; - const typename ParamGenerator::iterator end9_; - typename ParamGenerator::iterator current9_; - const typename ParamGenerator::iterator begin10_; - const typename ParamGenerator::iterator end10_; - typename ParamGenerator::iterator current10_; - linked_ptr current_value_; - }; // class CartesianProductGenerator10::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator10& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; - const ParamGenerator g8_; - const ParamGenerator g9_; - const ParamGenerator g10_; -}; // class CartesianProductGenerator10 - - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Helper classes providing Combine() with polymorphic features. They allow -// casting CartesianProductGeneratorN to ParamGenerator if T is -// convertible to U. -// -template -class CartesianProductHolder2 { - public: -CartesianProductHolder2(const Generator1& g1, const Generator2& g2) - : g1_(g1), g2_(g2) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator2( - static_cast >(g1_), - static_cast >(g2_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder2& other); - - const Generator1 g1_; - const Generator2 g2_; -}; // class CartesianProductHolder2 - -template -class CartesianProductHolder3 { - public: -CartesianProductHolder3(const Generator1& g1, const Generator2& g2, - const Generator3& g3) - : g1_(g1), g2_(g2), g3_(g3) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator3( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder3& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; -}; // class CartesianProductHolder3 - -template -class CartesianProductHolder4 { - public: -CartesianProductHolder4(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator4( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder4& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; -}; // class CartesianProductHolder4 - -template -class CartesianProductHolder5 { - public: -CartesianProductHolder5(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator5( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder5& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; -}; // class CartesianProductHolder5 - -template -class CartesianProductHolder6 { - public: -CartesianProductHolder6(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator6( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder6& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; -}; // class CartesianProductHolder6 - -template -class CartesianProductHolder7 { - public: -CartesianProductHolder7(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator7( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder7& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; -}; // class CartesianProductHolder7 - -template -class CartesianProductHolder8 { - public: -CartesianProductHolder8(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7, const Generator8& g8) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), - g8_(g8) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator8( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_), - static_cast >(g8_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder8& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; - const Generator8 g8_; -}; // class CartesianProductHolder8 - -template -class CartesianProductHolder9 { - public: -CartesianProductHolder9(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7, const Generator8& g8, - const Generator9& g9) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator9( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_), - static_cast >(g8_), - static_cast >(g9_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder9& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; - const Generator8 g8_; - const Generator9 g9_; -}; // class CartesianProductHolder9 - -template -class CartesianProductHolder10 { - public: -CartesianProductHolder10(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7, const Generator8& g8, - const Generator9& g9, const Generator10& g10) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9), g10_(g10) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator10( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_), - static_cast >(g8_), - static_cast >(g9_), - static_cast >(g10_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder10& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; - const Generator8 g8_; - const Generator9 g9_; - const Generator10 g10_; -}; // class CartesianProductHolder10 - -# endif // GTEST_HAS_COMBINE - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util-generated.h.pump b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util-generated.h.pump deleted file mode 100644 index 30dffe43c3c..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util-generated.h.pump +++ /dev/null @@ -1,282 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 50 $$ Maximum length of Values arguments we want to support. -$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Type and function utilities for implementing parameterized tests. -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently Google Test supports at most $n arguments in Values, -// and at most $maxtuple arguments in Combine. Please contact -// googletestframework@googlegroups.com if you need more. -// Please note that the number of arguments to Combine is limited -// by the maximum arity of the implementation of tuple which is -// currently set at $maxtuple. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ - -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-port.h" - -namespace testing { - -// Forward declarations of ValuesIn(), which is implemented in -// include/gtest/gtest-param-test.h. -template -internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end); - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]); - -template -internal::ParamGenerator ValuesIn( - const Container& container); - -namespace internal { - -// Used in the Values() function to provide polymorphic capabilities. -$range i 1..n -$for i [[ -$range j 1..i - -template <$for j, [[typename T$j]]> -class ValueArray$i { - public: - $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} - - template - operator ParamGenerator() const { - const T array[] = {$for j, [[static_cast(v$(j)_)]]}; - return ValuesIn(array); - } - - ValueArray$i(const ValueArray$i& other) : $for j, [[v$(j)_(other.v$(j)_)]] {} - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray$i& other); - -$for j [[ - - const T$j v$(j)_; -]] - -}; - -]] - -# if GTEST_HAS_COMBINE -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Generates values from the Cartesian product of values produced -// by the argument generators. -// -$range i 2..maxtuple -$for i [[ -$range j 1..i -$range k 2..i - -template <$for j, [[typename T$j]]> -class CartesianProductGenerator$i - : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > { - public: - typedef ::testing::tuple<$for j, [[T$j]]> ParamType; - - CartesianProductGenerator$i($for j, [[const ParamGenerator& g$j]]) - : $for j, [[g$(j)_(g$j)]] {} - virtual ~CartesianProductGenerator$i() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, $for j, [[ - - const ParamGenerator& g$j, - const typename ParamGenerator::iterator& current$(j)]]) - : base_(base), -$for j, [[ - - begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j) -]] { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current$(i)_; - -$for k [[ - if (current$(i+2-k)_ == end$(i+2-k)_) { - current$(i+2-k)_ = begin$(i+2-k)_; - ++current$(i+2-k-1)_; - } - -]] - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return current_value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ($for j && [[ - - current$(j)_ == typed_other->current$(j)_ -]]); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), $for j, [[ - - begin$(j)_(other.begin$(j)_), - end$(j)_(other.end$(j)_), - current$(j)_(other.current$(j)_) -]] { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_.reset(new ParamType($for j, [[*current$(j)_]])); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return -$for j || [[ - - current$(j)_ == end$(j)_ -]]; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. -$for j [[ - - const typename ParamGenerator::iterator begin$(j)_; - const typename ParamGenerator::iterator end$(j)_; - typename ParamGenerator::iterator current$(j)_; -]] - - linked_ptr current_value_; - }; // class CartesianProductGenerator$i::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator$i& other); - - -$for j [[ - const ParamGenerator g$(j)_; - -]] -}; // class CartesianProductGenerator$i - - -]] - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Helper classes providing Combine() with polymorphic features. They allow -// casting CartesianProductGeneratorN to ParamGenerator if T is -// convertible to U. -// -$range i 2..maxtuple -$for i [[ -$range j 1..i - -template <$for j, [[class Generator$j]]> -class CartesianProductHolder$i { - public: -CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) - : $for j, [[g$(j)_(g$j)]] {} - template <$for j, [[typename T$j]]> - operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const { - return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >( - new CartesianProductGenerator$i<$for j, [[T$j]]>( -$for j,[[ - - static_cast >(g$(j)_) -]])); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder$i& other); - - -$for j [[ - const Generator$j g$(j)_; - -]] -}; // class CartesianProductHolder$i - -]] - -# endif // GTEST_HAS_COMBINE - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util.h deleted file mode 100644 index 97533993c0c..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-param-util.h +++ /dev/null @@ -1,883 +0,0 @@ -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Type and function utilities for implementing parameterized tests. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-port.h" -#include "gtest/gtest-printers.h" - -namespace testing { -// Input to a parameterized test name generator, describing a test parameter. -// Consists of the parameter value and the integer parameter index. -template -struct TestParamInfo { - TestParamInfo(const ParamType& a_param, size_t an_index) : - param(a_param), - index(an_index) {} - ParamType param; - size_t index; -}; - -// A builtin parameterized test name generator which returns the result of -// testing::PrintToString. -struct PrintToStringParamName { - template - std::string operator()(const TestParamInfo& info) const { - return PrintToString(info.param); - } -}; - -namespace internal { - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// Utility Functions - -// Outputs a message explaining invalid registration of different -// fixture class for the same test suite. This may happen when -// TEST_P macro is used to define two tests with the same name -// but in different namespaces. -GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name, - CodeLocation code_location); - -template class ParamGeneratorInterface; -template class ParamGenerator; - -// Interface for iterating over elements provided by an implementation -// of ParamGeneratorInterface. -template -class ParamIteratorInterface { - public: - virtual ~ParamIteratorInterface() {} - // A pointer to the base generator instance. - // Used only for the purposes of iterator comparison - // to make sure that two iterators belong to the same generator. - virtual const ParamGeneratorInterface* BaseGenerator() const = 0; - // Advances iterator to point to the next element - // provided by the generator. The caller is responsible - // for not calling Advance() on an iterator equal to - // BaseGenerator()->End(). - virtual void Advance() = 0; - // Clones the iterator object. Used for implementing copy semantics - // of ParamIterator. - virtual ParamIteratorInterface* Clone() const = 0; - // Dereferences the current iterator and provides (read-only) access - // to the pointed value. It is the caller's responsibility not to call - // Current() on an iterator equal to BaseGenerator()->End(). - // Used for implementing ParamGenerator::operator*(). - virtual const T* Current() const = 0; - // Determines whether the given iterator and other point to the same - // element in the sequence generated by the generator. - // Used for implementing ParamGenerator::operator==(). - virtual bool Equals(const ParamIteratorInterface& other) const = 0; -}; - -// Class iterating over elements provided by an implementation of -// ParamGeneratorInterface. It wraps ParamIteratorInterface -// and implements the const forward iterator concept. -template -class ParamIterator { - public: - typedef T value_type; - typedef const T& reference; - typedef ptrdiff_t difference_type; - - // ParamIterator assumes ownership of the impl_ pointer. - ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} - ParamIterator& operator=(const ParamIterator& other) { - if (this != &other) - impl_.reset(other.impl_->Clone()); - return *this; - } - - const T& operator*() const { return *impl_->Current(); } - const T* operator->() const { return impl_->Current(); } - // Prefix version of operator++. - ParamIterator& operator++() { - impl_->Advance(); - return *this; - } - // Postfix version of operator++. - ParamIterator operator++(int /*unused*/) { - ParamIteratorInterface* clone = impl_->Clone(); - impl_->Advance(); - return ParamIterator(clone); - } - bool operator==(const ParamIterator& other) const { - return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); - } - bool operator!=(const ParamIterator& other) const { - return !(*this == other); - } - - private: - friend class ParamGenerator; - explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} - std::unique_ptr > impl_; -}; - -// ParamGeneratorInterface is the binary interface to access generators -// defined in other translation units. -template -class ParamGeneratorInterface { - public: - typedef T ParamType; - - virtual ~ParamGeneratorInterface() {} - - // Generator interface definition - virtual ParamIteratorInterface* Begin() const = 0; - virtual ParamIteratorInterface* End() const = 0; -}; - -// Wraps ParamGeneratorInterface and provides general generator syntax -// compatible with the STL Container concept. -// This class implements copy initialization semantics and the contained -// ParamGeneratorInterface instance is shared among all copies -// of the original object. This is possible because that instance is immutable. -template -class ParamGenerator { - public: - typedef ParamIterator iterator; - - explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} - ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} - - ParamGenerator& operator=(const ParamGenerator& other) { - impl_ = other.impl_; - return *this; - } - - iterator begin() const { return iterator(impl_->Begin()); } - iterator end() const { return iterator(impl_->End()); } - - private: - std::shared_ptr > impl_; -}; - -// Generates values from a range of two comparable values. Can be used to -// generate sequences of user-defined types that implement operator+() and -// operator<(). -// This class is used in the Range() function. -template -class RangeGenerator : public ParamGeneratorInterface { - public: - RangeGenerator(T begin, T end, IncrementT step) - : begin_(begin), end_(end), - step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} - ~RangeGenerator() override {} - - ParamIteratorInterface* Begin() const override { - return new Iterator(this, begin_, 0, step_); - } - ParamIteratorInterface* End() const override { - return new Iterator(this, end_, end_index_, step_); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, T value, int index, - IncrementT step) - : base_(base), value_(value), index_(index), step_(step) {} - ~Iterator() override {} - - const ParamGeneratorInterface* BaseGenerator() const override { - return base_; - } - void Advance() override { - value_ = static_cast(value_ + step_); - index_++; - } - ParamIteratorInterface* Clone() const override { - return new Iterator(*this); - } - const T* Current() const override { return &value_; } - bool Equals(const ParamIteratorInterface& other) const override { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const int other_index = - CheckedDowncastToActualType(&other)->index_; - return index_ == other_index; - } - - private: - Iterator(const Iterator& other) - : ParamIteratorInterface(), - base_(other.base_), value_(other.value_), index_(other.index_), - step_(other.step_) {} - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - T value_; - int index_; - const IncrementT step_; - }; // class RangeGenerator::Iterator - - static int CalculateEndIndex(const T& begin, - const T& end, - const IncrementT& step) { - int end_index = 0; - for (T i = begin; i < end; i = static_cast(i + step)) - end_index++; - return end_index; - } - - // No implementation - assignment is unsupported. - void operator=(const RangeGenerator& other); - - const T begin_; - const T end_; - const IncrementT step_; - // The index for the end() iterator. All the elements in the generated - // sequence are indexed (0-based) to aid iterator comparison. - const int end_index_; -}; // class RangeGenerator - - -// Generates values from a pair of STL-style iterators. Used in the -// ValuesIn() function. The elements are copied from the source range -// since the source can be located on the stack, and the generator -// is likely to persist beyond that stack frame. -template -class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { - public: - template - ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) - : container_(begin, end) {} - ~ValuesInIteratorRangeGenerator() override {} - - ParamIteratorInterface* Begin() const override { - return new Iterator(this, container_.begin()); - } - ParamIteratorInterface* End() const override { - return new Iterator(this, container_.end()); - } - - private: - typedef typename ::std::vector ContainerType; - - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - typename ContainerType::const_iterator iterator) - : base_(base), iterator_(iterator) {} - ~Iterator() override {} - - const ParamGeneratorInterface* BaseGenerator() const override { - return base_; - } - void Advance() override { - ++iterator_; - value_.reset(); - } - ParamIteratorInterface* Clone() const override { - return new Iterator(*this); - } - // We need to use cached value referenced by iterator_ because *iterator_ - // can return a temporary object (and of type other then T), so just - // having "return &*iterator_;" doesn't work. - // value_ is updated here and not in Advance() because Advance() - // can advance iterator_ beyond the end of the range, and we cannot - // detect that fact. The client code, on the other hand, is - // responsible for not calling Current() on an out-of-range iterator. - const T* Current() const override { - if (value_.get() == nullptr) value_.reset(new T(*iterator_)); - return value_.get(); - } - bool Equals(const ParamIteratorInterface& other) const override { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - return iterator_ == - CheckedDowncastToActualType(&other)->iterator_; - } - - private: - Iterator(const Iterator& other) - // The explicit constructor call suppresses a false warning - // emitted by gcc when supplied with the -Wextra option. - : ParamIteratorInterface(), - base_(other.base_), - iterator_(other.iterator_) {} - - const ParamGeneratorInterface* const base_; - typename ContainerType::const_iterator iterator_; - // A cached value of *iterator_. We keep it here to allow access by - // pointer in the wrapping iterator's operator->(). - // value_ needs to be mutable to be accessed in Current(). - // Use of std::unique_ptr helps manage cached value's lifetime, - // which is bound by the lifespan of the iterator itself. - mutable std::unique_ptr value_; - }; // class ValuesInIteratorRangeGenerator::Iterator - - // No implementation - assignment is unsupported. - void operator=(const ValuesInIteratorRangeGenerator& other); - - const ContainerType container_; -}; // class ValuesInIteratorRangeGenerator - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Default parameterized test name generator, returns a string containing the -// integer test parameter index. -template -std::string DefaultParamName(const TestParamInfo& info) { - Message name_stream; - name_stream << info.index; - return name_stream.GetString(); -} - -template -void TestNotEmpty() { - static_assert(sizeof(T) == 0, "Empty arguments are not allowed."); -} -template -void TestNotEmpty(const T&) {} - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Stores a parameter value and later creates tests parameterized with that -// value. -template -class ParameterizedTestFactory : public TestFactoryBase { - public: - typedef typename TestClass::ParamType ParamType; - explicit ParameterizedTestFactory(ParamType parameter) : - parameter_(parameter) {} - Test* CreateTest() override { - TestClass::SetParam(¶meter_); - return new TestClass(); - } - - private: - const ParamType parameter_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); -}; - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// TestMetaFactoryBase is a base class for meta-factories that create -// test factories for passing into MakeAndRegisterTestInfo function. -template -class TestMetaFactoryBase { - public: - virtual ~TestMetaFactoryBase() {} - - virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; -}; - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// TestMetaFactory creates test factories for passing into -// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives -// ownership of test factory pointer, same factory object cannot be passed -// into that method twice. But ParameterizedTestSuiteInfo is going to call -// it for each Test/Parameter value combination. Thus it needs meta factory -// creator class. -template -class TestMetaFactory - : public TestMetaFactoryBase { - public: - using ParamType = typename TestSuite::ParamType; - - TestMetaFactory() {} - - TestFactoryBase* CreateTestFactory(ParamType parameter) override { - return new ParameterizedTestFactory(parameter); - } - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); -}; - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// ParameterizedTestSuiteInfoBase is a generic interface -// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase -// accumulates test information provided by TEST_P macro invocations -// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations -// and uses that information to register all resulting test instances -// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds -// a collection of pointers to the ParameterizedTestSuiteInfo objects -// and calls RegisterTests() on each of them when asked. -class ParameterizedTestSuiteInfoBase { - public: - virtual ~ParameterizedTestSuiteInfoBase() {} - - // Base part of test suite name for display purposes. - virtual const std::string& GetTestSuiteName() const = 0; - // Test case id to verify identity. - virtual TypeId GetTestSuiteTypeId() const = 0; - // UnitTest class invokes this method to register tests in this - // test suite right before running them in RUN_ALL_TESTS macro. - // This method should not be called more than once on any single - // instance of a ParameterizedTestSuiteInfoBase derived class. - virtual void RegisterTests() = 0; - - protected: - ParameterizedTestSuiteInfoBase() {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); -}; - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P -// macro invocations for a particular test suite and generators -// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that -// test suite. It registers tests with all values generated by all -// generators when asked. -template -class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { - public: - // ParamType and GeneratorCreationFunc are private types but are required - // for declarations of public methods AddTestPattern() and - // AddTestSuiteInstantiation(). - using ParamType = typename TestSuite::ParamType; - // A function that returns an instance of appropriate generator type. - typedef ParamGenerator(GeneratorCreationFunc)(); - using ParamNameGeneratorFunc = std::string(const TestParamInfo&); - - explicit ParameterizedTestSuiteInfo(const char* name, - CodeLocation code_location) - : test_suite_name_(name), code_location_(code_location) {} - - // Test case base name for display purposes. - const std::string& GetTestSuiteName() const override { - return test_suite_name_; - } - // Test case id to verify identity. - TypeId GetTestSuiteTypeId() const override { return GetTypeId(); } - // TEST_P macro uses AddTestPattern() to record information - // about a single test in a LocalTestInfo structure. - // test_suite_name is the base name of the test suite (without invocation - // prefix). test_base_name is the name of an individual test without - // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is - // test suite base name and DoBar is test base name. - void AddTestPattern(const char* test_suite_name, const char* test_base_name, - TestMetaFactoryBase* meta_factory) { - tests_.push_back(std::shared_ptr( - new TestInfo(test_suite_name, test_base_name, meta_factory))); - } - // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information - // about a generator. - int AddTestSuiteInstantiation(const std::string& instantiation_name, - GeneratorCreationFunc* func, - ParamNameGeneratorFunc* name_func, - const char* file, int line) { - instantiations_.push_back( - InstantiationInfo(instantiation_name, func, name_func, file, line)); - return 0; // Return value used only to run this method in namespace scope. - } - // UnitTest class invokes this method to register tests in this test suite - // test suites right before running tests in RUN_ALL_TESTS macro. - // This method should not be called more than once on any single - // instance of a ParameterizedTestSuiteInfoBase derived class. - // UnitTest has a guard to prevent from calling this method more than once. - void RegisterTests() override { - for (typename TestInfoContainer::iterator test_it = tests_.begin(); - test_it != tests_.end(); ++test_it) { - std::shared_ptr test_info = *test_it; - for (typename InstantiationContainer::iterator gen_it = - instantiations_.begin(); gen_it != instantiations_.end(); - ++gen_it) { - const std::string& instantiation_name = gen_it->name; - ParamGenerator generator((*gen_it->generator)()); - ParamNameGeneratorFunc* name_func = gen_it->name_func; - const char* file = gen_it->file; - int line = gen_it->line; - - std::string test_suite_name; - if ( !instantiation_name.empty() ) - test_suite_name = instantiation_name + "/"; - test_suite_name += test_info->test_suite_base_name; - - size_t i = 0; - std::set test_param_names; - for (typename ParamGenerator::iterator param_it = - generator.begin(); - param_it != generator.end(); ++param_it, ++i) { - Message test_name_stream; - - std::string param_name = name_func( - TestParamInfo(*param_it, i)); - - GTEST_CHECK_(IsValidParamName(param_name)) - << "Parameterized test name '" << param_name - << "' is invalid, in " << file - << " line " << line << std::endl; - - GTEST_CHECK_(test_param_names.count(param_name) == 0) - << "Duplicate parameterized test name '" << param_name - << "', in " << file << " line " << line << std::endl; - - test_param_names.insert(param_name); - - if (!test_info->test_base_name.empty()) { - test_name_stream << test_info->test_base_name << "/"; - } - test_name_stream << param_name; - MakeAndRegisterTestInfo( - test_suite_name.c_str(), test_name_stream.GetString().c_str(), - nullptr, // No type parameter. - PrintToString(*param_it).c_str(), code_location_, - GetTestSuiteTypeId(), - SuiteApiResolver::GetSetUpCaseOrSuite(file, line), - SuiteApiResolver::GetTearDownCaseOrSuite(file, line), - test_info->test_meta_factory->CreateTestFactory(*param_it)); - } // for param_it - } // for gen_it - } // for test_it - } // RegisterTests - - private: - // LocalTestInfo structure keeps information about a single test registered - // with TEST_P macro. - struct TestInfo { - TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, - TestMetaFactoryBase* a_test_meta_factory) - : test_suite_base_name(a_test_suite_base_name), - test_base_name(a_test_base_name), - test_meta_factory(a_test_meta_factory) {} - - const std::string test_suite_base_name; - const std::string test_base_name; - const std::unique_ptr > test_meta_factory; - }; - using TestInfoContainer = ::std::vector >; - // Records data received from INSTANTIATE_TEST_SUITE_P macros: - // - struct InstantiationInfo { - InstantiationInfo(const std::string &name_in, - GeneratorCreationFunc* generator_in, - ParamNameGeneratorFunc* name_func_in, - const char* file_in, - int line_in) - : name(name_in), - generator(generator_in), - name_func(name_func_in), - file(file_in), - line(line_in) {} - - std::string name; - GeneratorCreationFunc* generator; - ParamNameGeneratorFunc* name_func; - const char* file; - int line; - }; - typedef ::std::vector InstantiationContainer; - - static bool IsValidParamName(const std::string& name) { - // Check for empty string - if (name.empty()) - return false; - - // Check for invalid characters - for (std::string::size_type index = 0; index < name.size(); ++index) { - if (!isalnum(name[index]) && name[index] != '_') - return false; - } - - return true; - } - - const std::string test_suite_name_; - CodeLocation code_location_; - TestInfoContainer tests_; - InstantiationContainer instantiations_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo); -}; // class ParameterizedTestSuiteInfo - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -template -using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// ParameterizedTestSuiteRegistry contains a map of -// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P -// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding -// ParameterizedTestSuiteInfo descriptors. -class ParameterizedTestSuiteRegistry { - public: - ParameterizedTestSuiteRegistry() {} - ~ParameterizedTestSuiteRegistry() { - for (auto& test_suite_info : test_suite_infos_) { - delete test_suite_info; - } - } - - // Looks up or creates and returns a structure containing information about - // tests and instantiations of a particular test suite. - template - ParameterizedTestSuiteInfo* GetTestSuitePatternHolder( - const char* test_suite_name, CodeLocation code_location) { - ParameterizedTestSuiteInfo* typed_test_info = nullptr; - for (auto& test_suite_info : test_suite_infos_) { - if (test_suite_info->GetTestSuiteName() == test_suite_name) { - if (test_suite_info->GetTestSuiteTypeId() != GetTypeId()) { - // Complain about incorrect usage of Google Test facilities - // and terminate the program since we cannot guaranty correct - // test suite setup and tear-down in this case. - ReportInvalidTestSuiteType(test_suite_name, code_location); - posix::Abort(); - } else { - // At this point we are sure that the object we found is of the same - // type we are looking for, so we downcast it to that type - // without further checks. - typed_test_info = CheckedDowncastToActualType< - ParameterizedTestSuiteInfo >(test_suite_info); - } - break; - } - } - if (typed_test_info == nullptr) { - typed_test_info = new ParameterizedTestSuiteInfo( - test_suite_name, code_location); - test_suite_infos_.push_back(typed_test_info); - } - return typed_test_info; - } - void RegisterTests() { - for (auto& test_suite_info : test_suite_infos_) { - test_suite_info->RegisterTests(); - } - } -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - template - ParameterizedTestCaseInfo* GetTestCasePatternHolder( - const char* test_case_name, CodeLocation code_location) { - return GetTestSuitePatternHolder(test_case_name, code_location); - } - -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - private: - using TestSuiteInfoContainer = ::std::vector; - - TestSuiteInfoContainer test_suite_infos_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); -}; - -} // namespace internal - -// Forward declarations of ValuesIn(), which is implemented in -// include/gtest/gtest-param-test.h. -template -internal::ParamGenerator ValuesIn( - const Container& container); - -namespace internal { -// Used in the Values() function to provide polymorphic capabilities. - -template -class ValueArray { - public: - ValueArray(Ts... v) : v_{std::move(v)...} {} - - template - operator ParamGenerator() const { // NOLINT - return ValuesIn(MakeVector(MakeIndexSequence())); - } - - private: - template - std::vector MakeVector(IndexSequence) const { - return std::vector{static_cast(v_.template Get())...}; - } - - FlatTuple v_; -}; - -template -class CartesianProductGenerator - : public ParamGeneratorInterface<::std::tuple> { - public: - typedef ::std::tuple ParamType; - - CartesianProductGenerator(const std::tuple...>& g) - : generators_(g) {} - ~CartesianProductGenerator() override {} - - ParamIteratorInterface* Begin() const override { - return new Iterator(this, generators_, false); - } - ParamIteratorInterface* End() const override { - return new Iterator(this, generators_, true); - } - - private: - template - class IteratorImpl; - template - class IteratorImpl> - : public ParamIteratorInterface { - public: - IteratorImpl(const ParamGeneratorInterface* base, - const std::tuple...>& generators, bool is_end) - : base_(base), - begin_(std::get(generators).begin()...), - end_(std::get(generators).end()...), - current_(is_end ? end_ : begin_) { - ComputeCurrentValue(); - } - ~IteratorImpl() override {} - - const ParamGeneratorInterface* BaseGenerator() const override { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - void Advance() override { - assert(!AtEnd()); - // Advance the last iterator. - ++std::get(current_); - // if that reaches end, propagate that up. - AdvanceIfEnd(); - ComputeCurrentValue(); - } - ParamIteratorInterface* Clone() const override { - return new IteratorImpl(*this); - } - - const ParamType* Current() const override { return current_value_.get(); } - - bool Equals(const ParamIteratorInterface& other) const override { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const IteratorImpl* typed_other = - CheckedDowncastToActualType(&other); - - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - if (AtEnd() && typed_other->AtEnd()) return true; - - bool same = true; - bool dummy[] = { - (same = same && std::get(current_) == - std::get(typed_other->current_))...}; - (void)dummy; - return same; - } - - private: - template - void AdvanceIfEnd() { - if (std::get(current_) != std::get(end_)) return; - - bool last = ThisI == 0; - if (last) { - // We are done. Nothing else to propagate. - return; - } - - constexpr size_t NextI = ThisI - (ThisI != 0); - std::get(current_) = std::get(begin_); - ++std::get(current_); - AdvanceIfEnd(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = std::make_shared(*std::get(current_)...); - } - bool AtEnd() const { - bool at_end = false; - bool dummy[] = { - (at_end = at_end || std::get(current_) == std::get(end_))...}; - (void)dummy; - return at_end; - } - - const ParamGeneratorInterface* const base_; - std::tuple::iterator...> begin_; - std::tuple::iterator...> end_; - std::tuple::iterator...> current_; - std::shared_ptr current_value_; - }; - - using Iterator = IteratorImpl::type>; - - std::tuple...> generators_; -}; - -template -class CartesianProductHolder { - public: - CartesianProductHolder(const Gen&... g) : generators_(g...) {} - template - operator ParamGenerator<::std::tuple>() const { - return ParamGenerator<::std::tuple>( - new CartesianProductGenerator(generators_)); - } - - private: - std::tuple generators_; -}; - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-port-arch.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-port-arch.h deleted file mode 100644 index cece93dba12..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-port-arch.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2015, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file defines the GTEST_OS_* macro. -// It is separate from gtest-port.h so that custom/gtest-port.h can include it. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ - -// Determines the platform on which Google Test is compiled. -#ifdef __CYGWIN__ -# define GTEST_OS_CYGWIN 1 -# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__) -# define GTEST_OS_WINDOWS_MINGW 1 -# define GTEST_OS_WINDOWS 1 -#elif defined _WIN32 -# define GTEST_OS_WINDOWS 1 -# ifdef _WIN32_WCE -# define GTEST_OS_WINDOWS_MOBILE 1 -# elif defined(WINAPI_FAMILY) -# include -# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -# define GTEST_OS_WINDOWS_DESKTOP 1 -# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) -# define GTEST_OS_WINDOWS_PHONE 1 -# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) -# define GTEST_OS_WINDOWS_RT 1 -# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE) -# define GTEST_OS_WINDOWS_PHONE 1 -# define GTEST_OS_WINDOWS_TV_TITLE 1 -# else - // WINAPI_FAMILY defined but no known partition matched. - // Default to desktop. -# define GTEST_OS_WINDOWS_DESKTOP 1 -# endif -# else -# define GTEST_OS_WINDOWS_DESKTOP 1 -# endif // _WIN32_WCE -#elif defined __OS2__ -# define GTEST_OS_OS2 1 -#elif defined __APPLE__ -# define GTEST_OS_MAC 1 -# if TARGET_OS_IPHONE -# define GTEST_OS_IOS 1 -# endif -#elif defined __DragonFly__ -# define GTEST_OS_DRAGONFLY 1 -#elif defined __FreeBSD__ -# define GTEST_OS_FREEBSD 1 -#elif defined __Fuchsia__ -# define GTEST_OS_FUCHSIA 1 -#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__) -# define GTEST_OS_GNU_KFREEBSD 1 -#elif defined __linux__ -# define GTEST_OS_LINUX 1 -# if defined __ANDROID__ -# define GTEST_OS_LINUX_ANDROID 1 -# endif -#elif defined __MVS__ -# define GTEST_OS_ZOS 1 -#elif defined(__sun) && defined(__SVR4) -# define GTEST_OS_SOLARIS 1 -#elif defined(_AIX) -# define GTEST_OS_AIX 1 -#elif defined(__hpux) -# define GTEST_OS_HPUX 1 -#elif defined __native_client__ -# define GTEST_OS_NACL 1 -#elif defined __NetBSD__ -# define GTEST_OS_NETBSD 1 -#elif defined __OpenBSD__ -# define GTEST_OS_OPENBSD 1 -#elif defined __QNX__ -# define GTEST_OS_QNX 1 -#elif defined(__HAIKU__) -#define GTEST_OS_HAIKU 1 -#endif // __CYGWIN__ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-port.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-port.h deleted file mode 100644 index 063fcb1083b..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-port.h +++ /dev/null @@ -1,2231 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// Low-level types and utilities for porting Google Test to various -// platforms. All macros ending with _ and symbols defined in an -// internal namespace are subject to change without notice. Code -// outside Google Test MUST NOT USE THEM DIRECTLY. Macros that don't -// end with _ are part of Google Test's public API and can be used by -// code outside Google Test. -// -// This file is fundamental to Google Test. All other Google Test source -// files are expected to #include this. Therefore, it cannot #include -// any other Google Test header. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ - -// Environment-describing macros -// ----------------------------- -// -// Google Test can be used in many different environments. Macros in -// this section tell Google Test what kind of environment it is being -// used in, such that Google Test can provide environment-specific -// features and implementations. -// -// Google Test tries to automatically detect the properties of its -// environment, so users usually don't need to worry about these -// macros. However, the automatic detection is not perfect. -// Sometimes it's necessary for a user to define some of the following -// macros in the build script to override Google Test's decisions. -// -// If the user doesn't define a macro in the list, Google Test will -// provide a default definition. After this header is #included, all -// macros in this list will be defined to either 1 or 0. -// -// Notes to maintainers: -// - Each macro here is a user-tweakable knob; do not grow the list -// lightly. -// - Use #if to key off these macros. Don't use #ifdef or "#if -// defined(...)", which will not work as these macros are ALWAYS -// defined. -// -// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) -// is/isn't available. -// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions -// are enabled. -// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular -// expressions are/aren't available. -// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that -// is/isn't available. -// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't -// enabled. -// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that -// std::wstring does/doesn't work (Google Test can -// be used where std::wstring is unavailable). -// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the -// compiler supports Microsoft's "Structured -// Exception Handling". -// GTEST_HAS_STREAM_REDIRECTION -// - Define it to 1/0 to indicate whether the -// platform supports I/O stream redirection using -// dup() and dup2(). -// GTEST_LINKED_AS_SHARED_LIBRARY -// - Define to 1 when compiling tests that use -// Google Test as a shared library (known as -// DLL on Windows). -// GTEST_CREATE_SHARED_LIBRARY -// - Define to 1 when compiling Google Test itself -// as a shared library. -// GTEST_DEFAULT_DEATH_TEST_STYLE -// - The default value of --gtest_death_test_style. -// The legacy default has been "fast" in the open -// source version since 2008. The recommended value -// is "threadsafe", and can be set in -// custom/gtest-port.h. - -// Platform-indicating macros -// -------------------------- -// -// Macros indicating the platform on which Google Test is being used -// (a macro is defined to 1 if compiled on the given platform; -// otherwise UNDEFINED -- it's never defined to 0.). Google Test -// defines these macros automatically. Code outside Google Test MUST -// NOT define them. -// -// GTEST_OS_AIX - IBM AIX -// GTEST_OS_CYGWIN - Cygwin -// GTEST_OS_DRAGONFLY - DragonFlyBSD -// GTEST_OS_FREEBSD - FreeBSD -// GTEST_OS_FUCHSIA - Fuchsia -// GTEST_OS_GNU_KFREEBSD - GNU/kFreeBSD -// GTEST_OS_HAIKU - Haiku -// GTEST_OS_HPUX - HP-UX -// GTEST_OS_LINUX - Linux -// GTEST_OS_LINUX_ANDROID - Google Android -// GTEST_OS_MAC - Mac OS X -// GTEST_OS_IOS - iOS -// GTEST_OS_NACL - Google Native Client (NaCl) -// GTEST_OS_NETBSD - NetBSD -// GTEST_OS_OPENBSD - OpenBSD -// GTEST_OS_OS2 - OS/2 -// GTEST_OS_QNX - QNX -// GTEST_OS_SOLARIS - Sun Solaris -// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) -// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop -// GTEST_OS_WINDOWS_MINGW - MinGW -// GTEST_OS_WINDOWS_MOBILE - Windows Mobile -// GTEST_OS_WINDOWS_PHONE - Windows Phone -// GTEST_OS_WINDOWS_RT - Windows Store App/WinRT -// GTEST_OS_ZOS - z/OS -// -// Among the platforms, Cygwin, Linux, Mac OS X, and Windows have the -// most stable support. Since core members of the Google Test project -// don't have access to other platforms, support for them may be less -// stable. If you notice any problems on your platform, please notify -// googletestframework@googlegroups.com (patches for fixing them are -// even more welcome!). -// -// It is possible that none of the GTEST_OS_* macros are defined. - -// Feature-indicating macros -// ------------------------- -// -// Macros indicating which Google Test features are available (a macro -// is defined to 1 if the corresponding feature is supported; -// otherwise UNDEFINED -- it's never defined to 0.). Google Test -// defines these macros automatically. Code outside Google Test MUST -// NOT define them. -// -// These macros are public so that portable tests can be written. -// Such tests typically surround code using a feature with an #if -// which controls that code. For example: -// -// #if GTEST_HAS_DEATH_TEST -// EXPECT_DEATH(DoSomethingDeadly()); -// #endif -// -// GTEST_HAS_DEATH_TEST - death tests -// GTEST_HAS_TYPED_TEST - typed tests -// GTEST_HAS_TYPED_TEST_P - type-parameterized tests -// GTEST_IS_THREADSAFE - Google Test is thread-safe. -// GOOGLETEST_CM0007 DO NOT DELETE -// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with -// GTEST_HAS_POSIX_RE (see above) which users can -// define themselves. -// GTEST_USES_SIMPLE_RE - our own simple regex is used; -// the above RE\b(s) are mutually exclusive. - -// Misc public macros -// ------------------ -// -// GTEST_FLAG(flag_name) - references the variable corresponding to -// the given Google Test flag. - -// Internal utilities -// ------------------ -// -// The following macros and utilities are for Google Test's INTERNAL -// use only. Code outside Google Test MUST NOT USE THEM DIRECTLY. -// -// Macros for basic C++ coding: -// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. -// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a -// variable don't have to be used. -// GTEST_DISALLOW_ASSIGN_ - disables operator=. -// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. -// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. -// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is -// suppressed (constant conditional). -// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127 -// is suppressed. -// -// Synchronization: -// Mutex, MutexLock, ThreadLocal, GetThreadCount() -// - synchronization primitives. -// -// Regular expressions: -// RE - a simple regular expression class using the POSIX -// Extended Regular Expression syntax on UNIX-like platforms -// GOOGLETEST_CM0008 DO NOT DELETE -// or a reduced regular exception syntax on other -// platforms, including Windows. -// Logging: -// GTEST_LOG_() - logs messages at the specified severity level. -// LogToStderr() - directs all log messages to stderr. -// FlushInfoLog() - flushes informational log messages. -// -// Stdout and stderr capturing: -// CaptureStdout() - starts capturing stdout. -// GetCapturedStdout() - stops capturing stdout and returns the captured -// string. -// CaptureStderr() - starts capturing stderr. -// GetCapturedStderr() - stops capturing stderr and returns the captured -// string. -// -// Integer types: -// TypeWithSize - maps an integer to a int type. -// Int32, UInt32, Int64, UInt64, TimeInMillis -// - integers of known sizes. -// BiggestInt - the biggest signed integer type. -// -// Command-line utilities: -// GTEST_DECLARE_*() - declares a flag. -// GTEST_DEFINE_*() - defines a flag. -// GetInjectableArgvs() - returns the command line as a vector of strings. -// -// Environment variable utilities: -// GetEnv() - gets the value of an environment variable. -// BoolFromGTestEnv() - parses a bool environment variable. -// Int32FromGTestEnv() - parses an Int32 environment variable. -// StringFromGTestEnv() - parses a string environment variable. -// -// Deprecation warnings: -// GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as -// deprecated; calling a marked function -// should generate a compiler warning - -#include // for isspace, etc -#include // for ptrdiff_t -#include -#include -#include -#include -#include - -#ifndef _WIN32_WCE -# include -# include -#endif // !_WIN32_WCE - -#if defined __APPLE__ -# include -# include -#endif - -#include // NOLINT -#include // NOLINT -#include // NOLINT -#include // NOLINT -#include -#include -#include // NOLINT - -#include "gtest/internal/gtest-port-arch.h" -#include "gtest/internal/custom/gtest-port.h" - -#if !defined(GTEST_DEV_EMAIL_) -# define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" -# define GTEST_FLAG_PREFIX_ "gtest_" -# define GTEST_FLAG_PREFIX_DASH_ "gtest-" -# define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" -# define GTEST_NAME_ "Google Test" -# define GTEST_PROJECT_URL_ "https://github.com/google/googletest/" -#endif // !defined(GTEST_DEV_EMAIL_) - -#if !defined(GTEST_INIT_GOOGLE_TEST_NAME_) -# define GTEST_INIT_GOOGLE_TEST_NAME_ "testing::InitGoogleTest" -#endif // !defined(GTEST_INIT_GOOGLE_TEST_NAME_) - -// Determines the version of gcc that is used to compile this. -#ifdef __GNUC__ -// 40302 means version 4.3.2. -# define GTEST_GCC_VER_ \ - (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) -#endif // __GNUC__ - -// Macros for disabling Microsoft Visual C++ warnings. -// -// GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385) -// /* code that triggers warnings C4800 and C4385 */ -// GTEST_DISABLE_MSC_WARNINGS_POP_() -#if defined(_MSC_VER) -# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \ - __pragma(warning(push)) \ - __pragma(warning(disable: warnings)) -# define GTEST_DISABLE_MSC_WARNINGS_POP_() \ - __pragma(warning(pop)) -#else -// Not all compilers are MSVC -# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) -# define GTEST_DISABLE_MSC_WARNINGS_POP_() -#endif - -// Clang on Windows does not understand MSVC's pragma warning. -// We need clang-specific way to disable function deprecation warning. -#ifdef __clang__ -# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \ - _Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"") -#define GTEST_DISABLE_MSC_DEPRECATED_POP_() \ - _Pragma("clang diagnostic pop") -#else -# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \ - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) -# define GTEST_DISABLE_MSC_DEPRECATED_POP_() \ - GTEST_DISABLE_MSC_WARNINGS_POP_() -#endif - -// Brings in definitions for functions used in the testing::internal::posix -// namespace (read, write, close, chdir, isatty, stat). We do not currently -// use them on Windows Mobile. -#if GTEST_OS_WINDOWS -# if !GTEST_OS_WINDOWS_MOBILE -# include -# include -# endif -// In order to avoid having to include , use forward declaration -#if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR) -// MinGW defined _CRITICAL_SECTION and _RTL_CRITICAL_SECTION as two -// separate (equivalent) structs, instead of using typedef -typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION; -#else -// Assume CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION. -// This assumption is verified by -// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION. -typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; -#endif -#else -// This assumes that non-Windows OSes provide unistd.h. For OSes where this -// is not the case, we need to include headers that provide the functions -// mentioned above. -# include -# include -#endif // GTEST_OS_WINDOWS - -#if GTEST_OS_LINUX_ANDROID -// Used to define __ANDROID_API__ matching the target NDK API level. -# include // NOLINT -#endif - -// Defines this to true if and only if Google Test can use POSIX regular -// expressions. -#ifndef GTEST_HAS_POSIX_RE -# if GTEST_OS_LINUX_ANDROID -// On Android, is only available starting with Gingerbread. -# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) -# else -# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) -# endif -#endif - -#if GTEST_USES_PCRE -// The appropriate headers have already been included. - -#elif GTEST_HAS_POSIX_RE - -// On some platforms, needs someone to define size_t, and -// won't compile otherwise. We can #include it here as we already -// included , which is guaranteed to define size_t through -// . -# include // NOLINT - -# define GTEST_USES_POSIX_RE 1 - -#elif GTEST_OS_WINDOWS - -// is not available on Windows. Use our own simple regex -// implementation instead. -# define GTEST_USES_SIMPLE_RE 1 - -#else - -// may not be available on this platform. Use our own -// simple regex implementation instead. -# define GTEST_USES_SIMPLE_RE 1 - -#endif // GTEST_USES_PCRE - -#ifndef GTEST_HAS_EXCEPTIONS -// The user didn't tell us whether exceptions are enabled, so we need -// to figure it out. -# if defined(_MSC_VER) && defined(_CPPUNWIND) -// MSVC defines _CPPUNWIND to 1 if and only if exceptions are enabled. -# define GTEST_HAS_EXCEPTIONS 1 -# elif defined(__BORLANDC__) -// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS -// macro to enable exceptions, so we'll do the same. -// Assumes that exceptions are enabled by default. -# ifndef _HAS_EXCEPTIONS -# define _HAS_EXCEPTIONS 1 -# endif // _HAS_EXCEPTIONS -# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS -# elif defined(__clang__) -// clang defines __EXCEPTIONS if and only if exceptions are enabled before clang -// 220714, but if and only if cleanups are enabled after that. In Obj-C++ files, -// there can be cleanups for ObjC exceptions which also need cleanups, even if -// C++ exceptions are disabled. clang has __has_feature(cxx_exceptions) which -// checks for C++ exceptions starting at clang r206352, but which checked for -// cleanups prior to that. To reliably check for C++ exception availability with -// clang, check for -// __EXCEPTIONS && __has_feature(cxx_exceptions). -# define GTEST_HAS_EXCEPTIONS (__EXCEPTIONS && __has_feature(cxx_exceptions)) -# elif defined(__GNUC__) && __EXCEPTIONS -// gcc defines __EXCEPTIONS to 1 if and only if exceptions are enabled. -# define GTEST_HAS_EXCEPTIONS 1 -# elif defined(__SUNPRO_CC) -// Sun Pro CC supports exceptions. However, there is no compile-time way of -// detecting whether they are enabled or not. Therefore, we assume that -// they are enabled unless the user tells us otherwise. -# define GTEST_HAS_EXCEPTIONS 1 -# elif defined(__IBMCPP__) && __EXCEPTIONS -// xlC defines __EXCEPTIONS to 1 if and only if exceptions are enabled. -# define GTEST_HAS_EXCEPTIONS 1 -# elif defined(__HP_aCC) -// Exception handling is in effect by default in HP aCC compiler. It has to -// be turned of by +noeh compiler option if desired. -# define GTEST_HAS_EXCEPTIONS 1 -# else -// For other compilers, we assume exceptions are disabled to be -// conservative. -# define GTEST_HAS_EXCEPTIONS 0 -# endif // defined(_MSC_VER) || defined(__BORLANDC__) -#endif // GTEST_HAS_EXCEPTIONS - -#if !defined(GTEST_HAS_STD_STRING) -// Even though we don't use this macro any longer, we keep it in case -// some clients still depend on it. -# define GTEST_HAS_STD_STRING 1 -#elif !GTEST_HAS_STD_STRING -// The user told us that ::std::string isn't available. -# error "::std::string isn't available." -#endif // !defined(GTEST_HAS_STD_STRING) - -#ifndef GTEST_HAS_STD_WSTRING -// The user didn't tell us whether ::std::wstring is available, so we need -// to figure it out. -// Cygwin 1.7 and below doesn't support ::std::wstring. -// Solaris' libc++ doesn't support it either. Android has -// no support for it at least as recent as Froyo (2.2). -#define GTEST_HAS_STD_WSTRING \ - (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ - GTEST_OS_HAIKU)) - -#endif // GTEST_HAS_STD_WSTRING - -// Determines whether RTTI is available. -#ifndef GTEST_HAS_RTTI -// The user didn't tell us whether RTTI is enabled, so we need to -// figure it out. - -# ifdef _MSC_VER - -#ifdef _CPPRTTI // MSVC defines this macro if and only if RTTI is enabled. -# define GTEST_HAS_RTTI 1 -# else -# define GTEST_HAS_RTTI 0 -# endif - -// Starting with version 4.3.2, gcc defines __GXX_RTTI if and only if RTTI is -// enabled. -# elif defined(__GNUC__) - -# ifdef __GXX_RTTI -// When building against STLport with the Android NDK and with -// -frtti -fno-exceptions, the build fails at link time with undefined -// references to __cxa_bad_typeid. Note sure if STL or toolchain bug, -// so disable RTTI when detected. -# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ - !defined(__EXCEPTIONS) -# define GTEST_HAS_RTTI 0 -# else -# define GTEST_HAS_RTTI 1 -# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS -# else -# define GTEST_HAS_RTTI 0 -# endif // __GXX_RTTI - -// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends -// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the -// first version with C++ support. -# elif defined(__clang__) - -# define GTEST_HAS_RTTI __has_feature(cxx_rtti) - -// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if -// both the typeid and dynamic_cast features are present. -# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) - -# ifdef __RTTI_ALL__ -# define GTEST_HAS_RTTI 1 -# else -# define GTEST_HAS_RTTI 0 -# endif - -# else - -// For all other compilers, we assume RTTI is enabled. -# define GTEST_HAS_RTTI 1 - -# endif // _MSC_VER - -#endif // GTEST_HAS_RTTI - -// It's this header's responsibility to #include when RTTI -// is enabled. -#if GTEST_HAS_RTTI -# include -#endif - -// Determines whether Google Test can use the pthreads library. -#ifndef GTEST_HAS_PTHREAD -// The user didn't tell us explicitly, so we make reasonable assumptions about -// which platforms have pthreads support. -// -// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 -// to your compiler flags. -#define GTEST_HAS_PTHREAD \ - (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX || GTEST_OS_QNX || \ - GTEST_OS_FREEBSD || GTEST_OS_NACL || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \ - GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_OPENBSD || \ - GTEST_OS_HAIKU) -#endif // GTEST_HAS_PTHREAD - -#if GTEST_HAS_PTHREAD -// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is -// true. -# include // NOLINT - -// For timespec and nanosleep, used below. -# include // NOLINT -#endif - -// Determines whether clone(2) is supported. -// Usually it will only be available on Linux, excluding -// Linux on the Itanium architecture. -// Also see http://linux.die.net/man/2/clone. -#ifndef GTEST_HAS_CLONE -// The user didn't tell us, so we need to figure it out. - -# if GTEST_OS_LINUX && !defined(__ia64__) -# if GTEST_OS_LINUX_ANDROID -// On Android, clone() became available at different API levels for each 32-bit -// architecture. -# if defined(__LP64__) || \ - (defined(__arm__) && __ANDROID_API__ >= 9) || \ - (defined(__mips__) && __ANDROID_API__ >= 12) || \ - (defined(__i386__) && __ANDROID_API__ >= 17) -# define GTEST_HAS_CLONE 1 -# else -# define GTEST_HAS_CLONE 0 -# endif -# else -# define GTEST_HAS_CLONE 1 -# endif -# else -# define GTEST_HAS_CLONE 0 -# endif // GTEST_OS_LINUX && !defined(__ia64__) - -#endif // GTEST_HAS_CLONE - -// Determines whether to support stream redirection. This is used to test -// output correctness and to implement death tests. -#ifndef GTEST_HAS_STREAM_REDIRECTION -// By default, we assume that stream redirection is supported on all -// platforms except known mobile ones. -# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT -# define GTEST_HAS_STREAM_REDIRECTION 0 -# else -# define GTEST_HAS_STREAM_REDIRECTION 1 -# endif // !GTEST_OS_WINDOWS_MOBILE -#endif // GTEST_HAS_STREAM_REDIRECTION - -// Determines whether to support death tests. -// pops up a dialog window that cannot be suppressed programmatically. -#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ - (GTEST_OS_MAC && !GTEST_OS_IOS) || \ - (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER) || GTEST_OS_WINDOWS_MINGW || \ - GTEST_OS_AIX || GTEST_OS_HPUX || GTEST_OS_OPENBSD || GTEST_OS_QNX || \ - GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \ - GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_HAIKU) -# define GTEST_HAS_DEATH_TEST 1 -#endif - -// Determines whether to support type-driven tests. - -// Typed tests need and variadic macros, which GCC, VC++ 8.0, -// Sun Pro CC, IBM Visual Age, and HP aCC support. -#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) || \ - defined(__IBMCPP__) || defined(__HP_aCC) -# define GTEST_HAS_TYPED_TEST 1 -# define GTEST_HAS_TYPED_TEST_P 1 -#endif - -// Determines whether the system compiler uses UTF-16 for encoding wide strings. -#define GTEST_WIDE_STRING_USES_UTF16_ \ - (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_AIX || GTEST_OS_OS2) - -// Determines whether test results can be streamed to a socket. -#if GTEST_OS_LINUX || GTEST_OS_GNU_KFREEBSD || GTEST_OS_DRAGONFLY || \ - GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_OPENBSD -# define GTEST_CAN_STREAM_RESULTS_ 1 -#endif - -// Defines some utility macros. - -// The GNU compiler emits a warning if nested "if" statements are followed by -// an "else" statement and braces are not used to explicitly disambiguate the -// "else" binding. This leads to problems with code like: -// -// if (gate) -// ASSERT_*(condition) << "Some message"; -// -// The "switch (0) case 0:" idiom is used to suppress this. -#ifdef __INTEL_COMPILER -# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ -#else -# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT -#endif - -// Use this annotation at the end of a struct/class definition to -// prevent the compiler from optimizing away instances that are never -// used. This is useful when all interesting logic happens inside the -// c'tor and / or d'tor. Example: -// -// struct Foo { -// Foo() { ... } -// } GTEST_ATTRIBUTE_UNUSED_; -// -// Also use it after a variable or parameter declaration to tell the -// compiler the variable/parameter does not have to be used. -#if defined(__GNUC__) && !defined(COMPILER_ICC) -# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) -#elif defined(__clang__) -# if __has_attribute(unused) -# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) -# endif -#endif -#ifndef GTEST_ATTRIBUTE_UNUSED_ -# define GTEST_ATTRIBUTE_UNUSED_ -#endif - -// Use this annotation before a function that takes a printf format string. -#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC) -# if defined(__MINGW_PRINTF_FORMAT) -// MinGW has two different printf implementations. Ensure the format macro -// matches the selected implementation. See -// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/. -# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \ - __attribute__((__format__(__MINGW_PRINTF_FORMAT, string_index, \ - first_to_check))) -# else -# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \ - __attribute__((__format__(__printf__, string_index, first_to_check))) -# endif -#else -# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) -#endif - - -// A macro to disallow operator= -// This should be used in the private: declarations for a class. -#define GTEST_DISALLOW_ASSIGN_(type) \ - void operator=(type const &) = delete - -// A macro to disallow copy constructor and operator= -// This should be used in the private: declarations for a class. -#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \ - type(type const &) = delete; \ - GTEST_DISALLOW_ASSIGN_(type) - -// Tell the compiler to warn about unused return values for functions declared -// with this macro. The macro should be used on function declarations -// following the argument list: -// -// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; -#if defined(__GNUC__) && !defined(COMPILER_ICC) -# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) -#else -# define GTEST_MUST_USE_RESULT_ -#endif // __GNUC__ && !COMPILER_ICC - -// MS C++ compiler emits warning when a conditional expression is compile time -// constant. In some contexts this warning is false positive and needs to be -// suppressed. Use the following two macros in such cases: -// -// GTEST_INTENTIONAL_CONST_COND_PUSH_() -// while (true) { -// GTEST_INTENTIONAL_CONST_COND_POP_() -// } -# define GTEST_INTENTIONAL_CONST_COND_PUSH_() \ - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127) -# define GTEST_INTENTIONAL_CONST_COND_POP_() \ - GTEST_DISABLE_MSC_WARNINGS_POP_() - -// Determine whether the compiler supports Microsoft's Structured Exception -// Handling. This is supported by several Windows compilers but generally -// does not exist on any other system. -#ifndef GTEST_HAS_SEH -// The user didn't tell us, so we need to figure it out. - -# if defined(_MSC_VER) || defined(__BORLANDC__) -// These two compilers are known to support SEH. -# define GTEST_HAS_SEH 1 -# else -// Assume no SEH. -# define GTEST_HAS_SEH 0 -# endif - -#endif // GTEST_HAS_SEH - -#ifndef GTEST_IS_THREADSAFE - -#define GTEST_IS_THREADSAFE \ - (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ || \ - (GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT) || \ - GTEST_HAS_PTHREAD) - -#endif // GTEST_IS_THREADSAFE - -// GTEST_API_ qualifies all symbols that must be exported. The definitions below -// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in -// gtest/internal/custom/gtest-port.h -#ifndef GTEST_API_ - -#ifdef _MSC_VER -# if GTEST_LINKED_AS_SHARED_LIBRARY -# define GTEST_API_ __declspec(dllimport) -# elif GTEST_CREATE_SHARED_LIBRARY -# define GTEST_API_ __declspec(dllexport) -# endif -#elif __GNUC__ >= 4 || defined(__clang__) -# define GTEST_API_ __attribute__((visibility ("default"))) -#endif // _MSC_VER - -#endif // GTEST_API_ - -#ifndef GTEST_API_ -# define GTEST_API_ -#endif // GTEST_API_ - -#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE -# define GTEST_DEFAULT_DEATH_TEST_STYLE "fast" -#endif // GTEST_DEFAULT_DEATH_TEST_STYLE - -#ifdef __GNUC__ -// Ask the compiler to never inline a given function. -# define GTEST_NO_INLINE_ __attribute__((noinline)) -#else -# define GTEST_NO_INLINE_ -#endif - -// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. -#if !defined(GTEST_HAS_CXXABI_H_) -# if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) -# define GTEST_HAS_CXXABI_H_ 1 -# else -# define GTEST_HAS_CXXABI_H_ 0 -# endif -#endif - -// A function level attribute to disable checking for use of uninitialized -// memory when built with MemorySanitizer. -#if defined(__clang__) -# if __has_feature(memory_sanitizer) -# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ \ - __attribute__((no_sanitize_memory)) -# else -# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ -# endif // __has_feature(memory_sanitizer) -#else -# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ -#endif // __clang__ - -// A function level attribute to disable AddressSanitizer instrumentation. -#if defined(__clang__) -# if __has_feature(address_sanitizer) -# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \ - __attribute__((no_sanitize_address)) -# else -# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -# endif // __has_feature(address_sanitizer) -#else -# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -#endif // __clang__ - -// A function level attribute to disable HWAddressSanitizer instrumentation. -#if defined(__clang__) -# if __has_feature(hwaddress_sanitizer) -# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ \ - __attribute__((no_sanitize("hwaddress"))) -# else -# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -# endif // __has_feature(hwaddress_sanitizer) -#else -# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -#endif // __clang__ - -// A function level attribute to disable ThreadSanitizer instrumentation. -#if defined(__clang__) -# if __has_feature(thread_sanitizer) -# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ \ - __attribute__((no_sanitize_thread)) -# else -# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ -# endif // __has_feature(thread_sanitizer) -#else -# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ -#endif // __clang__ - -namespace testing { - -class Message; - -// Legacy imports for backwards compatibility. -// New code should use std:: names directly. -using std::get; -using std::make_tuple; -using std::tuple; -using std::tuple_element; -using std::tuple_size; - -namespace internal { - -// A secret type that Google Test users don't know about. It has no -// definition on purpose. Therefore it's impossible to create a -// Secret object, which is what we want. -class Secret; - -// The GTEST_COMPILE_ASSERT_ is a legacy macro used to verify that a compile -// time expression is true (in new code, use static_assert instead). For -// example, you could use it to verify the size of a static array: -// -// GTEST_COMPILE_ASSERT_(GTEST_ARRAY_SIZE_(names) == NUM_NAMES, -// names_incorrect_size); -// -// The second argument to the macro must be a valid C++ identifier. If the -// expression is false, compiler will issue an error containing this identifier. -#define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg) - -// Evaluates to the number of elements in 'array'. -#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0])) - -// A helper for suppressing warnings on constant condition. It just -// returns 'condition'. -GTEST_API_ bool IsTrue(bool condition); - -// Defines RE. - -#if GTEST_USES_PCRE -// if used, PCRE is injected by custom/gtest-port.h -#elif GTEST_USES_POSIX_RE || GTEST_USES_SIMPLE_RE - -// A simple C++ wrapper for . It uses the POSIX Extended -// Regular Expression syntax. -class GTEST_API_ RE { - public: - // A copy constructor is required by the Standard to initialize object - // references from r-values. - RE(const RE& other) { Init(other.pattern()); } - - // Constructs an RE from a string. - RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT - - RE(const char* regex) { Init(regex); } // NOLINT - ~RE(); - - // Returns the string representation of the regex. - const char* pattern() const { return pattern_; } - - // FullMatch(str, re) returns true if and only if regular expression re - // matches the entire str. - // PartialMatch(str, re) returns true if and only if regular expression re - // matches a substring of str (including str itself). - static bool FullMatch(const ::std::string& str, const RE& re) { - return FullMatch(str.c_str(), re); - } - static bool PartialMatch(const ::std::string& str, const RE& re) { - return PartialMatch(str.c_str(), re); - } - - static bool FullMatch(const char* str, const RE& re); - static bool PartialMatch(const char* str, const RE& re); - - private: - void Init(const char* regex); - const char* pattern_; - bool is_valid_; - -# if GTEST_USES_POSIX_RE - - regex_t full_regex_; // For FullMatch(). - regex_t partial_regex_; // For PartialMatch(). - -# else // GTEST_USES_SIMPLE_RE - - const char* full_pattern_; // For FullMatch(); - -# endif - - GTEST_DISALLOW_ASSIGN_(RE); -}; - -#endif // GTEST_USES_PCRE - -// Formats a source file path and a line number as they would appear -// in an error message from the compiler used to compile this code. -GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); - -// Formats a file location for compiler-independent XML output. -// Although this function is not platform dependent, we put it next to -// FormatFileLocation in order to contrast the two functions. -GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, - int line); - -// Defines logging utilities: -// GTEST_LOG_(severity) - logs messages at the specified severity level. The -// message itself is streamed into the macro. -// LogToStderr() - directs all log messages to stderr. -// FlushInfoLog() - flushes informational log messages. - -enum GTestLogSeverity { - GTEST_INFO, - GTEST_WARNING, - GTEST_ERROR, - GTEST_FATAL -}; - -// Formats log entry severity, provides a stream object for streaming the -// log message, and terminates the message with a newline when going out of -// scope. -class GTEST_API_ GTestLog { - public: - GTestLog(GTestLogSeverity severity, const char* file, int line); - - // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. - ~GTestLog(); - - ::std::ostream& GetStream() { return ::std::cerr; } - - private: - const GTestLogSeverity severity_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); -}; - -#if !defined(GTEST_LOG_) - -# define GTEST_LOG_(severity) \ - ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ - __FILE__, __LINE__).GetStream() - -inline void LogToStderr() {} -inline void FlushInfoLog() { fflush(nullptr); } - -#endif // !defined(GTEST_LOG_) - -#if !defined(GTEST_CHECK_) -// INTERNAL IMPLEMENTATION - DO NOT USE. -// -// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition -// is not satisfied. -// Synopsys: -// GTEST_CHECK_(boolean_condition); -// or -// GTEST_CHECK_(boolean_condition) << "Additional message"; -// -// This checks the condition and if the condition is not satisfied -// it prints message about the condition violation, including the -// condition itself, plus additional message streamed into it, if any, -// and then it aborts the program. It aborts the program irrespective of -// whether it is built in the debug mode or not. -# define GTEST_CHECK_(condition) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::IsTrue(condition)) \ - ; \ - else \ - GTEST_LOG_(FATAL) << "Condition " #condition " failed. " -#endif // !defined(GTEST_CHECK_) - -// An all-mode assert to verify that the given POSIX-style function -// call returns 0 (indicating success). Known limitation: this -// doesn't expand to a balanced 'if' statement, so enclose the macro -// in {} if you need to use it as the only statement in an 'if' -// branch. -#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ - if (const int gtest_error = (posix_call)) \ - GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ - << gtest_error - -// Transforms "T" into "const T&" according to standard reference collapsing -// rules (this is only needed as a backport for C++98 compilers that do not -// support reference collapsing). Specifically, it transforms: -// -// char ==> const char& -// const char ==> const char& -// char& ==> char& -// const char& ==> const char& -// -// Note that the non-const reference will not have "const" added. This is -// standard, and necessary so that "T" can always bind to "const T&". -template -struct ConstRef { typedef const T& type; }; -template -struct ConstRef { typedef T& type; }; - -// The argument T must depend on some template parameters. -#define GTEST_REFERENCE_TO_CONST_(T) \ - typename ::testing::internal::ConstRef::type - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Use ImplicitCast_ as a safe version of static_cast for upcasting in -// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a -// const Foo*). When you use ImplicitCast_, the compiler checks that -// the cast is safe. Such explicit ImplicitCast_s are necessary in -// surprisingly many situations where C++ demands an exact type match -// instead of an argument type convertable to a target type. -// -// The syntax for using ImplicitCast_ is the same as for static_cast: -// -// ImplicitCast_(expr) -// -// ImplicitCast_ would have been part of the C++ standard library, -// but the proposal was submitted too late. It will probably make -// its way into the language in the future. -// -// This relatively ugly name is intentional. It prevents clashes with -// similar functions users may have (e.g., implicit_cast). The internal -// namespace alone is not enough because the function can be found by ADL. -template -inline To ImplicitCast_(To x) { return x; } - -// When you upcast (that is, cast a pointer from type Foo to type -// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts -// always succeed. When you downcast (that is, cast a pointer from -// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because -// how do you know the pointer is really of type SubclassOfFoo? It -// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, -// when you downcast, you should use this macro. In debug mode, we -// use dynamic_cast<> to double-check the downcast is legal (we die -// if it's not). In normal mode, we do the efficient static_cast<> -// instead. Thus, it's important to test in debug mode to make sure -// the cast is legal! -// This is the only place in the code we should use dynamic_cast<>. -// In particular, you SHOULDN'T be using dynamic_cast<> in order to -// do RTTI (eg code like this: -// if (dynamic_cast(foo)) HandleASubclass1Object(foo); -// if (dynamic_cast(foo)) HandleASubclass2Object(foo); -// You should design the code some other way not to need this. -// -// This relatively ugly name is intentional. It prevents clashes with -// similar functions users may have (e.g., down_cast). The internal -// namespace alone is not enough because the function can be found by ADL. -template // use like this: DownCast_(foo); -inline To DownCast_(From* f) { // so we only accept pointers - // Ensures that To is a sub-type of From *. This test is here only - // for compile-time type checking, and has no overhead in an - // optimized build at run-time, as it will be optimized away - // completely. - GTEST_INTENTIONAL_CONST_COND_PUSH_() - if (false) { - GTEST_INTENTIONAL_CONST_COND_POP_() - const To to = nullptr; - ::testing::internal::ImplicitCast_(to); - } - -#if GTEST_HAS_RTTI - // RTTI: debug mode only! - GTEST_CHECK_(f == nullptr || dynamic_cast(f) != nullptr); -#endif - return static_cast(f); -} - -// Downcasts the pointer of type Base to Derived. -// Derived must be a subclass of Base. The parameter MUST -// point to a class of type Derived, not any subclass of it. -// When RTTI is available, the function performs a runtime -// check to enforce this. -template -Derived* CheckedDowncastToActualType(Base* base) { -#if GTEST_HAS_RTTI - GTEST_CHECK_(typeid(*base) == typeid(Derived)); -#endif - -#if GTEST_HAS_DOWNCAST_ - return ::down_cast(base); -#elif GTEST_HAS_RTTI - return dynamic_cast(base); // NOLINT -#else - return static_cast(base); // Poor man's downcast. -#endif -} - -#if GTEST_HAS_STREAM_REDIRECTION - -// Defines the stderr capturer: -// CaptureStdout - starts capturing stdout. -// GetCapturedStdout - stops capturing stdout and returns the captured string. -// CaptureStderr - starts capturing stderr. -// GetCapturedStderr - stops capturing stderr and returns the captured string. -// -GTEST_API_ void CaptureStdout(); -GTEST_API_ std::string GetCapturedStdout(); -GTEST_API_ void CaptureStderr(); -GTEST_API_ std::string GetCapturedStderr(); - -#endif // GTEST_HAS_STREAM_REDIRECTION -// Returns the size (in bytes) of a file. -GTEST_API_ size_t GetFileSize(FILE* file); - -// Reads the entire content of a file as a string. -GTEST_API_ std::string ReadEntireFile(FILE* file); - -// All command line arguments. -GTEST_API_ std::vector GetArgvs(); - -#if GTEST_HAS_DEATH_TEST - -std::vector GetInjectableArgvs(); -// Deprecated: pass the args vector by value instead. -void SetInjectableArgvs(const std::vector* new_argvs); -void SetInjectableArgvs(const std::vector& new_argvs); -void ClearInjectableArgvs(); - -#endif // GTEST_HAS_DEATH_TEST - -// Defines synchronization primitives. -#if GTEST_IS_THREADSAFE -# if GTEST_HAS_PTHREAD -// Sleeps for (roughly) n milliseconds. This function is only for testing -// Google Test's own constructs. Don't use it in user tests, either -// directly or indirectly. -inline void SleepMilliseconds(int n) { - const timespec time = { - 0, // 0 seconds. - n * 1000L * 1000L, // And n ms. - }; - nanosleep(&time, nullptr); -} -# endif // GTEST_HAS_PTHREAD - -# if GTEST_HAS_NOTIFICATION_ -// Notification has already been imported into the namespace. -// Nothing to do here. - -# elif GTEST_HAS_PTHREAD -// Allows a controller thread to pause execution of newly created -// threads until notified. Instances of this class must be created -// and destroyed in the controller thread. -// -// This class is only for testing Google Test's own constructs. Do not -// use it in user tests, either directly or indirectly. -class Notification { - public: - Notification() : notified_(false) { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr)); - } - ~Notification() { - pthread_mutex_destroy(&mutex_); - } - - // Notifies all threads created with this notification to start. Must - // be called from the controller thread. - void Notify() { - pthread_mutex_lock(&mutex_); - notified_ = true; - pthread_mutex_unlock(&mutex_); - } - - // Blocks until the controller thread notifies. Must be called from a test - // thread. - void WaitForNotification() { - for (;;) { - pthread_mutex_lock(&mutex_); - const bool notified = notified_; - pthread_mutex_unlock(&mutex_); - if (notified) - break; - SleepMilliseconds(10); - } - } - - private: - pthread_mutex_t mutex_; - bool notified_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); -}; - -# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT - -GTEST_API_ void SleepMilliseconds(int n); - -// Provides leak-safe Windows kernel handle ownership. -// Used in death tests and in threading support. -class GTEST_API_ AutoHandle { - public: - // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to - // avoid including in this header file. Including is - // undesirable because it defines a lot of symbols and macros that tend to - // conflict with client code. This assumption is verified by - // WindowsTypesTest.HANDLEIsVoidStar. - typedef void* Handle; - AutoHandle(); - explicit AutoHandle(Handle handle); - - ~AutoHandle(); - - Handle Get() const; - void Reset(); - void Reset(Handle handle); - - private: - // Returns true if and only if the handle is a valid handle object that can be - // closed. - bool IsCloseable() const; - - Handle handle_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); -}; - -// Allows a controller thread to pause execution of newly created -// threads until notified. Instances of this class must be created -// and destroyed in the controller thread. -// -// This class is only for testing Google Test's own constructs. Do not -// use it in user tests, either directly or indirectly. -class GTEST_API_ Notification { - public: - Notification(); - void Notify(); - void WaitForNotification(); - - private: - AutoHandle event_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); -}; -# endif // GTEST_HAS_NOTIFICATION_ - -// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD -// defined, but we don't want to use MinGW's pthreads implementation, which -// has conformance problems with some versions of the POSIX standard. -# if GTEST_HAS_PTHREAD && !GTEST_OS_WINDOWS_MINGW - -// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. -// Consequently, it cannot select a correct instantiation of ThreadWithParam -// in order to call its Run(). Introducing ThreadWithParamBase as a -// non-templated base class for ThreadWithParam allows us to bypass this -// problem. -class ThreadWithParamBase { - public: - virtual ~ThreadWithParamBase() {} - virtual void Run() = 0; -}; - -// pthread_create() accepts a pointer to a function type with the C linkage. -// According to the Standard (7.5/1), function types with different linkages -// are different even if they are otherwise identical. Some compilers (for -// example, SunStudio) treat them as different types. Since class methods -// cannot be defined with C-linkage we need to define a free C-function to -// pass into pthread_create(). -extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { - static_cast(thread)->Run(); - return nullptr; -} - -// Helper class for testing Google Test's multi-threading constructs. -// To use it, write: -// -// void ThreadFunc(int param) { /* Do things with param */ } -// Notification thread_can_start; -// ... -// // The thread_can_start parameter is optional; you can supply NULL. -// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); -// thread_can_start.Notify(); -// -// These classes are only for testing Google Test's own constructs. Do -// not use them in user tests, either directly or indirectly. -template -class ThreadWithParam : public ThreadWithParamBase { - public: - typedef void UserThreadFunc(T); - - ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start) - : func_(func), - param_(param), - thread_can_start_(thread_can_start), - finished_(false) { - ThreadWithParamBase* const base = this; - // The thread can be created only after all fields except thread_ - // have been initialized. - GTEST_CHECK_POSIX_SUCCESS_( - pthread_create(&thread_, nullptr, &ThreadFuncWithCLinkage, base)); - } - ~ThreadWithParam() override { Join(); } - - void Join() { - if (!finished_) { - GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, nullptr)); - finished_ = true; - } - } - - void Run() override { - if (thread_can_start_ != nullptr) thread_can_start_->WaitForNotification(); - func_(param_); - } - - private: - UserThreadFunc* const func_; // User-supplied thread function. - const T param_; // User-supplied parameter to the thread function. - // When non-NULL, used to block execution until the controller thread - // notifies. - Notification* const thread_can_start_; - bool finished_; // true if and only if we know that the thread function has - // finished. - pthread_t thread_; // The native thread object. - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); -}; -# endif // !GTEST_OS_WINDOWS && GTEST_HAS_PTHREAD || - // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - -# if GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ -// Mutex and ThreadLocal have already been imported into the namespace. -// Nothing to do here. - -# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT - -// Mutex implements mutex on Windows platforms. It is used in conjunction -// with class MutexLock: -// -// Mutex mutex; -// ... -// MutexLock lock(&mutex); // Acquires the mutex and releases it at the -// // end of the current scope. -// -// A static Mutex *must* be defined or declared using one of the following -// macros: -// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); -// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); -// -// (A non-static Mutex is defined/declared in the usual way). -class GTEST_API_ Mutex { - public: - enum MutexType { kStatic = 0, kDynamic = 1 }; - // We rely on kStaticMutex being 0 as it is to what the linker initializes - // type_ in static mutexes. critical_section_ will be initialized lazily - // in ThreadSafeLazyInit(). - enum StaticConstructorSelector { kStaticMutex = 0 }; - - // This constructor intentionally does nothing. It relies on type_ being - // statically initialized to 0 (effectively setting it to kStatic) and on - // ThreadSafeLazyInit() to lazily initialize the rest of the members. - explicit Mutex(StaticConstructorSelector /*dummy*/) {} - - Mutex(); - ~Mutex(); - - void Lock(); - - void Unlock(); - - // Does nothing if the current thread holds the mutex. Otherwise, crashes - // with high probability. - void AssertHeld(); - - private: - // Initializes owner_thread_id_ and critical_section_ in static mutexes. - void ThreadSafeLazyInit(); - - // Per https://blogs.msdn.microsoft.com/oldnewthing/20040223-00/?p=40503, - // we assume that 0 is an invalid value for thread IDs. - unsigned int owner_thread_id_; - - // For static mutexes, we rely on these members being initialized to zeros - // by the linker. - MutexType type_; - long critical_section_init_phase_; // NOLINT - GTEST_CRITICAL_SECTION* critical_section_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); -}; - -# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ - extern ::testing::internal::Mutex mutex - -# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ - ::testing::internal::Mutex mutex(::testing::internal::Mutex::kStaticMutex) - -// We cannot name this class MutexLock because the ctor declaration would -// conflict with a macro named MutexLock, which is defined on some -// platforms. That macro is used as a defensive measure to prevent against -// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than -// "MutexLock l(&mu)". Hence the typedef trick below. -class GTestMutexLock { - public: - explicit GTestMutexLock(Mutex* mutex) - : mutex_(mutex) { mutex_->Lock(); } - - ~GTestMutexLock() { mutex_->Unlock(); } - - private: - Mutex* const mutex_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); -}; - -typedef GTestMutexLock MutexLock; - -// Base class for ValueHolder. Allows a caller to hold and delete a value -// without knowing its type. -class ThreadLocalValueHolderBase { - public: - virtual ~ThreadLocalValueHolderBase() {} -}; - -// Provides a way for a thread to send notifications to a ThreadLocal -// regardless of its parameter type. -class ThreadLocalBase { - public: - // Creates a new ValueHolder object holding a default value passed to - // this ThreadLocal's constructor and returns it. It is the caller's - // responsibility not to call this when the ThreadLocal instance already - // has a value on the current thread. - virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0; - - protected: - ThreadLocalBase() {} - virtual ~ThreadLocalBase() {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocalBase); -}; - -// Maps a thread to a set of ThreadLocals that have values instantiated on that -// thread and notifies them when the thread exits. A ThreadLocal instance is -// expected to persist until all threads it has values on have terminated. -class GTEST_API_ ThreadLocalRegistry { - public: - // Registers thread_local_instance as having value on the current thread. - // Returns a value that can be used to identify the thread from other threads. - static ThreadLocalValueHolderBase* GetValueOnCurrentThread( - const ThreadLocalBase* thread_local_instance); - - // Invoked when a ThreadLocal instance is destroyed. - static void OnThreadLocalDestroyed( - const ThreadLocalBase* thread_local_instance); -}; - -class GTEST_API_ ThreadWithParamBase { - public: - void Join(); - - protected: - class Runnable { - public: - virtual ~Runnable() {} - virtual void Run() = 0; - }; - - ThreadWithParamBase(Runnable *runnable, Notification* thread_can_start); - virtual ~ThreadWithParamBase(); - - private: - AutoHandle thread_; -}; - -// Helper class for testing Google Test's multi-threading constructs. -template -class ThreadWithParam : public ThreadWithParamBase { - public: - typedef void UserThreadFunc(T); - - ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start) - : ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) { - } - virtual ~ThreadWithParam() {} - - private: - class RunnableImpl : public Runnable { - public: - RunnableImpl(UserThreadFunc* func, T param) - : func_(func), - param_(param) { - } - virtual ~RunnableImpl() {} - virtual void Run() { - func_(param_); - } - - private: - UserThreadFunc* const func_; - const T param_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(RunnableImpl); - }; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); -}; - -// Implements thread-local storage on Windows systems. -// -// // Thread 1 -// ThreadLocal tl(100); // 100 is the default value for each thread. -// -// // Thread 2 -// tl.set(150); // Changes the value for thread 2 only. -// EXPECT_EQ(150, tl.get()); -// -// // Thread 1 -// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. -// tl.set(200); -// EXPECT_EQ(200, tl.get()); -// -// The template type argument T must have a public copy constructor. -// In addition, the default ThreadLocal constructor requires T to have -// a public default constructor. -// -// The users of a TheadLocal instance have to make sure that all but one -// threads (including the main one) using that instance have exited before -// destroying it. Otherwise, the per-thread objects managed for them by the -// ThreadLocal instance are not guaranteed to be destroyed on all platforms. -// -// Google Test only uses global ThreadLocal objects. That means they -// will die after main() has returned. Therefore, no per-thread -// object managed by Google Test will be leaked as long as all threads -// using Google Test have exited when main() returns. -template -class ThreadLocal : public ThreadLocalBase { - public: - ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {} - explicit ThreadLocal(const T& value) - : default_factory_(new InstanceValueHolderFactory(value)) {} - - ~ThreadLocal() { ThreadLocalRegistry::OnThreadLocalDestroyed(this); } - - T* pointer() { return GetOrCreateValue(); } - const T* pointer() const { return GetOrCreateValue(); } - const T& get() const { return *pointer(); } - void set(const T& value) { *pointer() = value; } - - private: - // Holds a value of T. Can be deleted via its base class without the caller - // knowing the type of T. - class ValueHolder : public ThreadLocalValueHolderBase { - public: - ValueHolder() : value_() {} - explicit ValueHolder(const T& value) : value_(value) {} - - T* pointer() { return &value_; } - - private: - T value_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); - }; - - - T* GetOrCreateValue() const { - return static_cast( - ThreadLocalRegistry::GetValueOnCurrentThread(this))->pointer(); - } - - virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const { - return default_factory_->MakeNewHolder(); - } - - class ValueHolderFactory { - public: - ValueHolderFactory() {} - virtual ~ValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const = 0; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory); - }; - - class DefaultValueHolderFactory : public ValueHolderFactory { - public: - DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); - }; - - class InstanceValueHolderFactory : public ValueHolderFactory { - public: - explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { - return new ValueHolder(value_); - } - - private: - const T value_; // The value for each thread. - - GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory); - }; - - std::unique_ptr default_factory_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); -}; - -# elif GTEST_HAS_PTHREAD - -// MutexBase and Mutex implement mutex on pthreads-based platforms. -class MutexBase { - public: - // Acquires this mutex. - void Lock() { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); - owner_ = pthread_self(); - has_owner_ = true; - } - - // Releases this mutex. - void Unlock() { - // Since the lock is being released the owner_ field should no longer be - // considered valid. We don't protect writing to has_owner_ here, as it's - // the caller's responsibility to ensure that the current thread holds the - // mutex when this is called. - has_owner_ = false; - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); - } - - // Does nothing if the current thread holds the mutex. Otherwise, crashes - // with high probability. - void AssertHeld() const { - GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) - << "The current thread is not holding the mutex @" << this; - } - - // A static mutex may be used before main() is entered. It may even - // be used before the dynamic initialization stage. Therefore we - // must be able to initialize a static mutex object at link time. - // This means MutexBase has to be a POD and its member variables - // have to be public. - public: - pthread_mutex_t mutex_; // The underlying pthread mutex. - // has_owner_ indicates whether the owner_ field below contains a valid thread - // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All - // accesses to the owner_ field should be protected by a check of this field. - // An alternative might be to memset() owner_ to all zeros, but there's no - // guarantee that a zero'd pthread_t is necessarily invalid or even different - // from pthread_self(). - bool has_owner_; - pthread_t owner_; // The thread holding the mutex. -}; - -// Forward-declares a static mutex. -# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ - extern ::testing::internal::MutexBase mutex - -// Defines and statically (i.e. at link time) initializes a static mutex. -// The initialization list here does not explicitly initialize each field, -// instead relying on default initialization for the unspecified fields. In -// particular, the owner_ field (a pthread_t) is not explicitly initialized. -// This allows initialization to work whether pthread_t is a scalar or struct. -// The flag -Wmissing-field-initializers must not be specified for this to work. -#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ - ::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, 0} - -// The Mutex class can only be used for mutexes created at runtime. It -// shares its API with MutexBase otherwise. -class Mutex : public MutexBase { - public: - Mutex() { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr)); - has_owner_ = false; - } - ~Mutex() { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); - } - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); -}; - -// We cannot name this class MutexLock because the ctor declaration would -// conflict with a macro named MutexLock, which is defined on some -// platforms. That macro is used as a defensive measure to prevent against -// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than -// "MutexLock l(&mu)". Hence the typedef trick below. -class GTestMutexLock { - public: - explicit GTestMutexLock(MutexBase* mutex) - : mutex_(mutex) { mutex_->Lock(); } - - ~GTestMutexLock() { mutex_->Unlock(); } - - private: - MutexBase* const mutex_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); -}; - -typedef GTestMutexLock MutexLock; - -// Helpers for ThreadLocal. - -// pthread_key_create() requires DeleteThreadLocalValue() to have -// C-linkage. Therefore it cannot be templatized to access -// ThreadLocal. Hence the need for class -// ThreadLocalValueHolderBase. -class ThreadLocalValueHolderBase { - public: - virtual ~ThreadLocalValueHolderBase() {} -}; - -// Called by pthread to delete thread-local data stored by -// pthread_setspecific(). -extern "C" inline void DeleteThreadLocalValue(void* value_holder) { - delete static_cast(value_holder); -} - -// Implements thread-local storage on pthreads-based systems. -template -class GTEST_API_ ThreadLocal { - public: - ThreadLocal() - : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {} - explicit ThreadLocal(const T& value) - : key_(CreateKey()), - default_factory_(new InstanceValueHolderFactory(value)) {} - - ~ThreadLocal() { - // Destroys the managed object for the current thread, if any. - DeleteThreadLocalValue(pthread_getspecific(key_)); - - // Releases resources associated with the key. This will *not* - // delete managed objects for other threads. - GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); - } - - T* pointer() { return GetOrCreateValue(); } - const T* pointer() const { return GetOrCreateValue(); } - const T& get() const { return *pointer(); } - void set(const T& value) { *pointer() = value; } - - private: - // Holds a value of type T. - class ValueHolder : public ThreadLocalValueHolderBase { - public: - ValueHolder() : value_() {} - explicit ValueHolder(const T& value) : value_(value) {} - - T* pointer() { return &value_; } - - private: - T value_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); - }; - - static pthread_key_t CreateKey() { - pthread_key_t key; - // When a thread exits, DeleteThreadLocalValue() will be called on - // the object managed for that thread. - GTEST_CHECK_POSIX_SUCCESS_( - pthread_key_create(&key, &DeleteThreadLocalValue)); - return key; - } - - T* GetOrCreateValue() const { - ThreadLocalValueHolderBase* const holder = - static_cast(pthread_getspecific(key_)); - if (holder != nullptr) { - return CheckedDowncastToActualType(holder)->pointer(); - } - - ValueHolder* const new_holder = default_factory_->MakeNewHolder(); - ThreadLocalValueHolderBase* const holder_base = new_holder; - GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); - return new_holder->pointer(); - } - - class ValueHolderFactory { - public: - ValueHolderFactory() {} - virtual ~ValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const = 0; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory); - }; - - class DefaultValueHolderFactory : public ValueHolderFactory { - public: - DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); - }; - - class InstanceValueHolderFactory : public ValueHolderFactory { - public: - explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { - return new ValueHolder(value_); - } - - private: - const T value_; // The value for each thread. - - GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory); - }; - - // A key pthreads uses for looking up per-thread values. - const pthread_key_t key_; - std::unique_ptr default_factory_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); -}; - -# endif // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - -#else // GTEST_IS_THREADSAFE - -// A dummy implementation of synchronization primitives (mutex, lock, -// and thread-local variable). Necessary for compiling Google Test where -// mutex is not supported - using Google Test in multiple threads is not -// supported on such platforms. - -class Mutex { - public: - Mutex() {} - void Lock() {} - void Unlock() {} - void AssertHeld() const {} -}; - -# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ - extern ::testing::internal::Mutex mutex - -# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex - -// We cannot name this class MutexLock because the ctor declaration would -// conflict with a macro named MutexLock, which is defined on some -// platforms. That macro is used as a defensive measure to prevent against -// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than -// "MutexLock l(&mu)". Hence the typedef trick below. -class GTestMutexLock { - public: - explicit GTestMutexLock(Mutex*) {} // NOLINT -}; - -typedef GTestMutexLock MutexLock; - -template -class GTEST_API_ ThreadLocal { - public: - ThreadLocal() : value_() {} - explicit ThreadLocal(const T& value) : value_(value) {} - T* pointer() { return &value_; } - const T* pointer() const { return &value_; } - const T& get() const { return value_; } - void set(const T& value) { value_ = value; } - private: - T value_; -}; - -#endif // GTEST_IS_THREADSAFE - -// Returns the number of threads running in the process, or 0 to indicate that -// we cannot detect it. -GTEST_API_ size_t GetThreadCount(); - -template -using bool_constant = std::integral_constant; - -#if GTEST_OS_WINDOWS -# define GTEST_PATH_SEP_ "\\" -# define GTEST_HAS_ALT_PATH_SEP_ 1 -// The biggest signed integer type the compiler supports. -typedef __int64 BiggestInt; -#else -# define GTEST_PATH_SEP_ "/" -# define GTEST_HAS_ALT_PATH_SEP_ 0 -typedef long long BiggestInt; // NOLINT -#endif // GTEST_OS_WINDOWS - -// Utilities for char. - -// isspace(int ch) and friends accept an unsigned char or EOF. char -// may be signed, depending on the compiler (or compiler flags). -// Therefore we need to cast a char to unsigned char before calling -// isspace(), etc. - -inline bool IsAlpha(char ch) { - return isalpha(static_cast(ch)) != 0; -} -inline bool IsAlNum(char ch) { - return isalnum(static_cast(ch)) != 0; -} -inline bool IsDigit(char ch) { - return isdigit(static_cast(ch)) != 0; -} -inline bool IsLower(char ch) { - return islower(static_cast(ch)) != 0; -} -inline bool IsSpace(char ch) { - return isspace(static_cast(ch)) != 0; -} -inline bool IsUpper(char ch) { - return isupper(static_cast(ch)) != 0; -} -inline bool IsXDigit(char ch) { - return isxdigit(static_cast(ch)) != 0; -} -inline bool IsXDigit(wchar_t ch) { - const unsigned char low_byte = static_cast(ch); - return ch == low_byte && isxdigit(low_byte) != 0; -} - -inline char ToLower(char ch) { - return static_cast(tolower(static_cast(ch))); -} -inline char ToUpper(char ch) { - return static_cast(toupper(static_cast(ch))); -} - -inline std::string StripTrailingSpaces(std::string str) { - std::string::iterator it = str.end(); - while (it != str.begin() && IsSpace(*--it)) - it = str.erase(it); - return str; -} - -// The testing::internal::posix namespace holds wrappers for common -// POSIX functions. These wrappers hide the differences between -// Windows/MSVC and POSIX systems. Since some compilers define these -// standard functions as macros, the wrapper cannot have the same name -// as the wrapped function. - -namespace posix { - -// Functions with a different name on Windows. - -#if GTEST_OS_WINDOWS - -typedef struct _stat StatStruct; - -# ifdef __BORLANDC__ -inline int IsATTY(int fd) { return isatty(fd); } -inline int StrCaseCmp(const char* s1, const char* s2) { - return stricmp(s1, s2); -} -inline char* StrDup(const char* src) { return strdup(src); } -# else // !__BORLANDC__ -# if GTEST_OS_WINDOWS_MOBILE -inline int IsATTY(int /* fd */) { return 0; } -# else -inline int IsATTY(int fd) { return _isatty(fd); } -# endif // GTEST_OS_WINDOWS_MOBILE -inline int StrCaseCmp(const char* s1, const char* s2) { - return _stricmp(s1, s2); -} -inline char* StrDup(const char* src) { return _strdup(src); } -# endif // __BORLANDC__ - -# if GTEST_OS_WINDOWS_MOBILE -inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } -// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this -// time and thus not defined there. -# else -inline int FileNo(FILE* file) { return _fileno(file); } -inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } -inline int RmDir(const char* dir) { return _rmdir(dir); } -inline bool IsDir(const StatStruct& st) { - return (_S_IFDIR & st.st_mode) != 0; -} -# endif // GTEST_OS_WINDOWS_MOBILE - -#else - -typedef struct stat StatStruct; - -inline int FileNo(FILE* file) { return fileno(file); } -inline int IsATTY(int fd) { return isatty(fd); } -inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } -inline int StrCaseCmp(const char* s1, const char* s2) { - return strcasecmp(s1, s2); -} -inline char* StrDup(const char* src) { return strdup(src); } -inline int RmDir(const char* dir) { return rmdir(dir); } -inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } - -#endif // GTEST_OS_WINDOWS - -// Functions deprecated by MSVC 8.0. - -GTEST_DISABLE_MSC_DEPRECATED_PUSH_() - -inline const char* StrNCpy(char* dest, const char* src, size_t n) { - return strncpy(dest, src, n); -} - -// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and -// StrError() aren't needed on Windows CE at this time and thus not -// defined there. - -#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT -inline int ChDir(const char* dir) { return chdir(dir); } -#endif -inline FILE* FOpen(const char* path, const char* mode) { - return fopen(path, mode); -} -#if !GTEST_OS_WINDOWS_MOBILE -inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { - return freopen(path, mode, stream); -} -inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } -#endif -inline int FClose(FILE* fp) { return fclose(fp); } -#if !GTEST_OS_WINDOWS_MOBILE -inline int Read(int fd, void* buf, unsigned int count) { - return static_cast(read(fd, buf, count)); -} -inline int Write(int fd, const void* buf, unsigned int count) { - return static_cast(write(fd, buf, count)); -} -inline int Close(int fd) { return close(fd); } -inline const char* StrError(int errnum) { return strerror(errnum); } -#endif -inline const char* GetEnv(const char* name) { -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT - // We are on Windows CE, which has no environment variables. - static_cast(name); // To prevent 'unused argument' warning. - return nullptr; -#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) - // Environment variables which we programmatically clear will be set to the - // empty string rather than unset (NULL). Handle that case. - const char* const env = getenv(name); - return (env != nullptr && env[0] != '\0') ? env : nullptr; -#else - return getenv(name); -#endif -} - -GTEST_DISABLE_MSC_DEPRECATED_POP_() - -#if GTEST_OS_WINDOWS_MOBILE -// Windows CE has no C library. The abort() function is used in -// several places in Google Test. This implementation provides a reasonable -// imitation of standard behaviour. -[[noreturn]] void Abort(); -#else -[[noreturn]] inline void Abort() { abort(); } -#endif // GTEST_OS_WINDOWS_MOBILE - -} // namespace posix - -// MSVC "deprecates" snprintf and issues warnings wherever it is used. In -// order to avoid these warnings, we need to use _snprintf or _snprintf_s on -// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate -// function in order to achieve that. We use macro definition here because -// snprintf is a variadic function. -#if _MSC_VER && !GTEST_OS_WINDOWS_MOBILE -// MSVC 2005 and above support variadic macros. -# define GTEST_SNPRINTF_(buffer, size, format, ...) \ - _snprintf_s(buffer, size, size, format, __VA_ARGS__) -#elif defined(_MSC_VER) -// Windows CE does not define _snprintf_s -# define GTEST_SNPRINTF_ _snprintf -#else -# define GTEST_SNPRINTF_ snprintf -#endif - -// The maximum number a BiggestInt can represent. This definition -// works no matter BiggestInt is represented in one's complement or -// two's complement. -// -// We cannot rely on numeric_limits in STL, as __int64 and long long -// are not part of standard C++ and numeric_limits doesn't need to be -// defined for them. -const BiggestInt kMaxBiggestInt = - ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); - -// This template class serves as a compile-time function from size to -// type. It maps a size in bytes to a primitive type with that -// size. e.g. -// -// TypeWithSize<4>::UInt -// -// is typedef-ed to be unsigned int (unsigned integer made up of 4 -// bytes). -// -// Such functionality should belong to STL, but I cannot find it -// there. -// -// Google Test uses this class in the implementation of floating-point -// comparison. -// -// For now it only handles UInt (unsigned int) as that's all Google Test -// needs. Other types can be easily added in the future if need -// arises. -template -class TypeWithSize { - public: - // This prevents the user from using TypeWithSize with incorrect - // values of N. - typedef void UInt; -}; - -// The specialization for size 4. -template <> -class TypeWithSize<4> { - public: - // unsigned int has size 4 in both gcc and MSVC. - // - // As base/basictypes.h doesn't compile on Windows, we cannot use - // uint32, uint64, and etc here. - typedef int Int; - typedef unsigned int UInt; -}; - -// The specialization for size 8. -template <> -class TypeWithSize<8> { - public: -#if GTEST_OS_WINDOWS - typedef __int64 Int; - typedef unsigned __int64 UInt; -#else - typedef long long Int; // NOLINT - typedef unsigned long long UInt; // NOLINT -#endif // GTEST_OS_WINDOWS -}; - -// Integer types of known sizes. -typedef TypeWithSize<4>::Int Int32; -typedef TypeWithSize<4>::UInt UInt32; -typedef TypeWithSize<8>::Int Int64; -typedef TypeWithSize<8>::UInt UInt64; -typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. - -// Utilities for command line flags and environment variables. - -// Macro for referencing flags. -#if !defined(GTEST_FLAG) -# define GTEST_FLAG(name) FLAGS_gtest_##name -#endif // !defined(GTEST_FLAG) - -#if !defined(GTEST_USE_OWN_FLAGFILE_FLAG_) -# define GTEST_USE_OWN_FLAGFILE_FLAG_ 1 -#endif // !defined(GTEST_USE_OWN_FLAGFILE_FLAG_) - -#if !defined(GTEST_DECLARE_bool_) -# define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver - -// Macros for declaring flags. -# define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) -# define GTEST_DECLARE_int32_(name) \ - GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) -# define GTEST_DECLARE_string_(name) \ - GTEST_API_ extern ::std::string GTEST_FLAG(name) - -// Macros for defining flags. -# define GTEST_DEFINE_bool_(name, default_val, doc) \ - GTEST_API_ bool GTEST_FLAG(name) = (default_val) -# define GTEST_DEFINE_int32_(name, default_val, doc) \ - GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) -# define GTEST_DEFINE_string_(name, default_val, doc) \ - GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) - -#endif // !defined(GTEST_DECLARE_bool_) - -// Thread annotations -#if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_) -# define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) -# define GTEST_LOCK_EXCLUDED_(locks) -#endif // !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_) - -// Parses 'str' for a 32-bit signed integer. If successful, writes the result -// to *value and returns true; otherwise leaves *value unchanged and returns -// false. -bool ParseInt32(const Message& src_text, const char* str, Int32* value); - -// Parses a bool/Int32/string from the environment variable -// corresponding to the given Google Test flag. -bool BoolFromGTestEnv(const char* flag, bool default_val); -GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); -std::string OutputFlagAlsoCheckEnvVar(); -const char* StringFromGTestEnv(const char* flag, const char* default_val); - -} // namespace internal -} // namespace testing - -#if !defined(GTEST_INTERNAL_DEPRECATED) - -// Internal Macro to mark an API deprecated, for googletest usage only -// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or -// GTEST_INTERNAL_DEPRECATED(message) myFunction(); Every usage of -// a deprecated entity will trigger a warning when compiled with -// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler). -// For msvc /W3 option will need to be used -// Note that for 'other' compilers this macro evaluates to nothing to prevent -// compilations errors. -#if defined(_MSC_VER) -#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message)) -#elif defined(__GNUC__) -#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message))) -#else -#define GTEST_INTERNAL_DEPRECATED(message) -#endif - -#endif // !defined(GTEST_INTERNAL_DEPRECATED) - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-string.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-string.h deleted file mode 100644 index 82aaa63bf46..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-string.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. -// -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This header file declares the String class and functions used internally by -// Google Test. They are subject to change without notice. They should not used -// by code external to Google Test. -// -// This header file is #included by gtest-internal.h. -// It should not be #included by other files. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ - -#ifdef __BORLANDC__ -// string.h is not guaranteed to provide strcpy on C++ Builder. -# include -#endif - -#include -#include - -#include "gtest/internal/gtest-port.h" - -namespace testing { -namespace internal { - -// String - an abstract class holding static string utilities. -class GTEST_API_ String { - public: - // Static utility methods - - // Clones a 0-terminated C string, allocating memory using new. The - // caller is responsible for deleting the return value using - // delete[]. Returns the cloned string, or NULL if the input is - // NULL. - // - // This is different from strdup() in string.h, which allocates - // memory using malloc(). - static const char* CloneCString(const char* c_str); - -#if GTEST_OS_WINDOWS_MOBILE - // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be - // able to pass strings to Win32 APIs on CE we need to convert them - // to 'Unicode', UTF-16. - - // Creates a UTF-16 wide string from the given ANSI string, allocating - // memory using new. The caller is responsible for deleting the return - // value using delete[]. Returns the wide string, or NULL if the - // input is NULL. - // - // The wide string is created using the ANSI codepage (CP_ACP) to - // match the behaviour of the ANSI versions of Win32 calls and the - // C runtime. - static LPCWSTR AnsiToUtf16(const char* c_str); - - // Creates an ANSI string from the given wide string, allocating - // memory using new. The caller is responsible for deleting the return - // value using delete[]. Returns the ANSI string, or NULL if the - // input is NULL. - // - // The returned string is created using the ANSI codepage (CP_ACP) to - // match the behaviour of the ANSI versions of Win32 calls and the - // C runtime. - static const char* Utf16ToAnsi(LPCWSTR utf16_str); -#endif - - // Compares two C strings. Returns true if and only if they have the same - // content. - // - // Unlike strcmp(), this function can handle NULL argument(s). A - // NULL C string is considered different to any non-NULL C string, - // including the empty string. - static bool CStringEquals(const char* lhs, const char* rhs); - - // Converts a wide C string to a String using the UTF-8 encoding. - // NULL will be converted to "(null)". If an error occurred during - // the conversion, "(failed to convert from wide string)" is - // returned. - static std::string ShowWideCString(const wchar_t* wide_c_str); - - // Compares two wide C strings. Returns true if and only if they have the - // same content. - // - // Unlike wcscmp(), this function can handle NULL argument(s). A - // NULL C string is considered different to any non-NULL C string, - // including the empty string. - static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); - - // Compares two C strings, ignoring case. Returns true if and only if - // they have the same content. - // - // Unlike strcasecmp(), this function can handle NULL argument(s). - // A NULL C string is considered different to any non-NULL C string, - // including the empty string. - static bool CaseInsensitiveCStringEquals(const char* lhs, - const char* rhs); - - // Compares two wide C strings, ignoring case. Returns true if and only if - // they have the same content. - // - // Unlike wcscasecmp(), this function can handle NULL argument(s). - // A NULL C string is considered different to any non-NULL wide C string, - // including the empty string. - // NB: The implementations on different platforms slightly differ. - // On windows, this method uses _wcsicmp which compares according to LC_CTYPE - // environment variable. On GNU platform this method uses wcscasecmp - // which compares according to LC_CTYPE category of the current locale. - // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the - // current locale. - static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, - const wchar_t* rhs); - - // Returns true if and only if the given string ends with the given suffix, - // ignoring case. Any string is considered to end with an empty suffix. - static bool EndsWithCaseInsensitive( - const std::string& str, const std::string& suffix); - - // Formats an int value as "%02d". - static std::string FormatIntWidth2(int value); // "%02d" for width == 2 - - // Formats an int value as "%X". - static std::string FormatHexInt(int value); - - // Formats an int value as "%X". - static std::string FormatHexUInt32(UInt32 value); - - // Formats a byte as "%02X". - static std::string FormatByte(unsigned char value); - - private: - String(); // Not meant to be instantiated. -}; // class String - -// Gets the content of the stringstream's buffer as an std::string. Each '\0' -// character in the buffer is replaced with "\\0". -GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-tuple.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-tuple.h deleted file mode 100644 index 78a3a6a01fa..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-tuple.h +++ /dev/null @@ -1,1021 +0,0 @@ -// This file was GENERATED by command: -// pump.py gtest-tuple.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2009 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Implements a subset of TR1 tuple needed by Google Test and Google Mock. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ - -#include // For ::std::pair. - -// The compiler used in Symbian has a bug that prevents us from declaring the -// tuple template as a friend (it complains that tuple is redefined). This -// bypasses the bug by declaring the members that should otherwise be -// private as public. -// Sun Studio versions < 12 also have the above bug. -#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: -#else -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ - template friend class tuple; \ - private: -#endif - -// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict -// with our own definitions. Therefore using our own tuple does not work on -// those compilers. -#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */ -# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \ -GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers." -#endif - -// GTEST_n_TUPLE_(T) is the type of an n-tuple. -#define GTEST_0_TUPLE_(T) tuple<> -#define GTEST_1_TUPLE_(T) tuple -#define GTEST_2_TUPLE_(T) tuple -#define GTEST_3_TUPLE_(T) tuple -#define GTEST_4_TUPLE_(T) tuple -#define GTEST_5_TUPLE_(T) tuple -#define GTEST_6_TUPLE_(T) tuple -#define GTEST_7_TUPLE_(T) tuple -#define GTEST_8_TUPLE_(T) tuple -#define GTEST_9_TUPLE_(T) tuple -#define GTEST_10_TUPLE_(T) tuple - -// GTEST_n_TYPENAMES_(T) declares a list of n typenames. -#define GTEST_0_TYPENAMES_(T) -#define GTEST_1_TYPENAMES_(T) typename T##0 -#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 -#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 -#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3 -#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4 -#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5 -#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6 -#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 -#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6, \ - typename T##7, typename T##8 -#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6, \ - typename T##7, typename T##8, typename T##9 - -// In theory, defining stuff in the ::std namespace is undefined -// behavior. We can do this as we are playing the role of a standard -// library vendor. -namespace std { -namespace tr1 { - -template -class tuple; - -// Anything in namespace gtest_internal is Google Test's INTERNAL -// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. -namespace gtest_internal { - -// ByRef::type is T if T is a reference; otherwise it's const T&. -template -struct ByRef { typedef const T& type; }; // NOLINT -template -struct ByRef { typedef T& type; }; // NOLINT - -// A handy wrapper for ByRef. -#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type - -// AddRef::type is T if T is a reference; otherwise it's T&. This -// is the same as tr1::add_reference::type. -template -struct AddRef { typedef T& type; }; // NOLINT -template -struct AddRef { typedef T& type; }; // NOLINT - -// A handy wrapper for AddRef. -#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type - -// A helper for implementing get(). -template class Get; - -// A helper for implementing tuple_element. kIndexValid is true -// iff k < the number of fields in tuple type T. -template -struct TupleElement; - -template -struct TupleElement { - typedef T0 type; -}; - -template -struct TupleElement { - typedef T1 type; -}; - -template -struct TupleElement { - typedef T2 type; -}; - -template -struct TupleElement { - typedef T3 type; -}; - -template -struct TupleElement { - typedef T4 type; -}; - -template -struct TupleElement { - typedef T5 type; -}; - -template -struct TupleElement { - typedef T6 type; -}; - -template -struct TupleElement { - typedef T7 type; -}; - -template -struct TupleElement { - typedef T8 type; -}; - -template -struct TupleElement { - typedef T9 type; -}; - -} // namespace gtest_internal - -template <> -class tuple<> { - public: - tuple() {} - tuple(const tuple& /* t */) {} - tuple& operator=(const tuple& /* t */) { return *this; } -}; - -template -class GTEST_1_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} - - tuple(const tuple& t) : f0_(t.f0_) {} - - template - tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_1_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { - f0_ = t.f0_; - return *this; - } - - T0 f0_; -}; - -template -class GTEST_2_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), - f1_(f1) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} - - template - tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} - template - tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_2_TUPLE_(U)& t) { - return CopyFrom(t); - } - template - tuple& operator=(const ::std::pair& p) { - f0_ = p.first; - f1_ = p.second; - return *this; - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - return *this; - } - - T0 f0_; - T1 f1_; -}; - -template -class GTEST_3_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} - - template - tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_3_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; -}; - -template -class GTEST_4_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), - f3_(f3) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} - - template - tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_4_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; -}; - -template -class GTEST_5_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, - GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_) {} - - template - tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_5_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; -}; - -template -class GTEST_6_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), - f5_(f5) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_) {} - - template - tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_6_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; -}; - -template -class GTEST_7_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), - f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} - - template - tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_7_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; -}; - -template -class GTEST_8_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, - GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), - f5_(f5), f6_(f6), f7_(f7) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} - - template - tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_8_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - f7_ = t.f7_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; - T7 f7_; -}; - -template -class GTEST_9_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, - GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), - f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} - - template - tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_9_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - f7_ = t.f7_; - f8_ = t.f8_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; - T7 f7_; - T8 f8_; -}; - -template -class tuple { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), - f9_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, - GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), - f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} - - template - tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), - f9_(t.f9_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_10_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - f7_ = t.f7_; - f8_ = t.f8_; - f9_ = t.f9_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; - T7 f7_; - T8 f8_; - T9 f9_; -}; - -// 6.1.3.2 Tuple creation functions. - -// Known limitations: we don't support passing an -// std::tr1::reference_wrapper to make_tuple(). And we don't -// implement tie(). - -inline tuple<> make_tuple() { return tuple<>(); } - -template -inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { - return GTEST_1_TUPLE_(T)(f0); -} - -template -inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { - return GTEST_2_TUPLE_(T)(f0, f1); -} - -template -inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { - return GTEST_3_TUPLE_(T)(f0, f1, f2); -} - -template -inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3) { - return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); -} - -template -inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4) { - return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); -} - -template -inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5) { - return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); -} - -template -inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6) { - return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); -} - -template -inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { - return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); -} - -template -inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, - const T8& f8) { - return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); -} - -template -inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, - const T8& f8, const T9& f9) { - return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); -} - -// 6.1.3.3 Tuple helper classes. - -template struct tuple_size; - -template -struct tuple_size { - static const int value = 0; -}; - -template -struct tuple_size { - static const int value = 1; -}; - -template -struct tuple_size { - static const int value = 2; -}; - -template -struct tuple_size { - static const int value = 3; -}; - -template -struct tuple_size { - static const int value = 4; -}; - -template -struct tuple_size { - static const int value = 5; -}; - -template -struct tuple_size { - static const int value = 6; -}; - -template -struct tuple_size { - static const int value = 7; -}; - -template -struct tuple_size { - static const int value = 8; -}; - -template -struct tuple_size { - static const int value = 9; -}; - -template -struct tuple_size { - static const int value = 10; -}; - -template -struct tuple_element { - typedef typename gtest_internal::TupleElement< - k < (tuple_size::value), k, Tuple>::type type; -}; - -#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type - -// 6.1.3.4 Element access. - -namespace gtest_internal { - -template <> -class Get<0> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) - Field(Tuple& t) { return t.f0_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) - ConstField(const Tuple& t) { return t.f0_; } -}; - -template <> -class Get<1> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) - Field(Tuple& t) { return t.f1_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) - ConstField(const Tuple& t) { return t.f1_; } -}; - -template <> -class Get<2> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) - Field(Tuple& t) { return t.f2_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) - ConstField(const Tuple& t) { return t.f2_; } -}; - -template <> -class Get<3> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) - Field(Tuple& t) { return t.f3_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) - ConstField(const Tuple& t) { return t.f3_; } -}; - -template <> -class Get<4> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) - Field(Tuple& t) { return t.f4_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) - ConstField(const Tuple& t) { return t.f4_; } -}; - -template <> -class Get<5> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) - Field(Tuple& t) { return t.f5_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) - ConstField(const Tuple& t) { return t.f5_; } -}; - -template <> -class Get<6> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) - Field(Tuple& t) { return t.f6_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) - ConstField(const Tuple& t) { return t.f6_; } -}; - -template <> -class Get<7> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) - Field(Tuple& t) { return t.f7_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) - ConstField(const Tuple& t) { return t.f7_; } -}; - -template <> -class Get<8> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) - Field(Tuple& t) { return t.f8_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) - ConstField(const Tuple& t) { return t.f8_; } -}; - -template <> -class Get<9> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) - Field(Tuple& t) { return t.f9_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) - ConstField(const Tuple& t) { return t.f9_; } -}; - -} // namespace gtest_internal - -template -GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) -get(GTEST_10_TUPLE_(T)& t) { - return gtest_internal::Get::Field(t); -} - -template -GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) -get(const GTEST_10_TUPLE_(T)& t) { - return gtest_internal::Get::ConstField(t); -} - -// 6.1.3.5 Relational operators - -// We only implement == and !=, as we don't have a need for the rest yet. - -namespace gtest_internal { - -// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the -// first k fields of t1 equals the first k fields of t2. -// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if -// k1 != k2. -template -struct SameSizeTuplePrefixComparator; - -template <> -struct SameSizeTuplePrefixComparator<0, 0> { - template - static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { - return true; - } -}; - -template -struct SameSizeTuplePrefixComparator { - template - static bool Eq(const Tuple1& t1, const Tuple2& t2) { - return SameSizeTuplePrefixComparator::Eq(t1, t2) && - ::std::tr1::get(t1) == ::std::tr1::get(t2); - } -}; - -} // namespace gtest_internal - -template -inline bool operator==(const GTEST_10_TUPLE_(T)& t, - const GTEST_10_TUPLE_(U)& u) { - return gtest_internal::SameSizeTuplePrefixComparator< - tuple_size::value, - tuple_size::value>::Eq(t, u); -} - -template -inline bool operator!=(const GTEST_10_TUPLE_(T)& t, - const GTEST_10_TUPLE_(U)& u) { return !(t == u); } - -// 6.1.4 Pairs. -// Unimplemented. - -} // namespace tr1 -} // namespace std - -#undef GTEST_0_TUPLE_ -#undef GTEST_1_TUPLE_ -#undef GTEST_2_TUPLE_ -#undef GTEST_3_TUPLE_ -#undef GTEST_4_TUPLE_ -#undef GTEST_5_TUPLE_ -#undef GTEST_6_TUPLE_ -#undef GTEST_7_TUPLE_ -#undef GTEST_8_TUPLE_ -#undef GTEST_9_TUPLE_ -#undef GTEST_10_TUPLE_ - -#undef GTEST_0_TYPENAMES_ -#undef GTEST_1_TYPENAMES_ -#undef GTEST_2_TYPENAMES_ -#undef GTEST_3_TYPENAMES_ -#undef GTEST_4_TYPENAMES_ -#undef GTEST_5_TYPENAMES_ -#undef GTEST_6_TYPENAMES_ -#undef GTEST_7_TYPENAMES_ -#undef GTEST_8_TYPENAMES_ -#undef GTEST_9_TYPENAMES_ -#undef GTEST_10_TYPENAMES_ - -#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ -#undef GTEST_BY_REF_ -#undef GTEST_ADD_REF_ -#undef GTEST_TUPLE_ELEMENT_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-tuple.h.pump b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-tuple.h.pump deleted file mode 100644 index bb626e049f0..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-tuple.h.pump +++ /dev/null @@ -1,348 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 10 $$ Maximum number of tuple fields we want to support. -$$ This meta comment fixes auto-indentation in Emacs. }} -// Copyright 2009 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Implements a subset of TR1 tuple needed by Google Test and Google Mock. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ - -#include // For ::std::pair. - -// The compiler used in Symbian has a bug that prevents us from declaring the -// tuple template as a friend (it complains that tuple is redefined). This -// bypasses the bug by declaring the members that should otherwise be -// private as public. -// Sun Studio versions < 12 also have the above bug. -#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: -#else -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ - template friend class tuple; \ - private: -#endif - -// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict -// with our own definitions. Therefore using our own tuple does not work on -// those compilers. -#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */ -# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \ -GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers." -#endif - - -$range i 0..n-1 -$range j 0..n -$range k 1..n -// GTEST_n_TUPLE_(T) is the type of an n-tuple. -#define GTEST_0_TUPLE_(T) tuple<> - -$for k [[ -$range m 0..k-1 -$range m2 k..n-1 -#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]> - -]] - -// GTEST_n_TYPENAMES_(T) declares a list of n typenames. - -$for j [[ -$range m 0..j-1 -#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]] - - -]] - -// In theory, defining stuff in the ::std namespace is undefined -// behavior. We can do this as we are playing the role of a standard -// library vendor. -namespace std { -namespace tr1 { - -template <$for i, [[typename T$i = void]]> -class tuple; - -// Anything in namespace gtest_internal is Google Test's INTERNAL -// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. -namespace gtest_internal { - -// ByRef::type is T if T is a reference; otherwise it's const T&. -template -struct ByRef { typedef const T& type; }; // NOLINT -template -struct ByRef { typedef T& type; }; // NOLINT - -// A handy wrapper for ByRef. -#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type - -// AddRef::type is T if T is a reference; otherwise it's T&. This -// is the same as tr1::add_reference::type. -template -struct AddRef { typedef T& type; }; // NOLINT -template -struct AddRef { typedef T& type; }; // NOLINT - -// A handy wrapper for AddRef. -#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type - -// A helper for implementing get(). -template class Get; - -// A helper for implementing tuple_element. kIndexValid is true -// iff k < the number of fields in tuple type T. -template -struct TupleElement; - - -$for i [[ -template -struct TupleElement { - typedef T$i type; -}; - - -]] -} // namespace gtest_internal - -template <> -class tuple<> { - public: - tuple() {} - tuple(const tuple& /* t */) {} - tuple& operator=(const tuple& /* t */) { return *this; } -}; - - -$for k [[ -$range m 0..k-1 -template -class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] { - public: - template friend class gtest_internal::Get; - - tuple() : $for m, [[f$(m)_()]] {} - - explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]] -$for m, [[f$(m)_(f$m)]] {} - - tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} - - template - tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} - -$if k == 2 [[ - template - tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} - -]] - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) { - return CopyFrom(t); - } - -$if k == 2 [[ - template - tuple& operator=(const ::std::pair& p) { - f0_ = p.first; - f1_ = p.second; - return *this; - } - -]] - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) { - -$for m [[ - f$(m)_ = t.f$(m)_; - -]] - return *this; - } - - -$for m [[ - T$m f$(m)_; - -]] -}; - - -]] -// 6.1.3.2 Tuple creation functions. - -// Known limitations: we don't support passing an -// std::tr1::reference_wrapper to make_tuple(). And we don't -// implement tie(). - -inline tuple<> make_tuple() { return tuple<>(); } - -$for k [[ -$range m 0..k-1 - -template -inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) { - return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]); -} - -]] - -// 6.1.3.3 Tuple helper classes. - -template struct tuple_size; - - -$for j [[ -template -struct tuple_size { - static const int value = $j; -}; - - -]] -template -struct tuple_element { - typedef typename gtest_internal::TupleElement< - k < (tuple_size::value), k, Tuple>::type type; -}; - -#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type - -// 6.1.3.4 Element access. - -namespace gtest_internal { - - -$for i [[ -template <> -class Get<$i> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) - Field(Tuple& t) { return t.f$(i)_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) - ConstField(const Tuple& t) { return t.f$(i)_; } -}; - - -]] -} // namespace gtest_internal - -template -GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) -get(GTEST_$(n)_TUPLE_(T)& t) { - return gtest_internal::Get::Field(t); -} - -template -GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) -get(const GTEST_$(n)_TUPLE_(T)& t) { - return gtest_internal::Get::ConstField(t); -} - -// 6.1.3.5 Relational operators - -// We only implement == and !=, as we don't have a need for the rest yet. - -namespace gtest_internal { - -// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the -// first k fields of t1 equals the first k fields of t2. -// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if -// k1 != k2. -template -struct SameSizeTuplePrefixComparator; - -template <> -struct SameSizeTuplePrefixComparator<0, 0> { - template - static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { - return true; - } -}; - -template -struct SameSizeTuplePrefixComparator { - template - static bool Eq(const Tuple1& t1, const Tuple2& t2) { - return SameSizeTuplePrefixComparator::Eq(t1, t2) && - ::std::tr1::get(t1) == ::std::tr1::get(t2); - } -}; - -} // namespace gtest_internal - -template -inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t, - const GTEST_$(n)_TUPLE_(U)& u) { - return gtest_internal::SameSizeTuplePrefixComparator< - tuple_size::value, - tuple_size::value>::Eq(t, u); -} - -template -inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t, - const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); } - -// 6.1.4 Pairs. -// Unimplemented. - -} // namespace tr1 -} // namespace std - - -$for j [[ -#undef GTEST_$(j)_TUPLE_ - -]] - - -$for j [[ -#undef GTEST_$(j)_TYPENAMES_ - -]] - -#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ -#undef GTEST_BY_REF_ -#undef GTEST_ADD_REF_ -#undef GTEST_TUPLE_ELEMENT_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-type-util.h b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-type-util.h deleted file mode 100644 index 3d7542d1fb3..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-type-util.h +++ /dev/null @@ -1,3335 +0,0 @@ -// This file was GENERATED by command: -// pump.py gtest-type-util.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// Type utilities needed for implementing typed and type-parameterized -// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently we support at most 50 types in a list, and at most 50 -// type-parameterized tests in one type-parameterized test suite. -// Please contact googletestframework@googlegroups.com if you need -// more. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ - -#include "gtest/internal/gtest-port.h" - -// #ifdef __GNUC__ is too general here. It is possible to use gcc without using -// libstdc++ (which is where cxxabi.h comes from). -# if GTEST_HAS_CXXABI_H_ -# include -# elif defined(__HP_aCC) -# include -# endif // GTEST_HASH_CXXABI_H_ - -namespace testing { -namespace internal { - -// Canonicalizes a given name with respect to the Standard C++ Library. -// This handles removing the inline namespace within `std` that is -// used by various standard libraries (e.g., `std::__1`). Names outside -// of namespace std are returned unmodified. -inline std::string CanonicalizeForStdLibVersioning(std::string s) { - static const char prefix[] = "std::__"; - if (s.compare(0, strlen(prefix), prefix) == 0) { - std::string::size_type end = s.find("::", strlen(prefix)); - if (end != s.npos) { - // Erase everything between the initial `std` and the second `::`. - s.erase(strlen("std"), end - strlen("std")); - } - } - return s; -} - -// GetTypeName() returns a human-readable name of type T. -// NB: This function is also used in Google Mock, so don't move it inside of -// the typed-test-only section below. -template -std::string GetTypeName() { -# if GTEST_HAS_RTTI - - const char* const name = typeid(T).name(); -# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) - int status = 0; - // gcc's implementation of typeid(T).name() mangles the type name, - // so we have to demangle it. -# if GTEST_HAS_CXXABI_H_ - using abi::__cxa_demangle; -# endif // GTEST_HAS_CXXABI_H_ - char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); - const std::string name_str(status == 0 ? readable_name : name); - free(readable_name); - return CanonicalizeForStdLibVersioning(name_str); -# else - return name; -# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC - -# else - - return ""; - -# endif // GTEST_HAS_RTTI -} - -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -// A unique type used as the default value for the arguments of class -// template Types. This allows us to simulate variadic templates -// (e.g. Types, Type, and etc), which C++ doesn't -// support directly. -struct None {}; - -// The following family of struct and struct templates are used to -// represent type lists. In particular, TypesN -// represents a type list with N types (T1, T2, ..., and TN) in it. -// Except for Types0, every struct in the family has two member types: -// Head for the first type in the list, and Tail for the rest of the -// list. - -// The empty type list. -struct Types0 {}; - -// Type lists of length 1, 2, 3, and so on. - -template -struct Types1 { - typedef T1 Head; - typedef Types0 Tail; -}; -template -struct Types2 { - typedef T1 Head; - typedef Types1 Tail; -}; - -template -struct Types3 { - typedef T1 Head; - typedef Types2 Tail; -}; - -template -struct Types4 { - typedef T1 Head; - typedef Types3 Tail; -}; - -template -struct Types5 { - typedef T1 Head; - typedef Types4 Tail; -}; - -template -struct Types6 { - typedef T1 Head; - typedef Types5 Tail; -}; - -template -struct Types7 { - typedef T1 Head; - typedef Types6 Tail; -}; - -template -struct Types8 { - typedef T1 Head; - typedef Types7 Tail; -}; - -template -struct Types9 { - typedef T1 Head; - typedef Types8 Tail; -}; - -template -struct Types10 { - typedef T1 Head; - typedef Types9 Tail; -}; - -template -struct Types11 { - typedef T1 Head; - typedef Types10 Tail; -}; - -template -struct Types12 { - typedef T1 Head; - typedef Types11 Tail; -}; - -template -struct Types13 { - typedef T1 Head; - typedef Types12 Tail; -}; - -template -struct Types14 { - typedef T1 Head; - typedef Types13 Tail; -}; - -template -struct Types15 { - typedef T1 Head; - typedef Types14 Tail; -}; - -template -struct Types16 { - typedef T1 Head; - typedef Types15 Tail; -}; - -template -struct Types17 { - typedef T1 Head; - typedef Types16 Tail; -}; - -template -struct Types18 { - typedef T1 Head; - typedef Types17 Tail; -}; - -template -struct Types19 { - typedef T1 Head; - typedef Types18 Tail; -}; - -template -struct Types20 { - typedef T1 Head; - typedef Types19 Tail; -}; - -template -struct Types21 { - typedef T1 Head; - typedef Types20 Tail; -}; - -template -struct Types22 { - typedef T1 Head; - typedef Types21 Tail; -}; - -template -struct Types23 { - typedef T1 Head; - typedef Types22 Tail; -}; - -template -struct Types24 { - typedef T1 Head; - typedef Types23 Tail; -}; - -template -struct Types25 { - typedef T1 Head; - typedef Types24 Tail; -}; - -template -struct Types26 { - typedef T1 Head; - typedef Types25 Tail; -}; - -template -struct Types27 { - typedef T1 Head; - typedef Types26 Tail; -}; - -template -struct Types28 { - typedef T1 Head; - typedef Types27 Tail; -}; - -template -struct Types29 { - typedef T1 Head; - typedef Types28 Tail; -}; - -template -struct Types30 { - typedef T1 Head; - typedef Types29 Tail; -}; - -template -struct Types31 { - typedef T1 Head; - typedef Types30 Tail; -}; - -template -struct Types32 { - typedef T1 Head; - typedef Types31 Tail; -}; - -template -struct Types33 { - typedef T1 Head; - typedef Types32 Tail; -}; - -template -struct Types34 { - typedef T1 Head; - typedef Types33 Tail; -}; - -template -struct Types35 { - typedef T1 Head; - typedef Types34 Tail; -}; - -template -struct Types36 { - typedef T1 Head; - typedef Types35 Tail; -}; - -template -struct Types37 { - typedef T1 Head; - typedef Types36 Tail; -}; - -template -struct Types38 { - typedef T1 Head; - typedef Types37 Tail; -}; - -template -struct Types39 { - typedef T1 Head; - typedef Types38 Tail; -}; - -template -struct Types40 { - typedef T1 Head; - typedef Types39 Tail; -}; - -template -struct Types41 { - typedef T1 Head; - typedef Types40 Tail; -}; - -template -struct Types42 { - typedef T1 Head; - typedef Types41 Tail; -}; - -template -struct Types43 { - typedef T1 Head; - typedef Types42 Tail; -}; - -template -struct Types44 { - typedef T1 Head; - typedef Types43 Tail; -}; - -template -struct Types45 { - typedef T1 Head; - typedef Types44 Tail; -}; - -template -struct Types46 { - typedef T1 Head; - typedef Types45 Tail; -}; - -template -struct Types47 { - typedef T1 Head; - typedef Types46 Tail; -}; - -template -struct Types48 { - typedef T1 Head; - typedef Types47 Tail; -}; - -template -struct Types49 { - typedef T1 Head; - typedef Types48 Tail; -}; - -template -struct Types50 { - typedef T1 Head; - typedef Types49 Tail; -}; - - -} // namespace internal - -// We don't want to require the users to write TypesN<...> directly, -// as that would require them to count the length. Types<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Types -// will appear as Types in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Types, and Google Test will translate -// that to TypesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Types template. -template -struct Types { - typedef internal::Types50 type; -}; - -template <> -struct Types { - typedef internal::Types0 type; -}; -template -struct Types { - typedef internal::Types1 type; -}; -template -struct Types { - typedef internal::Types2 type; -}; -template -struct Types { - typedef internal::Types3 type; -}; -template -struct Types { - typedef internal::Types4 type; -}; -template -struct Types { - typedef internal::Types5 type; -}; -template -struct Types { - typedef internal::Types6 type; -}; -template -struct Types { - typedef internal::Types7 type; -}; -template -struct Types { - typedef internal::Types8 type; -}; -template -struct Types { - typedef internal::Types9 type; -}; -template -struct Types { - typedef internal::Types10 type; -}; -template -struct Types { - typedef internal::Types11 type; -}; -template -struct Types { - typedef internal::Types12 type; -}; -template -struct Types { - typedef internal::Types13 type; -}; -template -struct Types { - typedef internal::Types14 type; -}; -template -struct Types { - typedef internal::Types15 type; -}; -template -struct Types { - typedef internal::Types16 type; -}; -template -struct Types { - typedef internal::Types17 type; -}; -template -struct Types { - typedef internal::Types18 type; -}; -template -struct Types { - typedef internal::Types19 type; -}; -template -struct Types { - typedef internal::Types20 type; -}; -template -struct Types { - typedef internal::Types21 type; -}; -template -struct Types { - typedef internal::Types22 type; -}; -template -struct Types { - typedef internal::Types23 type; -}; -template -struct Types { - typedef internal::Types24 type; -}; -template -struct Types { - typedef internal::Types25 type; -}; -template -struct Types { - typedef internal::Types26 type; -}; -template -struct Types { - typedef internal::Types27 type; -}; -template -struct Types { - typedef internal::Types28 type; -}; -template -struct Types { - typedef internal::Types29 type; -}; -template -struct Types { - typedef internal::Types30 type; -}; -template -struct Types { - typedef internal::Types31 type; -}; -template -struct Types { - typedef internal::Types32 type; -}; -template -struct Types { - typedef internal::Types33 type; -}; -template -struct Types { - typedef internal::Types34 type; -}; -template -struct Types { - typedef internal::Types35 type; -}; -template -struct Types { - typedef internal::Types36 type; -}; -template -struct Types { - typedef internal::Types37 type; -}; -template -struct Types { - typedef internal::Types38 type; -}; -template -struct Types { - typedef internal::Types39 type; -}; -template -struct Types { - typedef internal::Types40 type; -}; -template -struct Types { - typedef internal::Types41 type; -}; -template -struct Types { - typedef internal::Types42 type; -}; -template -struct Types { - typedef internal::Types43 type; -}; -template -struct Types { - typedef internal::Types44 type; -}; -template -struct Types { - typedef internal::Types45 type; -}; -template -struct Types { - typedef internal::Types46 type; -}; -template -struct Types { - typedef internal::Types47 type; -}; -template -struct Types { - typedef internal::Types48 type; -}; -template -struct Types { - typedef internal::Types49 type; -}; - -namespace internal { - -# define GTEST_TEMPLATE_ template class - -// The template "selector" struct TemplateSel is used to -// represent Tmpl, which must be a class template with one type -// parameter, as a type. TemplateSel::Bind::type is defined -// as the type Tmpl. This allows us to actually instantiate the -// template "selected" by TemplateSel. -// -// This trick is necessary for simulating typedef for class templates, -// which C++ doesn't support directly. -template -struct TemplateSel { - template - struct Bind { - typedef Tmpl type; - }; -}; - -# define GTEST_BIND_(TmplSel, T) \ - TmplSel::template Bind::type - -// A unique struct template used as the default value for the -// arguments of class template Templates. This allows us to simulate -// variadic templates (e.g. Templates, Templates, -// and etc), which C++ doesn't support directly. -template -struct NoneT {}; - -// The following family of struct and struct templates are used to -// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except -// for Templates0, every struct in the family has two member types: -// Head for the selector of the first template in the list, and Tail -// for the rest of the list. - -// The empty template list. -struct Templates0 {}; - -// Template lists of length 1, 2, 3, and so on. - -template -struct Templates1 { - typedef TemplateSel Head; - typedef Templates0 Tail; -}; -template -struct Templates2 { - typedef TemplateSel Head; - typedef Templates1 Tail; -}; - -template -struct Templates3 { - typedef TemplateSel Head; - typedef Templates2 Tail; -}; - -template -struct Templates4 { - typedef TemplateSel Head; - typedef Templates3 Tail; -}; - -template -struct Templates5 { - typedef TemplateSel Head; - typedef Templates4 Tail; -}; - -template -struct Templates6 { - typedef TemplateSel Head; - typedef Templates5 Tail; -}; - -template -struct Templates7 { - typedef TemplateSel Head; - typedef Templates6 Tail; -}; - -template -struct Templates8 { - typedef TemplateSel Head; - typedef Templates7 Tail; -}; - -template -struct Templates9 { - typedef TemplateSel Head; - typedef Templates8 Tail; -}; - -template -struct Templates10 { - typedef TemplateSel Head; - typedef Templates9 Tail; -}; - -template -struct Templates11 { - typedef TemplateSel Head; - typedef Templates10 Tail; -}; - -template -struct Templates12 { - typedef TemplateSel Head; - typedef Templates11 Tail; -}; - -template -struct Templates13 { - typedef TemplateSel Head; - typedef Templates12 Tail; -}; - -template -struct Templates14 { - typedef TemplateSel Head; - typedef Templates13 Tail; -}; - -template -struct Templates15 { - typedef TemplateSel Head; - typedef Templates14 Tail; -}; - -template -struct Templates16 { - typedef TemplateSel Head; - typedef Templates15 Tail; -}; - -template -struct Templates17 { - typedef TemplateSel Head; - typedef Templates16 Tail; -}; - -template -struct Templates18 { - typedef TemplateSel Head; - typedef Templates17 Tail; -}; - -template -struct Templates19 { - typedef TemplateSel Head; - typedef Templates18 Tail; -}; - -template -struct Templates20 { - typedef TemplateSel Head; - typedef Templates19 Tail; -}; - -template -struct Templates21 { - typedef TemplateSel Head; - typedef Templates20 Tail; -}; - -template -struct Templates22 { - typedef TemplateSel Head; - typedef Templates21 Tail; -}; - -template -struct Templates23 { - typedef TemplateSel Head; - typedef Templates22 Tail; -}; - -template -struct Templates24 { - typedef TemplateSel Head; - typedef Templates23 Tail; -}; - -template -struct Templates25 { - typedef TemplateSel Head; - typedef Templates24 Tail; -}; - -template -struct Templates26 { - typedef TemplateSel Head; - typedef Templates25 Tail; -}; - -template -struct Templates27 { - typedef TemplateSel Head; - typedef Templates26 Tail; -}; - -template -struct Templates28 { - typedef TemplateSel Head; - typedef Templates27 Tail; -}; - -template -struct Templates29 { - typedef TemplateSel Head; - typedef Templates28 Tail; -}; - -template -struct Templates30 { - typedef TemplateSel Head; - typedef Templates29 Tail; -}; - -template -struct Templates31 { - typedef TemplateSel Head; - typedef Templates30 Tail; -}; - -template -struct Templates32 { - typedef TemplateSel Head; - typedef Templates31 Tail; -}; - -template -struct Templates33 { - typedef TemplateSel Head; - typedef Templates32 Tail; -}; - -template -struct Templates34 { - typedef TemplateSel Head; - typedef Templates33 Tail; -}; - -template -struct Templates35 { - typedef TemplateSel Head; - typedef Templates34 Tail; -}; - -template -struct Templates36 { - typedef TemplateSel Head; - typedef Templates35 Tail; -}; - -template -struct Templates37 { - typedef TemplateSel Head; - typedef Templates36 Tail; -}; - -template -struct Templates38 { - typedef TemplateSel Head; - typedef Templates37 Tail; -}; - -template -struct Templates39 { - typedef TemplateSel Head; - typedef Templates38 Tail; -}; - -template -struct Templates40 { - typedef TemplateSel Head; - typedef Templates39 Tail; -}; - -template -struct Templates41 { - typedef TemplateSel Head; - typedef Templates40 Tail; -}; - -template -struct Templates42 { - typedef TemplateSel Head; - typedef Templates41 Tail; -}; - -template -struct Templates43 { - typedef TemplateSel Head; - typedef Templates42 Tail; -}; - -template -struct Templates44 { - typedef TemplateSel Head; - typedef Templates43 Tail; -}; - -template -struct Templates45 { - typedef TemplateSel Head; - typedef Templates44 Tail; -}; - -template -struct Templates46 { - typedef TemplateSel Head; - typedef Templates45 Tail; -}; - -template -struct Templates47 { - typedef TemplateSel Head; - typedef Templates46 Tail; -}; - -template -struct Templates48 { - typedef TemplateSel Head; - typedef Templates47 Tail; -}; - -template -struct Templates49 { - typedef TemplateSel Head; - typedef Templates48 Tail; -}; - -template -struct Templates50 { - typedef TemplateSel Head; - typedef Templates49 Tail; -}; - - -// We don't want to require the users to write TemplatesN<...> directly, -// as that would require them to count the length. Templates<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Templates -// will appear as Templates in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Templates, and Google Test will translate -// that to TemplatesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Templates template. -template -struct Templates { - typedef Templates50 type; -}; - -template <> -struct Templates { - typedef Templates0 type; -}; -template -struct Templates { - typedef Templates1 type; -}; -template -struct Templates { - typedef Templates2 type; -}; -template -struct Templates { - typedef Templates3 type; -}; -template -struct Templates { - typedef Templates4 type; -}; -template -struct Templates { - typedef Templates5 type; -}; -template -struct Templates { - typedef Templates6 type; -}; -template -struct Templates { - typedef Templates7 type; -}; -template -struct Templates { - typedef Templates8 type; -}; -template -struct Templates { - typedef Templates9 type; -}; -template -struct Templates { - typedef Templates10 type; -}; -template -struct Templates { - typedef Templates11 type; -}; -template -struct Templates { - typedef Templates12 type; -}; -template -struct Templates { - typedef Templates13 type; -}; -template -struct Templates { - typedef Templates14 type; -}; -template -struct Templates { - typedef Templates15 type; -}; -template -struct Templates { - typedef Templates16 type; -}; -template -struct Templates { - typedef Templates17 type; -}; -template -struct Templates { - typedef Templates18 type; -}; -template -struct Templates { - typedef Templates19 type; -}; -template -struct Templates { - typedef Templates20 type; -}; -template -struct Templates { - typedef Templates21 type; -}; -template -struct Templates { - typedef Templates22 type; -}; -template -struct Templates { - typedef Templates23 type; -}; -template -struct Templates { - typedef Templates24 type; -}; -template -struct Templates { - typedef Templates25 type; -}; -template -struct Templates { - typedef Templates26 type; -}; -template -struct Templates { - typedef Templates27 type; -}; -template -struct Templates { - typedef Templates28 type; -}; -template -struct Templates { - typedef Templates29 type; -}; -template -struct Templates { - typedef Templates30 type; -}; -template -struct Templates { - typedef Templates31 type; -}; -template -struct Templates { - typedef Templates32 type; -}; -template -struct Templates { - typedef Templates33 type; -}; -template -struct Templates { - typedef Templates34 type; -}; -template -struct Templates { - typedef Templates35 type; -}; -template -struct Templates { - typedef Templates36 type; -}; -template -struct Templates { - typedef Templates37 type; -}; -template -struct Templates { - typedef Templates38 type; -}; -template -struct Templates { - typedef Templates39 type; -}; -template -struct Templates { - typedef Templates40 type; -}; -template -struct Templates { - typedef Templates41 type; -}; -template -struct Templates { - typedef Templates42 type; -}; -template -struct Templates { - typedef Templates43 type; -}; -template -struct Templates { - typedef Templates44 type; -}; -template -struct Templates { - typedef Templates45 type; -}; -template -struct Templates { - typedef Templates46 type; -}; -template -struct Templates { - typedef Templates47 type; -}; -template -struct Templates { - typedef Templates48 type; -}; -template -struct Templates { - typedef Templates49 type; -}; - -// The TypeList template makes it possible to use either a single type -// or a Types<...> list in TYPED_TEST_SUITE() and -// INSTANTIATE_TYPED_TEST_SUITE_P(). - -template -struct TypeList { - typedef Types1 type; -}; - -template -struct TypeList > { - typedef typename Types::type type; -}; - -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-type-util.h.pump b/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-type-util.h.pump deleted file mode 100644 index 5e31b7b3206..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/include/gtest/internal/gtest-type-util.h.pump +++ /dev/null @@ -1,302 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 50 $$ Maximum length of type lists we want to support. -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Type utilities needed for implementing typed and type-parameterized -// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently we support at most $n types in a list, and at most $n -// type-parameterized tests in one type-parameterized test suite. -// Please contact googletestframework@googlegroups.com if you need -// more. - -// GOOGLETEST_CM0001 DO NOT DELETE - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ - -#include "gtest/internal/gtest-port.h" - -// #ifdef __GNUC__ is too general here. It is possible to use gcc without using -// libstdc++ (which is where cxxabi.h comes from). -# if GTEST_HAS_CXXABI_H_ -# include -# elif defined(__HP_aCC) -# include -# endif // GTEST_HASH_CXXABI_H_ - -namespace testing { -namespace internal { - -// Canonicalizes a given name with respect to the Standard C++ Library. -// This handles removing the inline namespace within `std` that is -// used by various standard libraries (e.g., `std::__1`). Names outside -// of namespace std are returned unmodified. -inline std::string CanonicalizeForStdLibVersioning(std::string s) { - static const char prefix[] = "std::__"; - if (s.compare(0, strlen(prefix), prefix) == 0) { - std::string::size_type end = s.find("::", strlen(prefix)); - if (end != s.npos) { - // Erase everything between the initial `std` and the second `::`. - s.erase(strlen("std"), end - strlen("std")); - } - } - return s; -} - -// GetTypeName() returns a human-readable name of type T. -// NB: This function is also used in Google Mock, so don't move it inside of -// the typed-test-only section below. -template -std::string GetTypeName() { -# if GTEST_HAS_RTTI - - const char* const name = typeid(T).name(); -# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) - int status = 0; - // gcc's implementation of typeid(T).name() mangles the type name, - // so we have to demangle it. -# if GTEST_HAS_CXXABI_H_ - using abi::__cxa_demangle; -# endif // GTEST_HAS_CXXABI_H_ - char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); - const std::string name_str(status == 0 ? readable_name : name); - free(readable_name); - return CanonicalizeForStdLibVersioning(name_str); -# else - return name; -# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC - -# else - - return ""; - -# endif // GTEST_HAS_RTTI -} - -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -// A unique type used as the default value for the arguments of class -// template Types. This allows us to simulate variadic templates -// (e.g. Types, Type, and etc), which C++ doesn't -// support directly. -struct None {}; - -// The following family of struct and struct templates are used to -// represent type lists. In particular, TypesN -// represents a type list with N types (T1, T2, ..., and TN) in it. -// Except for Types0, every struct in the family has two member types: -// Head for the first type in the list, and Tail for the rest of the -// list. - -// The empty type list. -struct Types0 {}; - -// Type lists of length 1, 2, 3, and so on. - -template -struct Types1 { - typedef T1 Head; - typedef Types0 Tail; -}; - -$range i 2..n - -$for i [[ -$range j 1..i -$range k 2..i -template <$for j, [[typename T$j]]> -struct Types$i { - typedef T1 Head; - typedef Types$(i-1)<$for k, [[T$k]]> Tail; -}; - - -]] - -} // namespace internal - -// We don't want to require the users to write TypesN<...> directly, -// as that would require them to count the length. Types<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Types -// will appear as Types in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Types, and Google Test will translate -// that to TypesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Types template. - -$range i 1..n -template <$for i, [[typename T$i = internal::None]]> -struct Types { - typedef internal::Types$n<$for i, [[T$i]]> type; -}; - -template <> -struct Types<$for i, [[internal::None]]> { - typedef internal::Types0 type; -}; - -$range i 1..n-1 -$for i [[ -$range j 1..i -$range k i+1..n -template <$for j, [[typename T$j]]> -struct Types<$for j, [[T$j]]$for k[[, internal::None]]> { - typedef internal::Types$i<$for j, [[T$j]]> type; -}; - -]] - -namespace internal { - -# define GTEST_TEMPLATE_ template class - -// The template "selector" struct TemplateSel is used to -// represent Tmpl, which must be a class template with one type -// parameter, as a type. TemplateSel::Bind::type is defined -// as the type Tmpl. This allows us to actually instantiate the -// template "selected" by TemplateSel. -// -// This trick is necessary for simulating typedef for class templates, -// which C++ doesn't support directly. -template -struct TemplateSel { - template - struct Bind { - typedef Tmpl type; - }; -}; - -# define GTEST_BIND_(TmplSel, T) \ - TmplSel::template Bind::type - -// A unique struct template used as the default value for the -// arguments of class template Templates. This allows us to simulate -// variadic templates (e.g. Templates, Templates, -// and etc), which C++ doesn't support directly. -template -struct NoneT {}; - -// The following family of struct and struct templates are used to -// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except -// for Templates0, every struct in the family has two member types: -// Head for the selector of the first template in the list, and Tail -// for the rest of the list. - -// The empty template list. -struct Templates0 {}; - -// Template lists of length 1, 2, 3, and so on. - -template -struct Templates1 { - typedef TemplateSel Head; - typedef Templates0 Tail; -}; - -$range i 2..n - -$for i [[ -$range j 1..i -$range k 2..i -template <$for j, [[GTEST_TEMPLATE_ T$j]]> -struct Templates$i { - typedef TemplateSel Head; - typedef Templates$(i-1)<$for k, [[T$k]]> Tail; -}; - - -]] - -// We don't want to require the users to write TemplatesN<...> directly, -// as that would require them to count the length. Templates<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Templates -// will appear as Templates in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Templates, and Google Test will translate -// that to TemplatesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Templates template. - -$range i 1..n -template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]> -struct Templates { - typedef Templates$n<$for i, [[T$i]]> type; -}; - -template <> -struct Templates<$for i, [[NoneT]]> { - typedef Templates0 type; -}; - -$range i 1..n-1 -$for i [[ -$range j 1..i -$range k i+1..n -template <$for j, [[GTEST_TEMPLATE_ T$j]]> -struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> { - typedef Templates$i<$for j, [[T$j]]> type; -}; - -]] - -// The TypeList template makes it possible to use either a single type -// or a Types<...> list in TYPED_TEST_SUITE() and -// INSTANTIATE_TYPED_TEST_SUITE_P(). - -template -struct TypeList { - typedef Types1 type; -}; - - -$range i 1..n -template <$for i, [[typename T$i]]> -struct TypeList > { - typedef typename Types<$for i, [[T$i]]>::type type; -}; - -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-all.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-all.cc deleted file mode 100644 index ad292905cf3..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-all.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// Google C++ Testing and Mocking Framework (Google Test) -// -// Sometimes it's desirable to build Google Test by compiling a single file. -// This file serves this purpose. - -// This line ensures that gtest.h can be compiled on its own, even -// when it's fused. -#include "gtest/gtest.h" - -// The following lines pull in the real gtest *.cc files. -#include "src/gtest.cc" -#include "src/gtest-death-test.cc" -#include "src/gtest-filepath.cc" -#include "src/gtest-matchers.cc" -#include "src/gtest-port.cc" -#include "src/gtest-printers.cc" -#include "src/gtest-test-part.cc" -#include "src/gtest-typed-test.cc" diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-death-test.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-death-test.cc deleted file mode 100644 index 92089ee24d9..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-death-test.cc +++ /dev/null @@ -1,1653 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// This file implements death tests. - -#include "gtest/gtest-death-test.h" - -#include - -#include "gtest/internal/gtest-port.h" -#include "gtest/internal/custom/gtest.h" - -#if GTEST_HAS_DEATH_TEST - -# if GTEST_OS_MAC -# include -# endif // GTEST_OS_MAC - -# include -# include -# include - -# if GTEST_OS_LINUX -# include -# endif // GTEST_OS_LINUX - -# include - -# if GTEST_OS_WINDOWS -# include -# else -# include -# include -# endif // GTEST_OS_WINDOWS - -# if GTEST_OS_QNX -# include -# endif // GTEST_OS_QNX - -# if GTEST_OS_FUCHSIA -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# endif // GTEST_OS_FUCHSIA - -#endif // GTEST_HAS_DEATH_TEST - -#include "gtest/gtest-message.h" -#include "gtest/internal/gtest-string.h" -#include "src/gtest-internal-inl.h" - -namespace testing { - -// Constants. - -// The default death test style. -// -// This is defined in internal/gtest-port.h as "fast", but can be overridden by -// a definition in internal/custom/gtest-port.h. The recommended value, which is -// used internally at Google, is "threadsafe". -static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE; - -GTEST_DEFINE_string_( - death_test_style, - internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), - "Indicates how to run a death test in a forked child process: " - "\"threadsafe\" (child process re-executes the test binary " - "from the beginning, running only the specific death test) or " - "\"fast\" (child process runs the death test immediately " - "after forking)."); - -GTEST_DEFINE_bool_( - death_test_use_fork, - internal::BoolFromGTestEnv("death_test_use_fork", false), - "Instructs to use fork()/_exit() instead of clone() in death tests. " - "Ignored and always uses fork() on POSIX systems where clone() is not " - "implemented. Useful when running under valgrind or similar tools if " - "those do not support clone(). Valgrind 3.3.1 will just fail if " - "it sees an unsupported combination of clone() flags. " - "It is not recommended to use this flag w/o valgrind though it will " - "work in 99% of the cases. Once valgrind is fixed, this flag will " - "most likely be removed."); - -namespace internal { -GTEST_DEFINE_string_( - internal_run_death_test, "", - "Indicates the file, line number, temporal index of " - "the single death test to run, and a file descriptor to " - "which a success code may be sent, all separated by " - "the '|' characters. This flag is specified if and only if the " - "current process is a sub-process launched for running a thread-safe " - "death test. FOR INTERNAL USE ONLY."); -} // namespace internal - -#if GTEST_HAS_DEATH_TEST - -namespace internal { - -// Valid only for fast death tests. Indicates the code is running in the -// child process of a fast style death test. -# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA -static bool g_in_fast_death_test_child = false; -# endif - -// Returns a Boolean value indicating whether the caller is currently -// executing in the context of the death test child process. Tools such as -// Valgrind heap checkers may need this to modify their behavior in death -// tests. IMPORTANT: This is an internal utility. Using it may break the -// implementation of death tests. User code MUST NOT use it. -bool InDeathTestChild() { -# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA - - // On Windows and Fuchsia, death tests are thread-safe regardless of the value - // of the death_test_style flag. - return !GTEST_FLAG(internal_run_death_test).empty(); - -# else - - if (GTEST_FLAG(death_test_style) == "threadsafe") - return !GTEST_FLAG(internal_run_death_test).empty(); - else - return g_in_fast_death_test_child; -#endif -} - -} // namespace internal - -// ExitedWithCode constructor. -ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { -} - -// ExitedWithCode function-call operator. -bool ExitedWithCode::operator()(int exit_status) const { -# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA - - return exit_status == exit_code_; - -# else - - return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; - -# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA -} - -# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA -// KilledBySignal constructor. -KilledBySignal::KilledBySignal(int signum) : signum_(signum) { -} - -// KilledBySignal function-call operator. -bool KilledBySignal::operator()(int exit_status) const { -# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_) - { - bool result; - if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) { - return result; - } - } -# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_) - return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; -} -# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA - -namespace internal { - -// Utilities needed for death tests. - -// Generates a textual description of a given exit code, in the format -// specified by wait(2). -static std::string ExitSummary(int exit_code) { - Message m; - -# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA - - m << "Exited with exit status " << exit_code; - -# else - - if (WIFEXITED(exit_code)) { - m << "Exited with exit status " << WEXITSTATUS(exit_code); - } else if (WIFSIGNALED(exit_code)) { - m << "Terminated by signal " << WTERMSIG(exit_code); - } -# ifdef WCOREDUMP - if (WCOREDUMP(exit_code)) { - m << " (core dumped)"; - } -# endif -# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA - - return m.GetString(); -} - -// Returns true if exit_status describes a process that was terminated -// by a signal, or exited normally with a nonzero exit code. -bool ExitedUnsuccessfully(int exit_status) { - return !ExitedWithCode(0)(exit_status); -} - -# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA -// Generates a textual failure message when a death test finds more than -// one thread running, or cannot determine the number of threads, prior -// to executing the given statement. It is the responsibility of the -// caller not to pass a thread_count of 1. -static std::string DeathTestThreadWarning(size_t thread_count) { - Message msg; - msg << "Death tests use fork(), which is unsafe particularly" - << " in a threaded context. For this test, " << GTEST_NAME_ << " "; - if (thread_count == 0) { - msg << "couldn't detect the number of threads."; - } else { - msg << "detected " << thread_count << " threads."; - } - msg << " See " - "https://github.com/google/googletest/blob/master/googletest/docs/" - "advanced.md#death-tests-and-threads" - << " for more explanation and suggested solutions, especially if" - << " this is the last message you see before your test times out."; - return msg.GetString(); -} -# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA - -// Flag characters for reporting a death test that did not die. -static const char kDeathTestLived = 'L'; -static const char kDeathTestReturned = 'R'; -static const char kDeathTestThrew = 'T'; -static const char kDeathTestInternalError = 'I'; - -#if GTEST_OS_FUCHSIA - -// File descriptor used for the pipe in the child process. -static const int kFuchsiaReadPipeFd = 3; - -#endif - -// An enumeration describing all of the possible ways that a death test can -// conclude. DIED means that the process died while executing the test -// code; LIVED means that process lived beyond the end of the test code; -// RETURNED means that the test statement attempted to execute a return -// statement, which is not allowed; THREW means that the test statement -// returned control by throwing an exception. IN_PROGRESS means the test -// has not yet concluded. -enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; - -// Routine for aborting the program which is safe to call from an -// exec-style death test child process, in which case the error -// message is propagated back to the parent process. Otherwise, the -// message is simply printed to stderr. In either case, the program -// then exits with status 1. -static void DeathTestAbort(const std::string& message) { - // On a POSIX system, this function may be called from a threadsafe-style - // death test child process, which operates on a very small stack. Use - // the heap for any additional non-minuscule memory requirements. - const InternalRunDeathTestFlag* const flag = - GetUnitTestImpl()->internal_run_death_test_flag(); - if (flag != nullptr) { - FILE* parent = posix::FDOpen(flag->write_fd(), "w"); - fputc(kDeathTestInternalError, parent); - fprintf(parent, "%s", message.c_str()); - fflush(parent); - _exit(1); - } else { - fprintf(stderr, "%s", message.c_str()); - fflush(stderr); - posix::Abort(); - } -} - -// A replacement for CHECK that calls DeathTestAbort if the assertion -// fails. -# define GTEST_DEATH_TEST_CHECK_(expression) \ - do { \ - if (!::testing::internal::IsTrue(expression)) { \ - DeathTestAbort( \ - ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ - + ::testing::internal::StreamableToString(__LINE__) + ": " \ - + #expression); \ - } \ - } while (::testing::internal::AlwaysFalse()) - -// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for -// evaluating any system call that fulfills two conditions: it must return -// -1 on failure, and set errno to EINTR when it is interrupted and -// should be tried again. The macro expands to a loop that repeatedly -// evaluates the expression as long as it evaluates to -1 and sets -// errno to EINTR. If the expression evaluates to -1 but errno is -// something other than EINTR, DeathTestAbort is called. -# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ - do { \ - int gtest_retval; \ - do { \ - gtest_retval = (expression); \ - } while (gtest_retval == -1 && errno == EINTR); \ - if (gtest_retval == -1) { \ - DeathTestAbort( \ - ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ - + ::testing::internal::StreamableToString(__LINE__) + ": " \ - + #expression + " != -1"); \ - } \ - } while (::testing::internal::AlwaysFalse()) - -// Returns the message describing the last system error in errno. -std::string GetLastErrnoDescription() { - return errno == 0 ? "" : posix::StrError(errno); -} - -// This is called from a death test parent process to read a failure -// message from the death test child process and log it with the FATAL -// severity. On Windows, the message is read from a pipe handle. On other -// platforms, it is read from a file descriptor. -static void FailFromInternalError(int fd) { - Message error; - char buffer[256]; - int num_read; - - do { - while ((num_read = posix::Read(fd, buffer, 255)) > 0) { - buffer[num_read] = '\0'; - error << buffer; - } - } while (num_read == -1 && errno == EINTR); - - if (num_read == 0) { - GTEST_LOG_(FATAL) << error.GetString(); - } else { - const int last_error = errno; - GTEST_LOG_(FATAL) << "Error while reading death test internal: " - << GetLastErrnoDescription() << " [" << last_error << "]"; - } -} - -// Death test constructor. Increments the running death test count -// for the current test. -DeathTest::DeathTest() { - TestInfo* const info = GetUnitTestImpl()->current_test_info(); - if (info == nullptr) { - DeathTestAbort("Cannot run a death test outside of a TEST or " - "TEST_F construct"); - } -} - -// Creates and returns a death test by dispatching to the current -// death test factory. -bool DeathTest::Create(const char* statement, - Matcher matcher, const char* file, - int line, DeathTest** test) { - return GetUnitTestImpl()->death_test_factory()->Create( - statement, std::move(matcher), file, line, test); -} - -const char* DeathTest::LastMessage() { - return last_death_test_message_.c_str(); -} - -void DeathTest::set_last_death_test_message(const std::string& message) { - last_death_test_message_ = message; -} - -std::string DeathTest::last_death_test_message_; - -// Provides cross platform implementation for some death functionality. -class DeathTestImpl : public DeathTest { - protected: - DeathTestImpl(const char* a_statement, Matcher matcher) - : statement_(a_statement), - matcher_(std::move(matcher)), - spawned_(false), - status_(-1), - outcome_(IN_PROGRESS), - read_fd_(-1), - write_fd_(-1) {} - - // read_fd_ is expected to be closed and cleared by a derived class. - ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } - - void Abort(AbortReason reason) override; - bool Passed(bool status_ok) override; - - const char* statement() const { return statement_; } - bool spawned() const { return spawned_; } - void set_spawned(bool is_spawned) { spawned_ = is_spawned; } - int status() const { return status_; } - void set_status(int a_status) { status_ = a_status; } - DeathTestOutcome outcome() const { return outcome_; } - void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } - int read_fd() const { return read_fd_; } - void set_read_fd(int fd) { read_fd_ = fd; } - int write_fd() const { return write_fd_; } - void set_write_fd(int fd) { write_fd_ = fd; } - - // Called in the parent process only. Reads the result code of the death - // test child process via a pipe, interprets it to set the outcome_ - // member, and closes read_fd_. Outputs diagnostics and terminates in - // case of unexpected codes. - void ReadAndInterpretStatusByte(); - - // Returns stderr output from the child process. - virtual std::string GetErrorLogs(); - - private: - // The textual content of the code this object is testing. This class - // doesn't own this string and should not attempt to delete it. - const char* const statement_; - // A matcher that's expected to match the stderr output by the child process. - Matcher matcher_; - // True if the death test child process has been successfully spawned. - bool spawned_; - // The exit status of the child process. - int status_; - // How the death test concluded. - DeathTestOutcome outcome_; - // Descriptor to the read end of the pipe to the child process. It is - // always -1 in the child process. The child keeps its write end of the - // pipe in write_fd_. - int read_fd_; - // Descriptor to the child's write end of the pipe to the parent process. - // It is always -1 in the parent process. The parent keeps its end of the - // pipe in read_fd_. - int write_fd_; -}; - -// Called in the parent process only. Reads the result code of the death -// test child process via a pipe, interprets it to set the outcome_ -// member, and closes read_fd_. Outputs diagnostics and terminates in -// case of unexpected codes. -void DeathTestImpl::ReadAndInterpretStatusByte() { - char flag; - int bytes_read; - - // The read() here blocks until data is available (signifying the - // failure of the death test) or until the pipe is closed (signifying - // its success), so it's okay to call this in the parent before - // the child process has exited. - do { - bytes_read = posix::Read(read_fd(), &flag, 1); - } while (bytes_read == -1 && errno == EINTR); - - if (bytes_read == 0) { - set_outcome(DIED); - } else if (bytes_read == 1) { - switch (flag) { - case kDeathTestReturned: - set_outcome(RETURNED); - break; - case kDeathTestThrew: - set_outcome(THREW); - break; - case kDeathTestLived: - set_outcome(LIVED); - break; - case kDeathTestInternalError: - FailFromInternalError(read_fd()); // Does not return. - break; - default: - GTEST_LOG_(FATAL) << "Death test child process reported " - << "unexpected status byte (" - << static_cast(flag) << ")"; - } - } else { - GTEST_LOG_(FATAL) << "Read from death test child process failed: " - << GetLastErrnoDescription(); - } - GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); - set_read_fd(-1); -} - -std::string DeathTestImpl::GetErrorLogs() { - return GetCapturedStderr(); -} - -// Signals that the death test code which should have exited, didn't. -// Should be called only in a death test child process. -// Writes a status byte to the child's status file descriptor, then -// calls _exit(1). -void DeathTestImpl::Abort(AbortReason reason) { - // The parent process considers the death test to be a failure if - // it finds any data in our pipe. So, here we write a single flag byte - // to the pipe, then exit. - const char status_ch = - reason == TEST_DID_NOT_DIE ? kDeathTestLived : - reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; - - GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); - // We are leaking the descriptor here because on some platforms (i.e., - // when built as Windows DLL), destructors of global objects will still - // run after calling _exit(). On such systems, write_fd_ will be - // indirectly closed from the destructor of UnitTestImpl, causing double - // close if it is also closed here. On debug configurations, double close - // may assert. As there are no in-process buffers to flush here, we are - // relying on the OS to close the descriptor after the process terminates - // when the destructors are not run. - _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) -} - -// Returns an indented copy of stderr output for a death test. -// This makes distinguishing death test output lines from regular log lines -// much easier. -static ::std::string FormatDeathTestOutput(const ::std::string& output) { - ::std::string ret; - for (size_t at = 0; ; ) { - const size_t line_end = output.find('\n', at); - ret += "[ DEATH ] "; - if (line_end == ::std::string::npos) { - ret += output.substr(at); - break; - } - ret += output.substr(at, line_end + 1 - at); - at = line_end + 1; - } - return ret; -} - -// Assesses the success or failure of a death test, using both private -// members which have previously been set, and one argument: -// -// Private data members: -// outcome: An enumeration describing how the death test -// concluded: DIED, LIVED, THREW, or RETURNED. The death test -// fails in the latter three cases. -// status: The exit status of the child process. On *nix, it is in the -// in the format specified by wait(2). On Windows, this is the -// value supplied to the ExitProcess() API or a numeric code -// of the exception that terminated the program. -// matcher_: A matcher that's expected to match the stderr output by the child -// process. -// -// Argument: -// status_ok: true if exit_status is acceptable in the context of -// this particular death test, which fails if it is false -// -// Returns true if and only if all of the above conditions are met. Otherwise, -// the first failing condition, in the order given above, is the one that is -// reported. Also sets the last death test message string. -bool DeathTestImpl::Passed(bool status_ok) { - if (!spawned()) - return false; - - const std::string error_message = GetErrorLogs(); - - bool success = false; - Message buffer; - - buffer << "Death test: " << statement() << "\n"; - switch (outcome()) { - case LIVED: - buffer << " Result: failed to die.\n" - << " Error msg:\n" << FormatDeathTestOutput(error_message); - break; - case THREW: - buffer << " Result: threw an exception.\n" - << " Error msg:\n" << FormatDeathTestOutput(error_message); - break; - case RETURNED: - buffer << " Result: illegal return in test statement.\n" - << " Error msg:\n" << FormatDeathTestOutput(error_message); - break; - case DIED: - if (status_ok) { - if (matcher_.Matches(error_message)) { - success = true; - } else { - std::ostringstream stream; - matcher_.DescribeTo(&stream); - buffer << " Result: died but not with expected error.\n" - << " Expected: " << stream.str() << "\n" - << "Actual msg:\n" - << FormatDeathTestOutput(error_message); - } - } else { - buffer << " Result: died but not with expected exit code:\n" - << " " << ExitSummary(status()) << "\n" - << "Actual msg:\n" << FormatDeathTestOutput(error_message); - } - break; - case IN_PROGRESS: - default: - GTEST_LOG_(FATAL) - << "DeathTest::Passed somehow called before conclusion of test"; - } - - DeathTest::set_last_death_test_message(buffer.GetString()); - return success; -} - -# if GTEST_OS_WINDOWS -// WindowsDeathTest implements death tests on Windows. Due to the -// specifics of starting new processes on Windows, death tests there are -// always threadsafe, and Google Test considers the -// --gtest_death_test_style=fast setting to be equivalent to -// --gtest_death_test_style=threadsafe there. -// -// A few implementation notes: Like the Linux version, the Windows -// implementation uses pipes for child-to-parent communication. But due to -// the specifics of pipes on Windows, some extra steps are required: -// -// 1. The parent creates a communication pipe and stores handles to both -// ends of it. -// 2. The parent starts the child and provides it with the information -// necessary to acquire the handle to the write end of the pipe. -// 3. The child acquires the write end of the pipe and signals the parent -// using a Windows event. -// 4. Now the parent can release the write end of the pipe on its side. If -// this is done before step 3, the object's reference count goes down to -// 0 and it is destroyed, preventing the child from acquiring it. The -// parent now has to release it, or read operations on the read end of -// the pipe will not return when the child terminates. -// 5. The parent reads child's output through the pipe (outcome code and -// any possible error messages) from the pipe, and its stderr and then -// determines whether to fail the test. -// -// Note: to distinguish Win32 API calls from the local method and function -// calls, the former are explicitly resolved in the global namespace. -// -class WindowsDeathTest : public DeathTestImpl { - public: - WindowsDeathTest(const char* a_statement, Matcher matcher, - const char* file, int line) - : DeathTestImpl(a_statement, std::move(matcher)), - file_(file), - line_(line) {} - - // All of these virtual functions are inherited from DeathTest. - virtual int Wait(); - virtual TestRole AssumeRole(); - - private: - // The name of the file in which the death test is located. - const char* const file_; - // The line number on which the death test is located. - const int line_; - // Handle to the write end of the pipe to the child process. - AutoHandle write_handle_; - // Child process handle. - AutoHandle child_handle_; - // Event the child process uses to signal the parent that it has - // acquired the handle to the write end of the pipe. After seeing this - // event the parent can release its own handles to make sure its - // ReadFile() calls return when the child terminates. - AutoHandle event_handle_; -}; - -// Waits for the child in a death test to exit, returning its exit -// status, or 0 if no child process exists. As a side effect, sets the -// outcome data member. -int WindowsDeathTest::Wait() { - if (!spawned()) - return 0; - - // Wait until the child either signals that it has acquired the write end - // of the pipe or it dies. - const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; - switch (::WaitForMultipleObjects(2, - wait_handles, - FALSE, // Waits for any of the handles. - INFINITE)) { - case WAIT_OBJECT_0: - case WAIT_OBJECT_0 + 1: - break; - default: - GTEST_DEATH_TEST_CHECK_(false); // Should not get here. - } - - // The child has acquired the write end of the pipe or exited. - // We release the handle on our side and continue. - write_handle_.Reset(); - event_handle_.Reset(); - - ReadAndInterpretStatusByte(); - - // Waits for the child process to exit if it haven't already. This - // returns immediately if the child has already exited, regardless of - // whether previous calls to WaitForMultipleObjects synchronized on this - // handle or not. - GTEST_DEATH_TEST_CHECK_( - WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), - INFINITE)); - DWORD status_code; - GTEST_DEATH_TEST_CHECK_( - ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); - child_handle_.Reset(); - set_status(static_cast(status_code)); - return status(); -} - -// The AssumeRole process for a Windows death test. It creates a child -// process with the same executable as the current process to run the -// death test. The child process is given the --gtest_filter and -// --gtest_internal_run_death_test flags such that it knows to run the -// current death test only. -DeathTest::TestRole WindowsDeathTest::AssumeRole() { - const UnitTestImpl* const impl = GetUnitTestImpl(); - const InternalRunDeathTestFlag* const flag = - impl->internal_run_death_test_flag(); - const TestInfo* const info = impl->current_test_info(); - const int death_test_index = info->result()->death_test_count(); - - if (flag != nullptr) { - // ParseInternalRunDeathTestFlag() has performed all the necessary - // processing. - set_write_fd(flag->write_fd()); - return EXECUTE_TEST; - } - - // WindowsDeathTest uses an anonymous pipe to communicate results of - // a death test. - SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES), - nullptr, TRUE}; - HANDLE read_handle, write_handle; - GTEST_DEATH_TEST_CHECK_( - ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, - 0) // Default buffer size. - != FALSE); - set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), - O_RDONLY)); - write_handle_.Reset(write_handle); - event_handle_.Reset(::CreateEvent( - &handles_are_inheritable, - TRUE, // The event will automatically reset to non-signaled state. - FALSE, // The initial state is non-signalled. - nullptr)); // The even is unnamed. - GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr); - const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + - kFilterFlag + "=" + info->test_suite_name() + - "." + info->name(); - const std::string internal_flag = - std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + - "=" + file_ + "|" + StreamableToString(line_) + "|" + - StreamableToString(death_test_index) + "|" + - StreamableToString(static_cast(::GetCurrentProcessId())) + - // size_t has the same width as pointers on both 32-bit and 64-bit - // Windows platforms. - // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. - "|" + StreamableToString(reinterpret_cast(write_handle)) + - "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); - - char executable_path[_MAX_PATH + 1]; // NOLINT - GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr, - executable_path, - _MAX_PATH)); - - std::string command_line = - std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + - internal_flag + "\""; - - DeathTest::set_last_death_test_message(""); - - CaptureStderr(); - // Flush the log buffers since the log streams are shared with the child. - FlushInfoLog(); - - // The child process will share the standard handles with the parent. - STARTUPINFOA startup_info; - memset(&startup_info, 0, sizeof(STARTUPINFO)); - startup_info.dwFlags = STARTF_USESTDHANDLES; - startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); - startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); - startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); - - PROCESS_INFORMATION process_info; - GTEST_DEATH_TEST_CHECK_( - ::CreateProcessA( - executable_path, const_cast(command_line.c_str()), - nullptr, // Retuned process handle is not inheritable. - nullptr, // Retuned thread handle is not inheritable. - TRUE, // Child inherits all inheritable handles (for write_handle_). - 0x0, // Default creation flags. - nullptr, // Inherit the parent's environment. - UnitTest::GetInstance()->original_working_dir(), &startup_info, - &process_info) != FALSE); - child_handle_.Reset(process_info.hProcess); - ::CloseHandle(process_info.hThread); - set_spawned(true); - return OVERSEE_TEST; -} - -# elif GTEST_OS_FUCHSIA - -class FuchsiaDeathTest : public DeathTestImpl { - public: - FuchsiaDeathTest(const char* a_statement, Matcher matcher, - const char* file, int line) - : DeathTestImpl(a_statement, std::move(matcher)), - file_(file), - line_(line) {} - - // All of these virtual functions are inherited from DeathTest. - int Wait() override; - TestRole AssumeRole() override; - std::string GetErrorLogs() override; - - private: - // The name of the file in which the death test is located. - const char* const file_; - // The line number on which the death test is located. - const int line_; - // The stderr data captured by the child process. - std::string captured_stderr_; - - zx::process child_process_; - zx::channel exception_channel_; - zx::socket stderr_socket_; -}; - -// Utility class for accumulating command-line arguments. -class Arguments { - public: - Arguments() { args_.push_back(nullptr); } - - ~Arguments() { - for (std::vector::iterator i = args_.begin(); i != args_.end(); - ++i) { - free(*i); - } - } - void AddArgument(const char* argument) { - args_.insert(args_.end() - 1, posix::StrDup(argument)); - } - - template - void AddArguments(const ::std::vector& arguments) { - for (typename ::std::vector::const_iterator i = arguments.begin(); - i != arguments.end(); - ++i) { - args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); - } - } - char* const* Argv() { - return &args_[0]; - } - - int size() { - return args_.size() - 1; - } - - private: - std::vector args_; -}; - -// Waits for the child in a death test to exit, returning its exit -// status, or 0 if no child process exists. As a side effect, sets the -// outcome data member. -int FuchsiaDeathTest::Wait() { - const int kProcessKey = 0; - const int kSocketKey = 1; - const int kExceptionKey = 2; - - if (!spawned()) - return 0; - - // Create a port to wait for socket/task/exception events. - zx_status_t status_zx; - zx::port port; - status_zx = zx::port::create(0, &port); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - - // Register to wait for the child process to terminate. - status_zx = child_process_.wait_async( - port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - - // Register to wait for the socket to be readable or closed. - status_zx = stderr_socket_.wait_async( - port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, - ZX_WAIT_ASYNC_ONCE); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - - // Register to wait for an exception. - status_zx = exception_channel_.wait_async( - port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - - bool process_terminated = false; - bool socket_closed = false; - do { - zx_port_packet_t packet = {}; - status_zx = port.wait(zx::time::infinite(), &packet); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - - if (packet.key == kExceptionKey) { - // Process encountered an exception. Kill it directly rather than - // letting other handlers process the event. We will get a kProcessKey - // event when the process actually terminates. - status_zx = child_process_.kill(); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - } else if (packet.key == kProcessKey) { - // Process terminated. - GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type)); - GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED); - process_terminated = true; - } else if (packet.key == kSocketKey) { - GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type)); - if (packet.signal.observed & ZX_SOCKET_READABLE) { - // Read data from the socket. - constexpr size_t kBufferSize = 1024; - do { - size_t old_length = captured_stderr_.length(); - size_t bytes_read = 0; - captured_stderr_.resize(old_length + kBufferSize); - status_zx = stderr_socket_.read( - 0, &captured_stderr_.front() + old_length, kBufferSize, - &bytes_read); - captured_stderr_.resize(old_length + bytes_read); - } while (status_zx == ZX_OK); - if (status_zx == ZX_ERR_PEER_CLOSED) { - socket_closed = true; - } else { - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT); - status_zx = stderr_socket_.wait_async( - port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, - ZX_WAIT_ASYNC_ONCE); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - } - } else { - GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED); - socket_closed = true; - } - } - } while (!process_terminated && !socket_closed); - - ReadAndInterpretStatusByte(); - - zx_info_process_t buffer; - status_zx = child_process_.get_info( - ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - - GTEST_DEATH_TEST_CHECK_(buffer.exited); - set_status(buffer.return_code); - return status(); -} - -// The AssumeRole process for a Fuchsia death test. It creates a child -// process with the same executable as the current process to run the -// death test. The child process is given the --gtest_filter and -// --gtest_internal_run_death_test flags such that it knows to run the -// current death test only. -DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { - const UnitTestImpl* const impl = GetUnitTestImpl(); - const InternalRunDeathTestFlag* const flag = - impl->internal_run_death_test_flag(); - const TestInfo* const info = impl->current_test_info(); - const int death_test_index = info->result()->death_test_count(); - - if (flag != nullptr) { - // ParseInternalRunDeathTestFlag() has performed all the necessary - // processing. - set_write_fd(kFuchsiaReadPipeFd); - return EXECUTE_TEST; - } - - // Flush the log buffers since the log streams are shared with the child. - FlushInfoLog(); - - // Build the child process command line. - const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + - kFilterFlag + "=" + info->test_suite_name() + - "." + info->name(); - const std::string internal_flag = - std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" - + file_ + "|" - + StreamableToString(line_) + "|" - + StreamableToString(death_test_index); - Arguments args; - args.AddArguments(GetInjectableArgvs()); - args.AddArgument(filter_flag.c_str()); - args.AddArgument(internal_flag.c_str()); - - // Build the pipe for communication with the child. - zx_status_t status; - zx_handle_t child_pipe_handle; - int child_pipe_fd; - status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - set_read_fd(child_pipe_fd); - - // Set the pipe handle for the child. - fdio_spawn_action_t spawn_actions[2] = {}; - fdio_spawn_action_t* add_handle_action = &spawn_actions[0]; - add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE; - add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd); - add_handle_action->h.handle = child_pipe_handle; - - // Create a socket pair will be used to receive the child process' stderr. - zx::socket stderr_producer_socket; - status = - zx::socket::create(0, &stderr_producer_socket, &stderr_socket_); - GTEST_DEATH_TEST_CHECK_(status >= 0); - int stderr_producer_fd = -1; - status = - fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd); - GTEST_DEATH_TEST_CHECK_(status >= 0); - - // Make the stderr socket nonblocking. - GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0); - - fdio_spawn_action_t* add_stderr_action = &spawn_actions[1]; - add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD; - add_stderr_action->fd.local_fd = stderr_producer_fd; - add_stderr_action->fd.target_fd = STDERR_FILENO; - - // Create a child job. - zx_handle_t child_job = ZX_HANDLE_INVALID; - status = zx_job_create(zx_job_default(), 0, & child_job); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - zx_policy_basic_t policy; - policy.condition = ZX_POL_NEW_ANY; - policy.policy = ZX_POL_ACTION_ALLOW; - status = zx_job_set_policy( - child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - - // Create an exception channel attached to the |child_job|, to allow - // us to suppress the system default exception handler from firing. - status = - zx_task_create_exception_channel( - child_job, 0, exception_channel_.reset_and_get_address()); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - - // Spawn the child process. - status = fdio_spawn_etc( - child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr, - 2, spawn_actions, child_process_.reset_and_get_address(), nullptr); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - - set_spawned(true); - return OVERSEE_TEST; -} - -std::string FuchsiaDeathTest::GetErrorLogs() { - return captured_stderr_; -} - -#else // We are neither on Windows, nor on Fuchsia. - -// ForkingDeathTest provides implementations for most of the abstract -// methods of the DeathTest interface. Only the AssumeRole method is -// left undefined. -class ForkingDeathTest : public DeathTestImpl { - public: - ForkingDeathTest(const char* statement, Matcher matcher); - - // All of these virtual functions are inherited from DeathTest. - int Wait() override; - - protected: - void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } - - private: - // PID of child process during death test; 0 in the child process itself. - pid_t child_pid_; -}; - -// Constructs a ForkingDeathTest. -ForkingDeathTest::ForkingDeathTest(const char* a_statement, - Matcher matcher) - : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {} - -// Waits for the child in a death test to exit, returning its exit -// status, or 0 if no child process exists. As a side effect, sets the -// outcome data member. -int ForkingDeathTest::Wait() { - if (!spawned()) - return 0; - - ReadAndInterpretStatusByte(); - - int status_value; - GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); - set_status(status_value); - return status_value; -} - -// A concrete death test class that forks, then immediately runs the test -// in the child process. -class NoExecDeathTest : public ForkingDeathTest { - public: - NoExecDeathTest(const char* a_statement, Matcher matcher) - : ForkingDeathTest(a_statement, std::move(matcher)) {} - TestRole AssumeRole() override; -}; - -// The AssumeRole process for a fork-and-run death test. It implements a -// straightforward fork, with a simple pipe to transmit the status byte. -DeathTest::TestRole NoExecDeathTest::AssumeRole() { - const size_t thread_count = GetThreadCount(); - if (thread_count != 1) { - GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); - } - - int pipe_fd[2]; - GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); - - DeathTest::set_last_death_test_message(""); - CaptureStderr(); - // When we fork the process below, the log file buffers are copied, but the - // file descriptors are shared. We flush all log files here so that closing - // the file descriptors in the child process doesn't throw off the - // synchronization between descriptors and buffers in the parent process. - // This is as close to the fork as possible to avoid a race condition in case - // there are multiple threads running before the death test, and another - // thread writes to the log file. - FlushInfoLog(); - - const pid_t child_pid = fork(); - GTEST_DEATH_TEST_CHECK_(child_pid != -1); - set_child_pid(child_pid); - if (child_pid == 0) { - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); - set_write_fd(pipe_fd[1]); - // Redirects all logging to stderr in the child process to prevent - // concurrent writes to the log files. We capture stderr in the parent - // process and append the child process' output to a log. - LogToStderr(); - // Event forwarding to the listeners of event listener API mush be shut - // down in death test subprocesses. - GetUnitTestImpl()->listeners()->SuppressEventForwarding(); - g_in_fast_death_test_child = true; - return EXECUTE_TEST; - } else { - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); - set_read_fd(pipe_fd[0]); - set_spawned(true); - return OVERSEE_TEST; - } -} - -// A concrete death test class that forks and re-executes the main -// program from the beginning, with command-line flags set that cause -// only this specific death test to be run. -class ExecDeathTest : public ForkingDeathTest { - public: - ExecDeathTest(const char* a_statement, Matcher matcher, - const char* file, int line) - : ForkingDeathTest(a_statement, std::move(matcher)), - file_(file), - line_(line) {} - TestRole AssumeRole() override; - - private: - static ::std::vector GetArgvsForDeathTestChildProcess() { - ::std::vector args = GetInjectableArgvs(); -# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) - ::std::vector extra_args = - GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_(); - args.insert(args.end(), extra_args.begin(), extra_args.end()); -# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) - return args; - } - // The name of the file in which the death test is located. - const char* const file_; - // The line number on which the death test is located. - const int line_; -}; - -// Utility class for accumulating command-line arguments. -class Arguments { - public: - Arguments() { args_.push_back(nullptr); } - - ~Arguments() { - for (std::vector::iterator i = args_.begin(); i != args_.end(); - ++i) { - free(*i); - } - } - void AddArgument(const char* argument) { - args_.insert(args_.end() - 1, posix::StrDup(argument)); - } - - template - void AddArguments(const ::std::vector& arguments) { - for (typename ::std::vector::const_iterator i = arguments.begin(); - i != arguments.end(); - ++i) { - args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); - } - } - char* const* Argv() { - return &args_[0]; - } - - private: - std::vector args_; -}; - -// A struct that encompasses the arguments to the child process of a -// threadsafe-style death test process. -struct ExecDeathTestArgs { - char* const* argv; // Command-line arguments for the child's call to exec - int close_fd; // File descriptor to close; the read end of a pipe -}; - -# if GTEST_OS_MAC -inline char** GetEnviron() { - // When Google Test is built as a framework on MacOS X, the environ variable - // is unavailable. Apple's documentation (man environ) recommends using - // _NSGetEnviron() instead. - return *_NSGetEnviron(); -} -# else -// Some POSIX platforms expect you to declare environ. extern "C" makes -// it reside in the global namespace. -extern "C" char** environ; -inline char** GetEnviron() { return environ; } -# endif // GTEST_OS_MAC - -# if !GTEST_OS_QNX -// The main function for a threadsafe-style death test child process. -// This function is called in a clone()-ed process and thus must avoid -// any potentially unsafe operations like malloc or libc functions. -static int ExecDeathTestChildMain(void* child_arg) { - ExecDeathTestArgs* const args = static_cast(child_arg); - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); - - // We need to execute the test program in the same environment where - // it was originally invoked. Therefore we change to the original - // working directory first. - const char* const original_dir = - UnitTest::GetInstance()->original_working_dir(); - // We can safely call chdir() as it's a direct system call. - if (chdir(original_dir) != 0) { - DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + - GetLastErrnoDescription()); - return EXIT_FAILURE; - } - - // We can safely call execve() as it's a direct system call. We - // cannot use execvp() as it's a libc function and thus potentially - // unsafe. Since execve() doesn't search the PATH, the user must - // invoke the test program via a valid path that contains at least - // one path separator. - execve(args->argv[0], args->argv, GetEnviron()); - DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + - original_dir + " failed: " + - GetLastErrnoDescription()); - return EXIT_FAILURE; -} -# endif // !GTEST_OS_QNX - -# if GTEST_HAS_CLONE -// Two utility routines that together determine the direction the stack -// grows. -// This could be accomplished more elegantly by a single recursive -// function, but we want to guard against the unlikely possibility of -// a smart compiler optimizing the recursion away. -// -// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining -// StackLowerThanAddress into StackGrowsDown, which then doesn't give -// correct answer. -static void StackLowerThanAddress(const void* ptr, - bool* result) GTEST_NO_INLINE_; -// HWAddressSanitizer add a random tag to the MSB of the local variable address, -// making comparison result unpredictable. -GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -static void StackLowerThanAddress(const void* ptr, bool* result) { - int dummy; - *result = (&dummy < ptr); -} - -// Make sure AddressSanitizer does not tamper with the stack here. -GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -static bool StackGrowsDown() { - int dummy = 0; - bool result; - StackLowerThanAddress(&dummy, &result); - return result; -} -# endif // GTEST_HAS_CLONE - -// Spawns a child process with the same executable as the current process in -// a thread-safe manner and instructs it to run the death test. The -// implementation uses fork(2) + exec. On systems where clone(2) is -// available, it is used instead, being slightly more thread-safe. On QNX, -// fork supports only single-threaded environments, so this function uses -// spawn(2) there instead. The function dies with an error message if -// anything goes wrong. -static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { - ExecDeathTestArgs args = { argv, close_fd }; - pid_t child_pid = -1; - -# if GTEST_OS_QNX - // Obtains the current directory and sets it to be closed in the child - // process. - const int cwd_fd = open(".", O_RDONLY); - GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); - GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); - // We need to execute the test program in the same environment where - // it was originally invoked. Therefore we change to the original - // working directory first. - const char* const original_dir = - UnitTest::GetInstance()->original_working_dir(); - // We can safely call chdir() as it's a direct system call. - if (chdir(original_dir) != 0) { - DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + - GetLastErrnoDescription()); - return EXIT_FAILURE; - } - - int fd_flags; - // Set close_fd to be closed after spawn. - GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); - GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, - fd_flags | FD_CLOEXEC)); - struct inheritance inherit = {0}; - // spawn is a system call. - child_pid = - spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron()); - // Restores the current working directory. - GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); - -# else // GTEST_OS_QNX -# if GTEST_OS_LINUX - // When a SIGPROF signal is received while fork() or clone() are executing, - // the process may hang. To avoid this, we ignore SIGPROF here and re-enable - // it after the call to fork()/clone() is complete. - struct sigaction saved_sigprof_action; - struct sigaction ignore_sigprof_action; - memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); - sigemptyset(&ignore_sigprof_action.sa_mask); - ignore_sigprof_action.sa_handler = SIG_IGN; - GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( - SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); -# endif // GTEST_OS_LINUX - -# if GTEST_HAS_CLONE - const bool use_fork = GTEST_FLAG(death_test_use_fork); - - if (!use_fork) { - static const bool stack_grows_down = StackGrowsDown(); - const auto stack_size = static_cast(getpagesize()); - // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. - void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); - GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); - - // Maximum stack alignment in bytes: For a downward-growing stack, this - // amount is subtracted from size of the stack space to get an address - // that is within the stack space and is aligned on all systems we care - // about. As far as I know there is no ABI with stack alignment greater - // than 64. We assume stack and stack_size already have alignment of - // kMaxStackAlignment. - const size_t kMaxStackAlignment = 64; - void* const stack_top = - static_cast(stack) + - (stack_grows_down ? stack_size - kMaxStackAlignment : 0); - GTEST_DEATH_TEST_CHECK_( - static_cast(stack_size) > kMaxStackAlignment && - reinterpret_cast(stack_top) % kMaxStackAlignment == 0); - - child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); - - GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); - } -# else - const bool use_fork = true; -# endif // GTEST_HAS_CLONE - - if (use_fork && (child_pid = fork()) == 0) { - ExecDeathTestChildMain(&args); - _exit(0); - } -# endif // GTEST_OS_QNX -# if GTEST_OS_LINUX - GTEST_DEATH_TEST_CHECK_SYSCALL_( - sigaction(SIGPROF, &saved_sigprof_action, nullptr)); -# endif // GTEST_OS_LINUX - - GTEST_DEATH_TEST_CHECK_(child_pid != -1); - return child_pid; -} - -// The AssumeRole process for a fork-and-exec death test. It re-executes the -// main program from the beginning, setting the --gtest_filter -// and --gtest_internal_run_death_test flags to cause only the current -// death test to be re-run. -DeathTest::TestRole ExecDeathTest::AssumeRole() { - const UnitTestImpl* const impl = GetUnitTestImpl(); - const InternalRunDeathTestFlag* const flag = - impl->internal_run_death_test_flag(); - const TestInfo* const info = impl->current_test_info(); - const int death_test_index = info->result()->death_test_count(); - - if (flag != nullptr) { - set_write_fd(flag->write_fd()); - return EXECUTE_TEST; - } - - int pipe_fd[2]; - GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); - // Clear the close-on-exec flag on the write end of the pipe, lest - // it be closed when the child process does an exec: - GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); - - const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + - kFilterFlag + "=" + info->test_suite_name() + - "." + info->name(); - const std::string internal_flag = - std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" - + file_ + "|" + StreamableToString(line_) + "|" - + StreamableToString(death_test_index) + "|" - + StreamableToString(pipe_fd[1]); - Arguments args; - args.AddArguments(GetArgvsForDeathTestChildProcess()); - args.AddArgument(filter_flag.c_str()); - args.AddArgument(internal_flag.c_str()); - - DeathTest::set_last_death_test_message(""); - - CaptureStderr(); - // See the comment in NoExecDeathTest::AssumeRole for why the next line - // is necessary. - FlushInfoLog(); - - const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); - set_child_pid(child_pid); - set_read_fd(pipe_fd[0]); - set_spawned(true); - return OVERSEE_TEST; -} - -# endif // !GTEST_OS_WINDOWS - -// Creates a concrete DeathTest-derived class that depends on the -// --gtest_death_test_style flag, and sets the pointer pointed to -// by the "test" argument to its address. If the test should be -// skipped, sets that pointer to NULL. Returns true, unless the -// flag is set to an invalid value. -bool DefaultDeathTestFactory::Create(const char* statement, - Matcher matcher, - const char* file, int line, - DeathTest** test) { - UnitTestImpl* const impl = GetUnitTestImpl(); - const InternalRunDeathTestFlag* const flag = - impl->internal_run_death_test_flag(); - const int death_test_index = impl->current_test_info() - ->increment_death_test_count(); - - if (flag != nullptr) { - if (death_test_index > flag->index()) { - DeathTest::set_last_death_test_message( - "Death test count (" + StreamableToString(death_test_index) - + ") somehow exceeded expected maximum (" - + StreamableToString(flag->index()) + ")"); - return false; - } - - if (!(flag->file() == file && flag->line() == line && - flag->index() == death_test_index)) { - *test = nullptr; - return true; - } - } - -# if GTEST_OS_WINDOWS - - if (GTEST_FLAG(death_test_style) == "threadsafe" || - GTEST_FLAG(death_test_style) == "fast") { - *test = new WindowsDeathTest(statement, std::move(matcher), file, line); - } - -# elif GTEST_OS_FUCHSIA - - if (GTEST_FLAG(death_test_style) == "threadsafe" || - GTEST_FLAG(death_test_style) == "fast") { - *test = new FuchsiaDeathTest(statement, std::move(matcher), file, line); - } - -# else - - if (GTEST_FLAG(death_test_style) == "threadsafe") { - *test = new ExecDeathTest(statement, std::move(matcher), file, line); - } else if (GTEST_FLAG(death_test_style) == "fast") { - *test = new NoExecDeathTest(statement, std::move(matcher)); - } - -# endif // GTEST_OS_WINDOWS - - else { // NOLINT - this is more readable than unbalanced brackets inside #if. - DeathTest::set_last_death_test_message( - "Unknown death test style \"" + GTEST_FLAG(death_test_style) - + "\" encountered"); - return false; - } - - return true; -} - -# if GTEST_OS_WINDOWS -// Recreates the pipe and event handles from the provided parameters, -// signals the event, and returns a file descriptor wrapped around the pipe -// handle. This function is called in the child process only. -static int GetStatusFileDescriptor(unsigned int parent_process_id, - size_t write_handle_as_size_t, - size_t event_handle_as_size_t) { - AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, - FALSE, // Non-inheritable. - parent_process_id)); - if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { - DeathTestAbort("Unable to open parent process " + - StreamableToString(parent_process_id)); - } - - GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); - - const HANDLE write_handle = - reinterpret_cast(write_handle_as_size_t); - HANDLE dup_write_handle; - - // The newly initialized handle is accessible only in the parent - // process. To obtain one accessible within the child, we need to use - // DuplicateHandle. - if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, - ::GetCurrentProcess(), &dup_write_handle, - 0x0, // Requested privileges ignored since - // DUPLICATE_SAME_ACCESS is used. - FALSE, // Request non-inheritable handler. - DUPLICATE_SAME_ACCESS)) { - DeathTestAbort("Unable to duplicate the pipe handle " + - StreamableToString(write_handle_as_size_t) + - " from the parent process " + - StreamableToString(parent_process_id)); - } - - const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); - HANDLE dup_event_handle; - - if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, - ::GetCurrentProcess(), &dup_event_handle, - 0x0, - FALSE, - DUPLICATE_SAME_ACCESS)) { - DeathTestAbort("Unable to duplicate the event handle " + - StreamableToString(event_handle_as_size_t) + - " from the parent process " + - StreamableToString(parent_process_id)); - } - - const int write_fd = - ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); - if (write_fd == -1) { - DeathTestAbort("Unable to convert pipe handle " + - StreamableToString(write_handle_as_size_t) + - " to a file descriptor"); - } - - // Signals the parent that the write end of the pipe has been acquired - // so the parent can release its own write end. - ::SetEvent(dup_event_handle); - - return write_fd; -} -# endif // GTEST_OS_WINDOWS - -// Returns a newly created InternalRunDeathTestFlag object with fields -// initialized from the GTEST_FLAG(internal_run_death_test) flag if -// the flag is specified; otherwise returns NULL. -InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { - if (GTEST_FLAG(internal_run_death_test) == "") return nullptr; - - // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we - // can use it here. - int line = -1; - int index = -1; - ::std::vector< ::std::string> fields; - SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); - int write_fd = -1; - -# if GTEST_OS_WINDOWS - - unsigned int parent_process_id = 0; - size_t write_handle_as_size_t = 0; - size_t event_handle_as_size_t = 0; - - if (fields.size() != 6 - || !ParseNaturalNumber(fields[1], &line) - || !ParseNaturalNumber(fields[2], &index) - || !ParseNaturalNumber(fields[3], &parent_process_id) - || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) - || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { - DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + - GTEST_FLAG(internal_run_death_test)); - } - write_fd = GetStatusFileDescriptor(parent_process_id, - write_handle_as_size_t, - event_handle_as_size_t); - -# elif GTEST_OS_FUCHSIA - - if (fields.size() != 3 - || !ParseNaturalNumber(fields[1], &line) - || !ParseNaturalNumber(fields[2], &index)) { - DeathTestAbort("Bad --gtest_internal_run_death_test flag: " - + GTEST_FLAG(internal_run_death_test)); - } - -# else - - if (fields.size() != 4 - || !ParseNaturalNumber(fields[1], &line) - || !ParseNaturalNumber(fields[2], &index) - || !ParseNaturalNumber(fields[3], &write_fd)) { - DeathTestAbort("Bad --gtest_internal_run_death_test flag: " - + GTEST_FLAG(internal_run_death_test)); - } - -# endif // GTEST_OS_WINDOWS - - return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); -} - -} // namespace internal - -#endif // GTEST_HAS_DEATH_TEST - -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-filepath.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-filepath.cc deleted file mode 100644 index bd7b99ff03e..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-filepath.cc +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -#include "gtest/internal/gtest-filepath.h" - -#include -#include "gtest/internal/gtest-port.h" -#include "gtest/gtest-message.h" - -#if GTEST_OS_WINDOWS_MOBILE -# include -#elif GTEST_OS_WINDOWS -# include -# include -#else -# include -# include // Some Linux distributions define PATH_MAX here. -#endif // GTEST_OS_WINDOWS_MOBILE - -#include "gtest/internal/gtest-string.h" - -#if GTEST_OS_WINDOWS -# define GTEST_PATH_MAX_ _MAX_PATH -#elif defined(PATH_MAX) -# define GTEST_PATH_MAX_ PATH_MAX -#elif defined(_XOPEN_PATH_MAX) -# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX -#else -# define GTEST_PATH_MAX_ _POSIX_PATH_MAX -#endif // GTEST_OS_WINDOWS - -namespace testing { -namespace internal { - -#if GTEST_OS_WINDOWS -// On Windows, '\\' is the standard path separator, but many tools and the -// Windows API also accept '/' as an alternate path separator. Unless otherwise -// noted, a file path can contain either kind of path separators, or a mixture -// of them. -const char kPathSeparator = '\\'; -const char kAlternatePathSeparator = '/'; -const char kAlternatePathSeparatorString[] = "/"; -# if GTEST_OS_WINDOWS_MOBILE -// Windows CE doesn't have a current directory. You should not use -// the current directory in tests on Windows CE, but this at least -// provides a reasonable fallback. -const char kCurrentDirectoryString[] = "\\"; -// Windows CE doesn't define INVALID_FILE_ATTRIBUTES -const DWORD kInvalidFileAttributes = 0xffffffff; -# else -const char kCurrentDirectoryString[] = ".\\"; -# endif // GTEST_OS_WINDOWS_MOBILE -#else -const char kPathSeparator = '/'; -const char kCurrentDirectoryString[] = "./"; -#endif // GTEST_OS_WINDOWS - -// Returns whether the given character is a valid path separator. -static bool IsPathSeparator(char c) { -#if GTEST_HAS_ALT_PATH_SEP_ - return (c == kPathSeparator) || (c == kAlternatePathSeparator); -#else - return c == kPathSeparator; -#endif -} - -// Returns the current working directory, or "" if unsuccessful. -FilePath FilePath::GetCurrentDir() { -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ - GTEST_OS_WINDOWS_RT || ARDUINO || defined(ESP_PLATFORM) - // These platforms do not have a current directory, so we just return - // something reasonable. - return FilePath(kCurrentDirectoryString); -#elif GTEST_OS_WINDOWS - char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; - return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd); -#else - char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; - char* result = getcwd(cwd, sizeof(cwd)); -# if GTEST_OS_NACL - // getcwd will likely fail in NaCl due to the sandbox, so return something - // reasonable. The user may have provided a shim implementation for getcwd, - // however, so fallback only when failure is detected. - return FilePath(result == nullptr ? kCurrentDirectoryString : cwd); -# endif // GTEST_OS_NACL - return FilePath(result == nullptr ? "" : cwd); -#endif // GTEST_OS_WINDOWS_MOBILE -} - -// Returns a copy of the FilePath with the case-insensitive extension removed. -// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns -// FilePath("dir/file"). If a case-insensitive extension is not -// found, returns a copy of the original FilePath. -FilePath FilePath::RemoveExtension(const char* extension) const { - const std::string dot_extension = std::string(".") + extension; - if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { - return FilePath(pathname_.substr( - 0, pathname_.length() - dot_extension.length())); - } - return *this; -} - -// Returns a pointer to the last occurrence of a valid path separator in -// the FilePath. On Windows, for example, both '/' and '\' are valid path -// separators. Returns NULL if no path separator was found. -const char* FilePath::FindLastPathSeparator() const { - const char* const last_sep = strrchr(c_str(), kPathSeparator); -#if GTEST_HAS_ALT_PATH_SEP_ - const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); - // Comparing two pointers of which only one is NULL is undefined. - if (last_alt_sep != nullptr && - (last_sep == nullptr || last_alt_sep > last_sep)) { - return last_alt_sep; - } -#endif - return last_sep; -} - -// Returns a copy of the FilePath with the directory part removed. -// Example: FilePath("path/to/file").RemoveDirectoryName() returns -// FilePath("file"). If there is no directory part ("just_a_file"), it returns -// the FilePath unmodified. If there is no file part ("just_a_dir/") it -// returns an empty FilePath (""). -// On Windows platform, '\' is the path separator, otherwise it is '/'. -FilePath FilePath::RemoveDirectoryName() const { - const char* const last_sep = FindLastPathSeparator(); - return last_sep ? FilePath(last_sep + 1) : *this; -} - -// RemoveFileName returns the directory path with the filename removed. -// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". -// If the FilePath is "a_file" or "/a_file", RemoveFileName returns -// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does -// not have a file, like "just/a/dir/", it returns the FilePath unmodified. -// On Windows platform, '\' is the path separator, otherwise it is '/'. -FilePath FilePath::RemoveFileName() const { - const char* const last_sep = FindLastPathSeparator(); - std::string dir; - if (last_sep) { - dir = std::string(c_str(), static_cast(last_sep + 1 - c_str())); - } else { - dir = kCurrentDirectoryString; - } - return FilePath(dir); -} - -// Helper functions for naming files in a directory for xml output. - -// Given directory = "dir", base_name = "test", number = 0, -// extension = "xml", returns "dir/test.xml". If number is greater -// than zero (e.g., 12), returns "dir/test_12.xml". -// On Windows platform, uses \ as the separator rather than /. -FilePath FilePath::MakeFileName(const FilePath& directory, - const FilePath& base_name, - int number, - const char* extension) { - std::string file; - if (number == 0) { - file = base_name.string() + "." + extension; - } else { - file = base_name.string() + "_" + StreamableToString(number) - + "." + extension; - } - return ConcatPaths(directory, FilePath(file)); -} - -// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". -// On Windows, uses \ as the separator rather than /. -FilePath FilePath::ConcatPaths(const FilePath& directory, - const FilePath& relative_path) { - if (directory.IsEmpty()) - return relative_path; - const FilePath dir(directory.RemoveTrailingPathSeparator()); - return FilePath(dir.string() + kPathSeparator + relative_path.string()); -} - -// Returns true if pathname describes something findable in the file-system, -// either a file, directory, or whatever. -bool FilePath::FileOrDirectoryExists() const { -#if GTEST_OS_WINDOWS_MOBILE - LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); - const DWORD attributes = GetFileAttributes(unicode); - delete [] unicode; - return attributes != kInvalidFileAttributes; -#else - posix::StatStruct file_stat; - return posix::Stat(pathname_.c_str(), &file_stat) == 0; -#endif // GTEST_OS_WINDOWS_MOBILE -} - -// Returns true if pathname describes a directory in the file-system -// that exists. -bool FilePath::DirectoryExists() const { - bool result = false; -#if GTEST_OS_WINDOWS - // Don't strip off trailing separator if path is a root directory on - // Windows (like "C:\\"). - const FilePath& path(IsRootDirectory() ? *this : - RemoveTrailingPathSeparator()); -#else - const FilePath& path(*this); -#endif - -#if GTEST_OS_WINDOWS_MOBILE - LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); - const DWORD attributes = GetFileAttributes(unicode); - delete [] unicode; - if ((attributes != kInvalidFileAttributes) && - (attributes & FILE_ATTRIBUTE_DIRECTORY)) { - result = true; - } -#else - posix::StatStruct file_stat; - result = posix::Stat(path.c_str(), &file_stat) == 0 && - posix::IsDir(file_stat); -#endif // GTEST_OS_WINDOWS_MOBILE - - return result; -} - -// Returns true if pathname describes a root directory. (Windows has one -// root directory per disk drive.) -bool FilePath::IsRootDirectory() const { -#if GTEST_OS_WINDOWS - return pathname_.length() == 3 && IsAbsolutePath(); -#else - return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); -#endif -} - -// Returns true if pathname describes an absolute path. -bool FilePath::IsAbsolutePath() const { - const char* const name = pathname_.c_str(); -#if GTEST_OS_WINDOWS - return pathname_.length() >= 3 && - ((name[0] >= 'a' && name[0] <= 'z') || - (name[0] >= 'A' && name[0] <= 'Z')) && - name[1] == ':' && - IsPathSeparator(name[2]); -#else - return IsPathSeparator(name[0]); -#endif -} - -// Returns a pathname for a file that does not currently exist. The pathname -// will be directory/base_name.extension or -// directory/base_name_.extension if directory/base_name.extension -// already exists. The number will be incremented until a pathname is found -// that does not already exist. -// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. -// There could be a race condition if two or more processes are calling this -// function at the same time -- they could both pick the same filename. -FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, - const FilePath& base_name, - const char* extension) { - FilePath full_pathname; - int number = 0; - do { - full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); - } while (full_pathname.FileOrDirectoryExists()); - return full_pathname; -} - -// Returns true if FilePath ends with a path separator, which indicates that -// it is intended to represent a directory. Returns false otherwise. -// This does NOT check that a directory (or file) actually exists. -bool FilePath::IsDirectory() const { - return !pathname_.empty() && - IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); -} - -// Create directories so that path exists. Returns true if successful or if -// the directories already exist; returns false if unable to create directories -// for any reason. -bool FilePath::CreateDirectoriesRecursively() const { - if (!this->IsDirectory()) { - return false; - } - - if (pathname_.length() == 0 || this->DirectoryExists()) { - return true; - } - - const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); - return parent.CreateDirectoriesRecursively() && this->CreateFolder(); -} - -// Create the directory so that path exists. Returns true if successful or -// if the directory already exists; returns false if unable to create the -// directory for any reason, including if the parent directory does not -// exist. Not named "CreateDirectory" because that's a macro on Windows. -bool FilePath::CreateFolder() const { -#if GTEST_OS_WINDOWS_MOBILE - FilePath removed_sep(this->RemoveTrailingPathSeparator()); - LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); - int result = CreateDirectory(unicode, nullptr) ? 0 : -1; - delete [] unicode; -#elif GTEST_OS_WINDOWS - int result = _mkdir(pathname_.c_str()); -#else - int result = mkdir(pathname_.c_str(), 0777); -#endif // GTEST_OS_WINDOWS_MOBILE - - if (result == -1) { - return this->DirectoryExists(); // An error is OK if the directory exists. - } - return true; // No error. -} - -// If input name has a trailing separator character, remove it and return the -// name, otherwise return the name string unmodified. -// On Windows platform, uses \ as the separator, other platforms use /. -FilePath FilePath::RemoveTrailingPathSeparator() const { - return IsDirectory() - ? FilePath(pathname_.substr(0, pathname_.length() - 1)) - : *this; -} - -// Removes any redundant separators that might be in the pathname. -// For example, "bar///foo" becomes "bar/foo". Does not eliminate other -// redundancies that might be in a pathname involving "." or "..". -void FilePath::Normalize() { - if (pathname_.c_str() == nullptr) { - pathname_ = ""; - return; - } - const char* src = pathname_.c_str(); - char* const dest = new char[pathname_.length() + 1]; - char* dest_ptr = dest; - memset(dest_ptr, 0, pathname_.length() + 1); - - while (*src != '\0') { - *dest_ptr = *src; - if (!IsPathSeparator(*src)) { - src++; - } else { -#if GTEST_HAS_ALT_PATH_SEP_ - if (*dest_ptr == kAlternatePathSeparator) { - *dest_ptr = kPathSeparator; - } -#endif - while (IsPathSeparator(*src)) - src++; - } - dest_ptr++; - } - *dest_ptr = '\0'; - pathname_ = dest; - delete[] dest; -} - -} // namespace internal -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-internal-inl.h b/Sofa/framework/Testing/extlibs/gtest/src/gtest-internal-inl.h deleted file mode 100644 index 8ed70daab09..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-internal-inl.h +++ /dev/null @@ -1,1211 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// Utility functions and classes used by the Google C++ testing framework.// -// This file contains purely Google Test's internal implementation. Please -// DO NOT #INCLUDE IT IN A USER PROGRAM. - -#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ -#define GTEST_SRC_GTEST_INTERNAL_INL_H_ - -#ifndef _WIN32_WCE -# include -#endif // !_WIN32_WCE -#include -#include // For strtoll/_strtoul64/malloc/free. -#include // For memmove. - -#include -#include -#include -#include - -#include "gtest/internal/gtest-port.h" - -#if GTEST_CAN_STREAM_RESULTS_ -# include // NOLINT -# include // NOLINT -#endif - -#if GTEST_OS_WINDOWS -# include // NOLINT -#endif // GTEST_OS_WINDOWS - -#include "gtest/gtest.h" -#include "gtest/gtest-spi.h" - -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ -/* class A needs to have dll-interface to be used by clients of class B */) - -namespace testing { - -// Declares the flags. -// -// We don't want the users to modify this flag in the code, but want -// Google Test's own unit tests to be able to access it. Therefore we -// declare it here as opposed to in gtest.h. -GTEST_DECLARE_bool_(death_test_use_fork); - -namespace internal { - -// The value of GetTestTypeId() as seen from within the Google Test -// library. This is solely for testing GetTestTypeId(). -GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; - -// Names of the flags (needed for parsing Google Test flags). -const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; -const char kBreakOnFailureFlag[] = "break_on_failure"; -const char kCatchExceptionsFlag[] = "catch_exceptions"; -const char kColorFlag[] = "color"; -const char kFilterFlag[] = "filter"; -const char kListTestsFlag[] = "list_tests"; -const char kOutputFlag[] = "output"; -const char kPrintTimeFlag[] = "print_time"; -const char kPrintUTF8Flag[] = "print_utf8"; -const char kRandomSeedFlag[] = "random_seed"; -const char kRepeatFlag[] = "repeat"; -const char kShuffleFlag[] = "shuffle"; -const char kStackTraceDepthFlag[] = "stack_trace_depth"; -const char kStreamResultToFlag[] = "stream_result_to"; -const char kThrowOnFailureFlag[] = "throw_on_failure"; -const char kFlagfileFlag[] = "flagfile"; - -// A valid random seed must be in [1, kMaxRandomSeed]. -const int kMaxRandomSeed = 99999; - -// g_help_flag is true if and only if the --help flag or an equivalent form -// is specified on the command line. -GTEST_API_ extern bool g_help_flag; - -// Returns the current time in milliseconds. -GTEST_API_ TimeInMillis GetTimeInMillis(); - -// Returns true if and only if Google Test should use colors in the output. -GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); - -// Formats the given time in milliseconds as seconds. -GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); - -// Converts the given time in milliseconds to a date string in the ISO 8601 -// format, without the timezone information. N.B.: due to the use the -// non-reentrant localtime() function, this function is not thread safe. Do -// not use it in any code that can be called from multiple threads. -GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); - -// Parses a string for an Int32 flag, in the form of "--flag=value". -// -// On success, stores the value of the flag in *value, and returns -// true. On failure, returns false without changing *value. -GTEST_API_ bool ParseInt32Flag( - const char* str, const char* flag, Int32* value); - -// Returns a random seed in range [1, kMaxRandomSeed] based on the -// given --gtest_random_seed flag value. -inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { - const unsigned int raw_seed = (random_seed_flag == 0) ? - static_cast(GetTimeInMillis()) : - static_cast(random_seed_flag); - - // Normalizes the actual seed to range [1, kMaxRandomSeed] such that - // it's easy to type. - const int normalized_seed = - static_cast((raw_seed - 1U) % - static_cast(kMaxRandomSeed)) + 1; - return normalized_seed; -} - -// Returns the first valid random seed after 'seed'. The behavior is -// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is -// considered to be 1. -inline int GetNextRandomSeed(int seed) { - GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) - << "Invalid random seed " << seed << " - must be in [1, " - << kMaxRandomSeed << "]."; - const int next_seed = seed + 1; - return (next_seed > kMaxRandomSeed) ? 1 : next_seed; -} - -// This class saves the values of all Google Test flags in its c'tor, and -// restores them in its d'tor. -class GTestFlagSaver { - public: - // The c'tor. - GTestFlagSaver() { - also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); - break_on_failure_ = GTEST_FLAG(break_on_failure); - catch_exceptions_ = GTEST_FLAG(catch_exceptions); - color_ = GTEST_FLAG(color); - death_test_style_ = GTEST_FLAG(death_test_style); - death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); - filter_ = GTEST_FLAG(filter); - internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); - list_tests_ = GTEST_FLAG(list_tests); - output_ = GTEST_FLAG(output); - print_time_ = GTEST_FLAG(print_time); - print_utf8_ = GTEST_FLAG(print_utf8); - random_seed_ = GTEST_FLAG(random_seed); - repeat_ = GTEST_FLAG(repeat); - shuffle_ = GTEST_FLAG(shuffle); - stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); - stream_result_to_ = GTEST_FLAG(stream_result_to); - throw_on_failure_ = GTEST_FLAG(throw_on_failure); - } - - // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. - ~GTestFlagSaver() { - GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; - GTEST_FLAG(break_on_failure) = break_on_failure_; - GTEST_FLAG(catch_exceptions) = catch_exceptions_; - GTEST_FLAG(color) = color_; - GTEST_FLAG(death_test_style) = death_test_style_; - GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; - GTEST_FLAG(filter) = filter_; - GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; - GTEST_FLAG(list_tests) = list_tests_; - GTEST_FLAG(output) = output_; - GTEST_FLAG(print_time) = print_time_; - GTEST_FLAG(print_utf8) = print_utf8_; - GTEST_FLAG(random_seed) = random_seed_; - GTEST_FLAG(repeat) = repeat_; - GTEST_FLAG(shuffle) = shuffle_; - GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; - GTEST_FLAG(stream_result_to) = stream_result_to_; - GTEST_FLAG(throw_on_failure) = throw_on_failure_; - } - - private: - // Fields for saving the original values of flags. - bool also_run_disabled_tests_; - bool break_on_failure_; - bool catch_exceptions_; - std::string color_; - std::string death_test_style_; - bool death_test_use_fork_; - std::string filter_; - std::string internal_run_death_test_; - bool list_tests_; - std::string output_; - bool print_time_; - bool print_utf8_; - internal::Int32 random_seed_; - internal::Int32 repeat_; - bool shuffle_; - internal::Int32 stack_trace_depth_; - std::string stream_result_to_; - bool throw_on_failure_; -} GTEST_ATTRIBUTE_UNUSED_; - -// Converts a Unicode code point to a narrow string in UTF-8 encoding. -// code_point parameter is of type UInt32 because wchar_t may not be -// wide enough to contain a code point. -// If the code_point is not a valid Unicode code point -// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted -// to "(Invalid Unicode 0xXXXXXXXX)". -GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); - -// Converts a wide string to a narrow string in UTF-8 encoding. -// The wide string is assumed to have the following encoding: -// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin) -// UTF-32 if sizeof(wchar_t) == 4 (on Linux) -// Parameter str points to a null-terminated wide string. -// Parameter num_chars may additionally limit the number -// of wchar_t characters processed. -1 is used when the entire string -// should be processed. -// If the string contains code points that are not valid Unicode code points -// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output -// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding -// and contains invalid UTF-16 surrogate pairs, values in those pairs -// will be encoded as individual Unicode characters from Basic Normal Plane. -GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); - -// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file -// if the variable is present. If a file already exists at this location, this -// function will write over it. If the variable is present, but the file cannot -// be created, prints an error and exits. -void WriteToShardStatusFileIfNeeded(); - -// Checks whether sharding is enabled by examining the relevant -// environment variable values. If the variables are present, -// but inconsistent (e.g., shard_index >= total_shards), prints -// an error and exits. If in_subprocess_for_death_test, sharding is -// disabled because it must only be applied to the original test -// process. Otherwise, we could filter out death tests we intended to execute. -GTEST_API_ bool ShouldShard(const char* total_shards_str, - const char* shard_index_str, - bool in_subprocess_for_death_test); - -// Parses the environment variable var as an Int32. If it is unset, -// returns default_val. If it is not an Int32, prints an error and -// and aborts. -GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); - -// Given the total number of shards, the shard index, and the test id, -// returns true if and only if the test should be run on this shard. The test id -// is some arbitrary but unique non-negative integer assigned to each test -// method. Assumes that 0 <= shard_index < total_shards. -GTEST_API_ bool ShouldRunTestOnShard( - int total_shards, int shard_index, int test_id); - -// STL container utilities. - -// Returns the number of elements in the given container that satisfy -// the given predicate. -template -inline int CountIf(const Container& c, Predicate predicate) { - // Implemented as an explicit loop since std::count_if() in libCstd on - // Solaris has a non-standard signature. - int count = 0; - for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { - if (predicate(*it)) - ++count; - } - return count; -} - -// Applies a function/functor to each element in the container. -template -void ForEach(const Container& c, Functor functor) { - std::for_each(c.begin(), c.end(), functor); -} - -// Returns the i-th element of the vector, or default_value if i is not -// in range [0, v.size()). -template -inline E GetElementOr(const std::vector& v, int i, E default_value) { - return (i < 0 || i >= static_cast(v.size())) ? default_value - : v[static_cast(i)]; -} - -// Performs an in-place shuffle of a range of the vector's elements. -// 'begin' and 'end' are element indices as an STL-style range; -// i.e. [begin, end) are shuffled, where 'end' == size() means to -// shuffle to the end of the vector. -template -void ShuffleRange(internal::Random* random, int begin, int end, - std::vector* v) { - const int size = static_cast(v->size()); - GTEST_CHECK_(0 <= begin && begin <= size) - << "Invalid shuffle range start " << begin << ": must be in range [0, " - << size << "]."; - GTEST_CHECK_(begin <= end && end <= size) - << "Invalid shuffle range finish " << end << ": must be in range [" - << begin << ", " << size << "]."; - - // Fisher-Yates shuffle, from - // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle - for (int range_width = end - begin; range_width >= 2; range_width--) { - const int last_in_range = begin + range_width - 1; - const int selected = - begin + - static_cast(random->Generate(static_cast(range_width))); - std::swap((*v)[static_cast(selected)], - (*v)[static_cast(last_in_range)]); - } -} - -// Performs an in-place shuffle of the vector's elements. -template -inline void Shuffle(internal::Random* random, std::vector* v) { - ShuffleRange(random, 0, static_cast(v->size()), v); -} - -// A function for deleting an object. Handy for being used as a -// functor. -template -static void Delete(T* x) { - delete x; -} - -// A predicate that checks the key of a TestProperty against a known key. -// -// TestPropertyKeyIs is copyable. -class TestPropertyKeyIs { - public: - // Constructor. - // - // TestPropertyKeyIs has NO default constructor. - explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} - - // Returns true if and only if the test name of test property matches on key_. - bool operator()(const TestProperty& test_property) const { - return test_property.key() == key_; - } - - private: - std::string key_; -}; - -// Class UnitTestOptions. -// -// This class contains functions for processing options the user -// specifies when running the tests. It has only static members. -// -// In most cases, the user can specify an option using either an -// environment variable or a command line flag. E.g. you can set the -// test filter using either GTEST_FILTER or --gtest_filter. If both -// the variable and the flag are present, the latter overrides the -// former. -class GTEST_API_ UnitTestOptions { - public: - // Functions for processing the gtest_output flag. - - // Returns the output format, or "" for normal printed output. - static std::string GetOutputFormat(); - - // Returns the absolute path of the requested output file, or the - // default (test_detail.xml in the original working directory) if - // none was explicitly specified. - static std::string GetAbsolutePathToOutputFile(); - - // Functions for processing the gtest_filter flag. - - // Returns true if and only if the wildcard pattern matches the string. - // The first ':' or '\0' character in pattern marks the end of it. - // - // This recursive algorithm isn't very efficient, but is clear and - // works well enough for matching test names, which are short. - static bool PatternMatchesString(const char *pattern, const char *str); - - // Returns true if and only if the user-specified filter matches the test - // suite name and the test name. - static bool FilterMatchesTest(const std::string& test_suite_name, - const std::string& test_name); - -#if GTEST_OS_WINDOWS - // Function for supporting the gtest_catch_exception flag. - - // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the - // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. - // This function is useful as an __except condition. - static int GTestShouldProcessSEH(DWORD exception_code); -#endif // GTEST_OS_WINDOWS - - // Returns true if "name" matches the ':' separated list of glob-style - // filters in "filter". - static bool MatchesFilter(const std::string& name, const char* filter); -}; - -// Returns the current application's name, removing directory path if that -// is present. Used by UnitTestOptions::GetOutputFile. -GTEST_API_ FilePath GetCurrentExecutableName(); - -// The role interface for getting the OS stack trace as a string. -class OsStackTraceGetterInterface { - public: - OsStackTraceGetterInterface() {} - virtual ~OsStackTraceGetterInterface() {} - - // Returns the current OS stack trace as an std::string. Parameters: - // - // max_depth - the maximum number of stack frames to be included - // in the trace. - // skip_count - the number of top frames to be skipped; doesn't count - // against max_depth. - virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0; - - // UponLeavingGTest() should be called immediately before Google Test calls - // user code. It saves some information about the current stack that - // CurrentStackTrace() will use to find and hide Google Test stack frames. - virtual void UponLeavingGTest() = 0; - - // This string is inserted in place of stack frames that are part of - // Google Test's implementation. - static const char* const kElidedFramesMarker; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); -}; - -// A working implementation of the OsStackTraceGetterInterface interface. -class OsStackTraceGetter : public OsStackTraceGetterInterface { - public: - OsStackTraceGetter() {} - - std::string CurrentStackTrace(int max_depth, int skip_count) override; - void UponLeavingGTest() override; - - private: -#if GTEST_HAS_ABSL - Mutex mutex_; // Protects all internal state. - - // We save the stack frame below the frame that calls user code. - // We do this because the address of the frame immediately below - // the user code changes between the call to UponLeavingGTest() - // and any calls to the stack trace code from within the user code. - void* caller_frame_ = nullptr; -#endif // GTEST_HAS_ABSL - - GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); -}; - -// Information about a Google Test trace point. -struct TraceInfo { - const char* file; - int line; - std::string message; -}; - -// This is the default global test part result reporter used in UnitTestImpl. -// This class should only be used by UnitTestImpl. -class DefaultGlobalTestPartResultReporter - : public TestPartResultReporterInterface { - public: - explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); - // Implements the TestPartResultReporterInterface. Reports the test part - // result in the current test. - void ReportTestPartResult(const TestPartResult& result) override; - - private: - UnitTestImpl* const unit_test_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); -}; - -// This is the default per thread test part result reporter used in -// UnitTestImpl. This class should only be used by UnitTestImpl. -class DefaultPerThreadTestPartResultReporter - : public TestPartResultReporterInterface { - public: - explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); - // Implements the TestPartResultReporterInterface. The implementation just - // delegates to the current global test part result reporter of *unit_test_. - void ReportTestPartResult(const TestPartResult& result) override; - - private: - UnitTestImpl* const unit_test_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); -}; - -// The private implementation of the UnitTest class. We don't protect -// the methods under a mutex, as this class is not accessible by a -// user and the UnitTest class that delegates work to this class does -// proper locking. -class GTEST_API_ UnitTestImpl { - public: - explicit UnitTestImpl(UnitTest* parent); - virtual ~UnitTestImpl(); - - // There are two different ways to register your own TestPartResultReporter. - // You can register your own repoter to listen either only for test results - // from the current thread or for results from all threads. - // By default, each per-thread test result repoter just passes a new - // TestPartResult to the global test result reporter, which registers the - // test part result for the currently running test. - - // Returns the global test part result reporter. - TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); - - // Sets the global test part result reporter. - void SetGlobalTestPartResultReporter( - TestPartResultReporterInterface* reporter); - - // Returns the test part result reporter for the current thread. - TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); - - // Sets the test part result reporter for the current thread. - void SetTestPartResultReporterForCurrentThread( - TestPartResultReporterInterface* reporter); - - // Gets the number of successful test suites. - int successful_test_suite_count() const; - - // Gets the number of failed test suites. - int failed_test_suite_count() const; - - // Gets the number of all test suites. - int total_test_suite_count() const; - - // Gets the number of all test suites that contain at least one test - // that should run. - int test_suite_to_run_count() const; - - // Gets the number of successful tests. - int successful_test_count() const; - - // Gets the number of skipped tests. - int skipped_test_count() const; - - // Gets the number of failed tests. - int failed_test_count() const; - - // Gets the number of disabled tests that will be reported in the XML report. - int reportable_disabled_test_count() const; - - // Gets the number of disabled tests. - int disabled_test_count() const; - - // Gets the number of tests to be printed in the XML report. - int reportable_test_count() const; - - // Gets the number of all tests. - int total_test_count() const; - - // Gets the number of tests that should run. - int test_to_run_count() const; - - // Gets the time of the test program start, in ms from the start of the - // UNIX epoch. - TimeInMillis start_timestamp() const { return start_timestamp_; } - - // Gets the elapsed time, in milliseconds. - TimeInMillis elapsed_time() const { return elapsed_time_; } - - // Returns true if and only if the unit test passed (i.e. all test suites - // passed). - bool Passed() const { return !Failed(); } - - // Returns true if and only if the unit test failed (i.e. some test suite - // failed or something outside of all tests failed). - bool Failed() const { - return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed(); - } - - // Gets the i-th test suite among all the test suites. i can range from 0 to - // total_test_suite_count() - 1. If i is not in that range, returns NULL. - const TestSuite* GetTestSuite(int i) const { - const int index = GetElementOr(test_suite_indices_, i, -1); - return index < 0 ? nullptr : test_suites_[static_cast(i)]; - } - - // Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - const TestCase* GetTestCase(int i) const { return GetTestSuite(i); } -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Gets the i-th test suite among all the test suites. i can range from 0 to - // total_test_suite_count() - 1. If i is not in that range, returns NULL. - TestSuite* GetMutableSuiteCase(int i) { - const int index = GetElementOr(test_suite_indices_, i, -1); - return index < 0 ? nullptr : test_suites_[static_cast(index)]; - } - - // Provides access to the event listener list. - TestEventListeners* listeners() { return &listeners_; } - - // Returns the TestResult for the test that's currently running, or - // the TestResult for the ad hoc test if no test is running. - TestResult* current_test_result(); - - // Returns the TestResult for the ad hoc test. - const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } - - // Sets the OS stack trace getter. - // - // Does nothing if the input and the current OS stack trace getter - // are the same; otherwise, deletes the old getter and makes the - // input the current getter. - void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); - - // Returns the current OS stack trace getter if it is not NULL; - // otherwise, creates an OsStackTraceGetter, makes it the current - // getter, and returns it. - OsStackTraceGetterInterface* os_stack_trace_getter(); - - // Returns the current OS stack trace as an std::string. - // - // The maximum number of stack frames to be included is specified by - // the gtest_stack_trace_depth flag. The skip_count parameter - // specifies the number of top frames to be skipped, which doesn't - // count against the number of frames to be included. - // - // For example, if Foo() calls Bar(), which in turn calls - // CurrentOsStackTraceExceptTop(1), Foo() will be included in the - // trace but Bar() and CurrentOsStackTraceExceptTop() won't. - std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; - - // Finds and returns a TestSuite with the given name. If one doesn't - // exist, creates one and returns it. - // - // Arguments: - // - // test_suite_name: name of the test suite - // type_param: the name of the test's type parameter, or NULL if - // this is not a typed or a type-parameterized test. - // set_up_tc: pointer to the function that sets up the test suite - // tear_down_tc: pointer to the function that tears down the test suite - TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param, - internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc); - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - TestCase* GetTestCase(const char* test_case_name, const char* type_param, - internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc) { - return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc); - } -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - // Adds a TestInfo to the unit test. - // - // Arguments: - // - // set_up_tc: pointer to the function that sets up the test suite - // tear_down_tc: pointer to the function that tears down the test suite - // test_info: the TestInfo object - void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc, - TestInfo* test_info) { - // In order to support thread-safe death tests, we need to - // remember the original working directory when the test program - // was first invoked. We cannot do this in RUN_ALL_TESTS(), as - // the user may have changed the current directory before calling - // RUN_ALL_TESTS(). Therefore we capture the current directory in - // AddTestInfo(), which is called to register a TEST or TEST_F - // before main() is reached. - if (original_working_dir_.IsEmpty()) { - original_working_dir_.Set(FilePath::GetCurrentDir()); - GTEST_CHECK_(!original_working_dir_.IsEmpty()) - << "Failed to get the current working directory."; - } - - GetTestSuite(test_info->test_suite_name(), test_info->type_param(), - set_up_tc, tear_down_tc) - ->AddTestInfo(test_info); - } - - // Returns ParameterizedTestSuiteRegistry object used to keep track of - // value-parameterized tests and instantiate and register them. - internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() { - return parameterized_test_registry_; - } - - // Sets the TestSuite object for the test that's currently running. - void set_current_test_suite(TestSuite* a_current_test_suite) { - current_test_suite_ = a_current_test_suite; - } - - // Sets the TestInfo object for the test that's currently running. If - // current_test_info is NULL, the assertion results will be stored in - // ad_hoc_test_result_. - void set_current_test_info(TestInfo* a_current_test_info) { - current_test_info_ = a_current_test_info; - } - - // Registers all parameterized tests defined using TEST_P and - // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter - // combination. This method can be called more then once; it has guards - // protecting from registering the tests more then once. If - // value-parameterized tests are disabled, RegisterParameterizedTests is - // present but does nothing. - void RegisterParameterizedTests(); - - // Runs all tests in this UnitTest object, prints the result, and - // returns true if all tests are successful. If any exception is - // thrown during a test, this test is considered to be failed, but - // the rest of the tests will still be run. - bool RunAllTests(); - - // Clears the results of all tests, except the ad hoc tests. - void ClearNonAdHocTestResult() { - ForEach(test_suites_, TestSuite::ClearTestSuiteResult); - } - - // Clears the results of ad-hoc test assertions. - void ClearAdHocTestResult() { - ad_hoc_test_result_.Clear(); - } - - // Adds a TestProperty to the current TestResult object when invoked in a - // context of a test or a test suite, or to the global property set. If the - // result already contains a property with the same key, the value will be - // updated. - void RecordProperty(const TestProperty& test_property); - - enum ReactionToSharding { - HONOR_SHARDING_PROTOCOL, - IGNORE_SHARDING_PROTOCOL - }; - - // Matches the full name of each test against the user-specified - // filter to decide whether the test should run, then records the - // result in each TestSuite and TestInfo object. - // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests - // based on sharding variables in the environment. - // Returns the number of tests that should run. - int FilterTests(ReactionToSharding shard_tests); - - // Prints the names of the tests matching the user-specified filter flag. - void ListTestsMatchingFilter(); - - const TestSuite* current_test_suite() const { return current_test_suite_; } - TestInfo* current_test_info() { return current_test_info_; } - const TestInfo* current_test_info() const { return current_test_info_; } - - // Returns the vector of environments that need to be set-up/torn-down - // before/after the tests are run. - std::vector& environments() { return environments_; } - - // Getters for the per-thread Google Test trace stack. - std::vector& gtest_trace_stack() { - return *(gtest_trace_stack_.pointer()); - } - const std::vector& gtest_trace_stack() const { - return gtest_trace_stack_.get(); - } - -#if GTEST_HAS_DEATH_TEST - void InitDeathTestSubprocessControlInfo() { - internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); - } - // Returns a pointer to the parsed --gtest_internal_run_death_test - // flag, or NULL if that flag was not specified. - // This information is useful only in a death test child process. - // Must not be called before a call to InitGoogleTest. - const InternalRunDeathTestFlag* internal_run_death_test_flag() const { - return internal_run_death_test_flag_.get(); - } - - // Returns a pointer to the current death test factory. - internal::DeathTestFactory* death_test_factory() { - return death_test_factory_.get(); - } - - void SuppressTestEventsIfInSubprocess(); - - friend class ReplaceDeathTestFactory; -#endif // GTEST_HAS_DEATH_TEST - - // Initializes the event listener performing XML output as specified by - // UnitTestOptions. Must not be called before InitGoogleTest. - void ConfigureXmlOutput(); - -#if GTEST_CAN_STREAM_RESULTS_ - // Initializes the event listener for streaming test results to a socket. - // Must not be called before InitGoogleTest. - void ConfigureStreamingOutput(); -#endif - - // Performs initialization dependent upon flag values obtained in - // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to - // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest - // this function is also called from RunAllTests. Since this function can be - // called more than once, it has to be idempotent. - void PostFlagParsingInit(); - - // Gets the random seed used at the start of the current test iteration. - int random_seed() const { return random_seed_; } - - // Gets the random number generator. - internal::Random* random() { return &random_; } - - // Shuffles all test suites, and the tests within each test suite, - // making sure that death tests are still run first. - void ShuffleTests(); - - // Restores the test suites and tests to their order before the first shuffle. - void UnshuffleTests(); - - // Returns the value of GTEST_FLAG(catch_exceptions) at the moment - // UnitTest::Run() starts. - bool catch_exceptions() const { return catch_exceptions_; } - - private: - friend class ::testing::UnitTest; - - // Used by UnitTest::Run() to capture the state of - // GTEST_FLAG(catch_exceptions) at the moment it starts. - void set_catch_exceptions(bool value) { catch_exceptions_ = value; } - - // The UnitTest object that owns this implementation object. - UnitTest* const parent_; - - // The working directory when the first TEST() or TEST_F() was - // executed. - internal::FilePath original_working_dir_; - - // The default test part result reporters. - DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; - DefaultPerThreadTestPartResultReporter - default_per_thread_test_part_result_reporter_; - - // Points to (but doesn't own) the global test part result reporter. - TestPartResultReporterInterface* global_test_part_result_repoter_; - - // Protects read and write access to global_test_part_result_reporter_. - internal::Mutex global_test_part_result_reporter_mutex_; - - // Points to (but doesn't own) the per-thread test part result reporter. - internal::ThreadLocal - per_thread_test_part_result_reporter_; - - // The vector of environments that need to be set-up/torn-down - // before/after the tests are run. - std::vector environments_; - - // The vector of TestSuites in their original order. It owns the - // elements in the vector. - std::vector test_suites_; - - // Provides a level of indirection for the test suite list to allow - // easy shuffling and restoring the test suite order. The i-th - // element of this vector is the index of the i-th test suite in the - // shuffled order. - std::vector test_suite_indices_; - - // ParameterizedTestRegistry object used to register value-parameterized - // tests. - internal::ParameterizedTestSuiteRegistry parameterized_test_registry_; - - // Indicates whether RegisterParameterizedTests() has been called already. - bool parameterized_tests_registered_; - - // Index of the last death test suite registered. Initially -1. - int last_death_test_suite_; - - // This points to the TestSuite for the currently running test. It - // changes as Google Test goes through one test suite after another. - // When no test is running, this is set to NULL and Google Test - // stores assertion results in ad_hoc_test_result_. Initially NULL. - TestSuite* current_test_suite_; - - // This points to the TestInfo for the currently running test. It - // changes as Google Test goes through one test after another. When - // no test is running, this is set to NULL and Google Test stores - // assertion results in ad_hoc_test_result_. Initially NULL. - TestInfo* current_test_info_; - - // Normally, a user only writes assertions inside a TEST or TEST_F, - // or inside a function called by a TEST or TEST_F. Since Google - // Test keeps track of which test is current running, it can - // associate such an assertion with the test it belongs to. - // - // If an assertion is encountered when no TEST or TEST_F is running, - // Google Test attributes the assertion result to an imaginary "ad hoc" - // test, and records the result in ad_hoc_test_result_. - TestResult ad_hoc_test_result_; - - // The list of event listeners that can be used to track events inside - // Google Test. - TestEventListeners listeners_; - - // The OS stack trace getter. Will be deleted when the UnitTest - // object is destructed. By default, an OsStackTraceGetter is used, - // but the user can set this field to use a custom getter if that is - // desired. - OsStackTraceGetterInterface* os_stack_trace_getter_; - - // True if and only if PostFlagParsingInit() has been called. - bool post_flag_parse_init_performed_; - - // The random number seed used at the beginning of the test run. - int random_seed_; - - // Our random number generator. - internal::Random random_; - - // The time of the test program start, in ms from the start of the - // UNIX epoch. - TimeInMillis start_timestamp_; - - // How long the test took to run, in milliseconds. - TimeInMillis elapsed_time_; - -#if GTEST_HAS_DEATH_TEST - // The decomposed components of the gtest_internal_run_death_test flag, - // parsed when RUN_ALL_TESTS is called. - std::unique_ptr internal_run_death_test_flag_; - std::unique_ptr death_test_factory_; -#endif // GTEST_HAS_DEATH_TEST - - // A per-thread stack of traces created by the SCOPED_TRACE() macro. - internal::ThreadLocal > gtest_trace_stack_; - - // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() - // starts. - bool catch_exceptions_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); -}; // class UnitTestImpl - -// Convenience function for accessing the global UnitTest -// implementation object. -inline UnitTestImpl* GetUnitTestImpl() { - return UnitTest::GetInstance()->impl(); -} - -#if GTEST_USES_SIMPLE_RE - -// Internal helper functions for implementing the simple regular -// expression matcher. -GTEST_API_ bool IsInSet(char ch, const char* str); -GTEST_API_ bool IsAsciiDigit(char ch); -GTEST_API_ bool IsAsciiPunct(char ch); -GTEST_API_ bool IsRepeat(char ch); -GTEST_API_ bool IsAsciiWhiteSpace(char ch); -GTEST_API_ bool IsAsciiWordChar(char ch); -GTEST_API_ bool IsValidEscape(char ch); -GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); -GTEST_API_ bool ValidateRegex(const char* regex); -GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); -GTEST_API_ bool MatchRepetitionAndRegexAtHead( - bool escaped, char ch, char repeat, const char* regex, const char* str); -GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); - -#endif // GTEST_USES_SIMPLE_RE - -// Parses the command line for Google Test flags, without initializing -// other parts of Google Test. -GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); -GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); - -#if GTEST_HAS_DEATH_TEST - -// Returns the message describing the last system error, regardless of the -// platform. -GTEST_API_ std::string GetLastErrnoDescription(); - -// Attempts to parse a string into a positive integer pointed to by the -// number parameter. Returns true if that is possible. -// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use -// it here. -template -bool ParseNaturalNumber(const ::std::string& str, Integer* number) { - // Fail fast if the given string does not begin with a digit; - // this bypasses strtoXXX's "optional leading whitespace and plus - // or minus sign" semantics, which are undesirable here. - if (str.empty() || !IsDigit(str[0])) { - return false; - } - errno = 0; - - char* end; - // BiggestConvertible is the largest integer type that system-provided - // string-to-number conversion routines can return. - -# if GTEST_OS_WINDOWS && !defined(__GNUC__) - - // MSVC and C++ Builder define __int64 instead of the standard long long. - typedef unsigned __int64 BiggestConvertible; - const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); - -# else - - typedef unsigned long long BiggestConvertible; // NOLINT - const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); - -# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) - - const bool parse_success = *end == '\0' && errno == 0; - - GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); - - const Integer result = static_cast(parsed); - if (parse_success && static_cast(result) == parsed) { - *number = result; - return true; - } - return false; -} -#endif // GTEST_HAS_DEATH_TEST - -// TestResult contains some private methods that should be hidden from -// Google Test user but are required for testing. This class allow our tests -// to access them. -// -// This class is supplied only for the purpose of testing Google Test's own -// constructs. Do not use it in user tests, either directly or indirectly. -class TestResultAccessor { - public: - static void RecordProperty(TestResult* test_result, - const std::string& xml_element, - const TestProperty& property) { - test_result->RecordProperty(xml_element, property); - } - - static void ClearTestPartResults(TestResult* test_result) { - test_result->ClearTestPartResults(); - } - - static const std::vector& test_part_results( - const TestResult& test_result) { - return test_result.test_part_results(); - } -}; - -#if GTEST_CAN_STREAM_RESULTS_ - -// Streams test results to the given port on the given host machine. -class StreamingListener : public EmptyTestEventListener { - public: - // Abstract base class for writing strings to a socket. - class AbstractSocketWriter { - public: - virtual ~AbstractSocketWriter() {} - - // Sends a string to the socket. - virtual void Send(const std::string& message) = 0; - - // Closes the socket. - virtual void CloseConnection() {} - - // Sends a string and a newline to the socket. - void SendLn(const std::string& message) { Send(message + "\n"); } - }; - - // Concrete class for actually writing strings to a socket. - class SocketWriter : public AbstractSocketWriter { - public: - SocketWriter(const std::string& host, const std::string& port) - : sockfd_(-1), host_name_(host), port_num_(port) { - MakeConnection(); - } - - ~SocketWriter() override { - if (sockfd_ != -1) - CloseConnection(); - } - - // Sends a string to the socket. - void Send(const std::string& message) override { - GTEST_CHECK_(sockfd_ != -1) - << "Send() can be called only when there is a connection."; - - const auto len = static_cast(message.length()); - if (write(sockfd_, message.c_str(), len) != static_cast(len)) { - GTEST_LOG_(WARNING) - << "stream_result_to: failed to stream to " - << host_name_ << ":" << port_num_; - } - } - - private: - // Creates a client socket and connects to the server. - void MakeConnection(); - - // Closes the socket. - void CloseConnection() override { - GTEST_CHECK_(sockfd_ != -1) - << "CloseConnection() can be called only when there is a connection."; - - close(sockfd_); - sockfd_ = -1; - } - - int sockfd_; // socket file descriptor - const std::string host_name_; - const std::string port_num_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); - }; // class SocketWriter - - // Escapes '=', '&', '%', and '\n' characters in str as "%xx". - static std::string UrlEncode(const char* str); - - StreamingListener(const std::string& host, const std::string& port) - : socket_writer_(new SocketWriter(host, port)) { - Start(); - } - - explicit StreamingListener(AbstractSocketWriter* socket_writer) - : socket_writer_(socket_writer) { Start(); } - - void OnTestProgramStart(const UnitTest& /* unit_test */) override { - SendLn("event=TestProgramStart"); - } - - void OnTestProgramEnd(const UnitTest& unit_test) override { - // Note that Google Test current only report elapsed time for each - // test iteration, not for the entire test program. - SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); - - // Notify the streaming server to stop. - socket_writer_->CloseConnection(); - } - - void OnTestIterationStart(const UnitTest& /* unit_test */, - int iteration) override { - SendLn("event=TestIterationStart&iteration=" + - StreamableToString(iteration)); - } - - void OnTestIterationEnd(const UnitTest& unit_test, - int /* iteration */) override { - SendLn("event=TestIterationEnd&passed=" + - FormatBool(unit_test.Passed()) + "&elapsed_time=" + - StreamableToString(unit_test.elapsed_time()) + "ms"); - } - - // Note that "event=TestCaseStart" is a wire format and has to remain - // "case" for compatibilty - void OnTestCaseStart(const TestCase& test_case) override { - SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); - } - - // Note that "event=TestCaseEnd" is a wire format and has to remain - // "case" for compatibilty - void OnTestCaseEnd(const TestCase& test_case) override { - SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + - "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + - "ms"); - } - - void OnTestStart(const TestInfo& test_info) override { - SendLn(std::string("event=TestStart&name=") + test_info.name()); - } - - void OnTestEnd(const TestInfo& test_info) override { - SendLn("event=TestEnd&passed=" + - FormatBool((test_info.result())->Passed()) + - "&elapsed_time=" + - StreamableToString((test_info.result())->elapsed_time()) + "ms"); - } - - void OnTestPartResult(const TestPartResult& test_part_result) override { - const char* file_name = test_part_result.file_name(); - if (file_name == nullptr) file_name = ""; - SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + - "&line=" + StreamableToString(test_part_result.line_number()) + - "&message=" + UrlEncode(test_part_result.message())); - } - - private: - // Sends the given message and a newline to the socket. - void SendLn(const std::string& message) { socket_writer_->SendLn(message); } - - // Called at the start of streaming to notify the receiver what - // protocol we are using. - void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } - - std::string FormatBool(bool value) { return value ? "1" : "0"; } - - const std::unique_ptr socket_writer_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); -}; // class StreamingListener - -#endif // GTEST_CAN_STREAM_RESULTS_ - -} // namespace internal -} // namespace testing - -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 - -#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-matchers.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-matchers.cc deleted file mode 100644 index 7d2fb6851ec..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-matchers.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2007, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// The Google C++ Testing and Mocking Framework (Google Test) -// -// This file implements just enough of the matcher interface to allow -// EXPECT_DEATH and friends to accept a matcher argument. - -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-port.h" -#include "gtest/gtest-matchers.h" - -#include - -namespace testing { - -// Constructs a matcher that matches a const std::string& whose value is -// equal to s. -Matcher::Matcher(const std::string& s) { *this = Eq(s); } - -// Constructs a matcher that matches a const std::string& whose value is -// equal to s. -Matcher::Matcher(const char* s) { - *this = Eq(std::string(s)); -} - -// Constructs a matcher that matches a std::string whose value is equal to -// s. -Matcher::Matcher(const std::string& s) { *this = Eq(s); } - -// Constructs a matcher that matches a std::string whose value is equal to -// s. -Matcher::Matcher(const char* s) { *this = Eq(std::string(s)); } - -#if GTEST_HAS_ABSL -// Constructs a matcher that matches a const absl::string_view& whose value is -// equal to s. -Matcher::Matcher(const std::string& s) { - *this = Eq(s); -} - -// Constructs a matcher that matches a const absl::string_view& whose value is -// equal to s. -Matcher::Matcher(const char* s) { - *this = Eq(std::string(s)); -} - -// Constructs a matcher that matches a const absl::string_view& whose value is -// equal to s. -Matcher::Matcher(absl::string_view s) { - *this = Eq(std::string(s)); -} - -// Constructs a matcher that matches a absl::string_view whose value is equal to -// s. -Matcher::Matcher(const std::string& s) { *this = Eq(s); } - -// Constructs a matcher that matches a absl::string_view whose value is equal to -// s. -Matcher::Matcher(const char* s) { - *this = Eq(std::string(s)); -} - -// Constructs a matcher that matches a absl::string_view whose value is equal to -// s. -Matcher::Matcher(absl::string_view s) { - *this = Eq(std::string(s)); -} -#endif // GTEST_HAS_ABSL - -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-port.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-port.cc deleted file mode 100644 index fc5ba6becc5..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-port.cc +++ /dev/null @@ -1,1399 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -#include "gtest/internal/gtest-port.h" - -#include -#include -#include -#include -#include -#include - -#if GTEST_OS_WINDOWS -# include -# include -# include -# include // Used in ThreadLocal. -# ifdef _MSC_VER -# include -# endif // _MSC_VER -#else -# include -#endif // GTEST_OS_WINDOWS - -#if GTEST_OS_MAC -# include -# include -# include -#endif // GTEST_OS_MAC - -#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ - GTEST_OS_NETBSD || GTEST_OS_OPENBSD -# include -# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD -# include -# endif -#endif - -#if GTEST_OS_QNX -# include -# include -# include -#endif // GTEST_OS_QNX - -#if GTEST_OS_AIX -# include -# include -#endif // GTEST_OS_AIX - -#if GTEST_OS_FUCHSIA -# include -# include -#endif // GTEST_OS_FUCHSIA - -#include "gtest/gtest-spi.h" -#include "gtest/gtest-message.h" -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-string.h" -#include "src/gtest-internal-inl.h" - -namespace testing { -namespace internal { - -#if defined(_MSC_VER) || defined(__BORLANDC__) -// MSVC and C++Builder do not provide a definition of STDERR_FILENO. -const int kStdOutFileno = 1; -const int kStdErrFileno = 2; -#else -const int kStdOutFileno = STDOUT_FILENO; -const int kStdErrFileno = STDERR_FILENO; -#endif // _MSC_VER - -#if GTEST_OS_LINUX - -namespace { -template -T ReadProcFileField(const std::string& filename, int field) { - std::string dummy; - std::ifstream file(filename.c_str()); - while (field-- > 0) { - file >> dummy; - } - T output = 0; - file >> output; - return output; -} -} // namespace - -// Returns the number of active threads, or 0 when there is an error. -size_t GetThreadCount() { - const std::string filename = - (Message() << "/proc/" << getpid() << "/stat").GetString(); - return ReadProcFileField(filename, 19); -} - -#elif GTEST_OS_MAC - -size_t GetThreadCount() { - const task_t task = mach_task_self(); - mach_msg_type_number_t thread_count; - thread_act_array_t thread_list; - const kern_return_t status = task_threads(task, &thread_list, &thread_count); - if (status == KERN_SUCCESS) { - // task_threads allocates resources in thread_list and we need to free them - // to avoid leaks. - vm_deallocate(task, - reinterpret_cast(thread_list), - sizeof(thread_t) * thread_count); - return static_cast(thread_count); - } else { - return 0; - } -} - -#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ - GTEST_OS_NETBSD - -#if GTEST_OS_NETBSD -#undef KERN_PROC -#define KERN_PROC KERN_PROC2 -#define kinfo_proc kinfo_proc2 -#endif - -#if GTEST_OS_DRAGONFLY -#define KP_NLWP(kp) (kp.kp_nthreads) -#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD -#define KP_NLWP(kp) (kp.ki_numthreads) -#elif GTEST_OS_NETBSD -#define KP_NLWP(kp) (kp.p_nlwps) -#endif - -// Returns the number of threads running in the process, or 0 to indicate that -// we cannot detect it. -size_t GetThreadCount() { - int mib[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID, - getpid(), -#if GTEST_OS_NETBSD - sizeof(struct kinfo_proc), - 1, -#endif - }; - u_int miblen = sizeof(mib) / sizeof(mib[0]); - struct kinfo_proc info; - size_t size = sizeof(info); - if (sysctl(mib, miblen, &info, &size, NULL, 0)) { - return 0; - } - return static_cast(KP_NLWP(info)); -} -#elif GTEST_OS_OPENBSD - -// Returns the number of threads running in the process, or 0 to indicate that -// we cannot detect it. -size_t GetThreadCount() { - int mib[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID | KERN_PROC_SHOW_THREADS, - getpid(), - sizeof(struct kinfo_proc), - 0, - }; - u_int miblen = sizeof(mib) / sizeof(mib[0]); - - // get number of structs - size_t size; - if (sysctl(mib, miblen, NULL, &size, NULL, 0)) { - return 0; - } - mib[5] = size / mib[4]; - - // populate array of structs - struct kinfo_proc info[mib[5]]; - if (sysctl(mib, miblen, &info, &size, NULL, 0)) { - return 0; - } - - // exclude empty members - int nthreads = 0; - for (int i = 0; i < size / mib[4]; i++) { - if (info[i].p_tid != -1) - nthreads++; - } - return nthreads; -} - -#elif GTEST_OS_QNX - -// Returns the number of threads running in the process, or 0 to indicate that -// we cannot detect it. -size_t GetThreadCount() { - const int fd = open("/proc/self/as", O_RDONLY); - if (fd < 0) { - return 0; - } - procfs_info process_info; - const int status = - devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr); - close(fd); - if (status == EOK) { - return static_cast(process_info.num_threads); - } else { - return 0; - } -} - -#elif GTEST_OS_AIX - -size_t GetThreadCount() { - struct procentry64 entry; - pid_t pid = getpid(); - int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1); - if (status == 1) { - return entry.pi_thcount; - } else { - return 0; - } -} - -#elif GTEST_OS_FUCHSIA - -size_t GetThreadCount() { - int dummy_buffer; - size_t avail; - zx_status_t status = zx_object_get_info( - zx_process_self(), - ZX_INFO_PROCESS_THREADS, - &dummy_buffer, - 0, - nullptr, - &avail); - if (status == ZX_OK) { - return avail; - } else { - return 0; - } -} - -#else - -size_t GetThreadCount() { - // There's no portable way to detect the number of threads, so we just - // return 0 to indicate that we cannot detect it. - return 0; -} - -#endif // GTEST_OS_LINUX - -#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS - -void SleepMilliseconds(int n) { - ::Sleep(static_cast(n)); -} - -AutoHandle::AutoHandle() - : handle_(INVALID_HANDLE_VALUE) {} - -AutoHandle::AutoHandle(Handle handle) - : handle_(handle) {} - -AutoHandle::~AutoHandle() { - Reset(); -} - -AutoHandle::Handle AutoHandle::Get() const { - return handle_; -} - -void AutoHandle::Reset() { - Reset(INVALID_HANDLE_VALUE); -} - -void AutoHandle::Reset(HANDLE handle) { - // Resetting with the same handle we already own is invalid. - if (handle_ != handle) { - if (IsCloseable()) { - ::CloseHandle(handle_); - } - handle_ = handle; - } else { - GTEST_CHECK_(!IsCloseable()) - << "Resetting a valid handle to itself is likely a programmer error " - "and thus not allowed."; - } -} - -bool AutoHandle::IsCloseable() const { - // Different Windows APIs may use either of these values to represent an - // invalid handle. - return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE; -} - -Notification::Notification() - : event_(::CreateEvent(nullptr, // Default security attributes. - TRUE, // Do not reset automatically. - FALSE, // Initially unset. - nullptr)) { // Anonymous event. - GTEST_CHECK_(event_.Get() != nullptr); -} - -void Notification::Notify() { - GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE); -} - -void Notification::WaitForNotification() { - GTEST_CHECK_( - ::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0); -} - -Mutex::Mutex() - : owner_thread_id_(0), - type_(kDynamic), - critical_section_init_phase_(0), - critical_section_(new CRITICAL_SECTION) { - ::InitializeCriticalSection(critical_section_); -} - -Mutex::~Mutex() { - // Static mutexes are leaked intentionally. It is not thread-safe to try - // to clean them up. - if (type_ == kDynamic) { - ::DeleteCriticalSection(critical_section_); - delete critical_section_; - critical_section_ = nullptr; - } -} - -void Mutex::Lock() { - ThreadSafeLazyInit(); - ::EnterCriticalSection(critical_section_); - owner_thread_id_ = ::GetCurrentThreadId(); -} - -void Mutex::Unlock() { - ThreadSafeLazyInit(); - // We don't protect writing to owner_thread_id_ here, as it's the - // caller's responsibility to ensure that the current thread holds the - // mutex when this is called. - owner_thread_id_ = 0; - ::LeaveCriticalSection(critical_section_); -} - -// Does nothing if the current thread holds the mutex. Otherwise, crashes -// with high probability. -void Mutex::AssertHeld() { - ThreadSafeLazyInit(); - GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId()) - << "The current thread is not holding the mutex @" << this; -} - -namespace { - -#ifdef _MSC_VER -// Use the RAII idiom to flag mem allocs that are intentionally never -// deallocated. The motivation is to silence the false positive mem leaks -// that are reported by the debug version of MS's CRT which can only detect -// if an alloc is missing a matching deallocation. -// Example: -// MemoryIsNotDeallocated memory_is_not_deallocated; -// critical_section_ = new CRITICAL_SECTION; -// -class MemoryIsNotDeallocated -{ - public: - MemoryIsNotDeallocated() : old_crtdbg_flag_(0) { - old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT - // doesn't report mem leak if there's no matching deallocation. - _CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF); - } - - ~MemoryIsNotDeallocated() { - // Restore the original _CRTDBG_ALLOC_MEM_DF flag - _CrtSetDbgFlag(old_crtdbg_flag_); - } - - private: - int old_crtdbg_flag_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated); -}; -#endif // _MSC_VER - -} // namespace - -// Initializes owner_thread_id_ and critical_section_ in static mutexes. -void Mutex::ThreadSafeLazyInit() { - // Dynamic mutexes are initialized in the constructor. - if (type_ == kStatic) { - switch ( - ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) { - case 0: - // If critical_section_init_phase_ was 0 before the exchange, we - // are the first to test it and need to perform the initialization. - owner_thread_id_ = 0; - { - // Use RAII to flag that following mem alloc is never deallocated. -#ifdef _MSC_VER - MemoryIsNotDeallocated memory_is_not_deallocated; -#endif // _MSC_VER - critical_section_ = new CRITICAL_SECTION; - } - ::InitializeCriticalSection(critical_section_); - // Updates the critical_section_init_phase_ to 2 to signal - // initialization complete. - GTEST_CHECK_(::InterlockedCompareExchange( - &critical_section_init_phase_, 2L, 1L) == - 1L); - break; - case 1: - // Somebody else is already initializing the mutex; spin until they - // are done. - while (::InterlockedCompareExchange(&critical_section_init_phase_, - 2L, - 2L) != 2L) { - // Possibly yields the rest of the thread's time slice to other - // threads. - ::Sleep(0); - } - break; - - case 2: - break; // The mutex is already initialized and ready for use. - - default: - GTEST_CHECK_(false) - << "Unexpected value of critical_section_init_phase_ " - << "while initializing a static mutex."; - } - } -} - -namespace { - -class ThreadWithParamSupport : public ThreadWithParamBase { - public: - static HANDLE CreateThread(Runnable* runnable, - Notification* thread_can_start) { - ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start); - DWORD thread_id; - HANDLE thread_handle = ::CreateThread( - nullptr, // Default security. - 0, // Default stack size. - &ThreadWithParamSupport::ThreadMain, - param, // Parameter to ThreadMainStatic - 0x0, // Default creation flags. - &thread_id); // Need a valid pointer for the call to work under Win98. - GTEST_CHECK_(thread_handle != nullptr) - << "CreateThread failed with error " << ::GetLastError() << "."; - if (thread_handle == nullptr) { - delete param; - } - return thread_handle; - } - - private: - struct ThreadMainParam { - ThreadMainParam(Runnable* runnable, Notification* thread_can_start) - : runnable_(runnable), - thread_can_start_(thread_can_start) { - } - std::unique_ptr runnable_; - // Does not own. - Notification* thread_can_start_; - }; - - static DWORD WINAPI ThreadMain(void* ptr) { - // Transfers ownership. - std::unique_ptr param(static_cast(ptr)); - if (param->thread_can_start_ != nullptr) - param->thread_can_start_->WaitForNotification(); - param->runnable_->Run(); - return 0; - } - - // Prohibit instantiation. - ThreadWithParamSupport(); - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport); -}; - -} // namespace - -ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable, - Notification* thread_can_start) - : thread_(ThreadWithParamSupport::CreateThread(runnable, - thread_can_start)) { -} - -ThreadWithParamBase::~ThreadWithParamBase() { - Join(); -} - -void ThreadWithParamBase::Join() { - GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0) - << "Failed to join the thread with error " << ::GetLastError() << "."; -} - -// Maps a thread to a set of ThreadIdToThreadLocals that have values -// instantiated on that thread and notifies them when the thread exits. A -// ThreadLocal instance is expected to persist until all threads it has -// values on have terminated. -class ThreadLocalRegistryImpl { - public: - // Registers thread_local_instance as having value on the current thread. - // Returns a value that can be used to identify the thread from other threads. - static ThreadLocalValueHolderBase* GetValueOnCurrentThread( - const ThreadLocalBase* thread_local_instance) { - DWORD current_thread = ::GetCurrentThreadId(); - MutexLock lock(&mutex_); - ThreadIdToThreadLocals* const thread_to_thread_locals = - GetThreadLocalsMapLocked(); - ThreadIdToThreadLocals::iterator thread_local_pos = - thread_to_thread_locals->find(current_thread); - if (thread_local_pos == thread_to_thread_locals->end()) { - thread_local_pos = thread_to_thread_locals->insert( - std::make_pair(current_thread, ThreadLocalValues())).first; - StartWatcherThreadFor(current_thread); - } - ThreadLocalValues& thread_local_values = thread_local_pos->second; - ThreadLocalValues::iterator value_pos = - thread_local_values.find(thread_local_instance); - if (value_pos == thread_local_values.end()) { - value_pos = - thread_local_values - .insert(std::make_pair( - thread_local_instance, - std::shared_ptr( - thread_local_instance->NewValueForCurrentThread()))) - .first; - } - return value_pos->second.get(); - } - - static void OnThreadLocalDestroyed( - const ThreadLocalBase* thread_local_instance) { - std::vector > value_holders; - // Clean up the ThreadLocalValues data structure while holding the lock, but - // defer the destruction of the ThreadLocalValueHolderBases. - { - MutexLock lock(&mutex_); - ThreadIdToThreadLocals* const thread_to_thread_locals = - GetThreadLocalsMapLocked(); - for (ThreadIdToThreadLocals::iterator it = - thread_to_thread_locals->begin(); - it != thread_to_thread_locals->end(); - ++it) { - ThreadLocalValues& thread_local_values = it->second; - ThreadLocalValues::iterator value_pos = - thread_local_values.find(thread_local_instance); - if (value_pos != thread_local_values.end()) { - value_holders.push_back(value_pos->second); - thread_local_values.erase(value_pos); - // This 'if' can only be successful at most once, so theoretically we - // could break out of the loop here, but we don't bother doing so. - } - } - } - // Outside the lock, let the destructor for 'value_holders' deallocate the - // ThreadLocalValueHolderBases. - } - - static void OnThreadExit(DWORD thread_id) { - GTEST_CHECK_(thread_id != 0) << ::GetLastError(); - std::vector > value_holders; - // Clean up the ThreadIdToThreadLocals data structure while holding the - // lock, but defer the destruction of the ThreadLocalValueHolderBases. - { - MutexLock lock(&mutex_); - ThreadIdToThreadLocals* const thread_to_thread_locals = - GetThreadLocalsMapLocked(); - ThreadIdToThreadLocals::iterator thread_local_pos = - thread_to_thread_locals->find(thread_id); - if (thread_local_pos != thread_to_thread_locals->end()) { - ThreadLocalValues& thread_local_values = thread_local_pos->second; - for (ThreadLocalValues::iterator value_pos = - thread_local_values.begin(); - value_pos != thread_local_values.end(); - ++value_pos) { - value_holders.push_back(value_pos->second); - } - thread_to_thread_locals->erase(thread_local_pos); - } - } - // Outside the lock, let the destructor for 'value_holders' deallocate the - // ThreadLocalValueHolderBases. - } - - private: - // In a particular thread, maps a ThreadLocal object to its value. - typedef std::map > - ThreadLocalValues; - // Stores all ThreadIdToThreadLocals having values in a thread, indexed by - // thread's ID. - typedef std::map ThreadIdToThreadLocals; - - // Holds the thread id and thread handle that we pass from - // StartWatcherThreadFor to WatcherThreadFunc. - typedef std::pair ThreadIdAndHandle; - - static void StartWatcherThreadFor(DWORD thread_id) { - // The returned handle will be kept in thread_map and closed by - // watcher_thread in WatcherThreadFunc. - HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, - FALSE, - thread_id); - GTEST_CHECK_(thread != nullptr); - // We need to pass a valid thread ID pointer into CreateThread for it - // to work correctly under Win98. - DWORD watcher_thread_id; - HANDLE watcher_thread = ::CreateThread( - nullptr, // Default security. - 0, // Default stack size - &ThreadLocalRegistryImpl::WatcherThreadFunc, - reinterpret_cast(new ThreadIdAndHandle(thread_id, thread)), - CREATE_SUSPENDED, &watcher_thread_id); - GTEST_CHECK_(watcher_thread != nullptr); - // Give the watcher thread the same priority as ours to avoid being - // blocked by it. - ::SetThreadPriority(watcher_thread, - ::GetThreadPriority(::GetCurrentThread())); - ::ResumeThread(watcher_thread); - ::CloseHandle(watcher_thread); - } - - // Monitors exit from a given thread and notifies those - // ThreadIdToThreadLocals about thread termination. - static DWORD WINAPI WatcherThreadFunc(LPVOID param) { - const ThreadIdAndHandle* tah = - reinterpret_cast(param); - GTEST_CHECK_( - ::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0); - OnThreadExit(tah->first); - ::CloseHandle(tah->second); - delete tah; - return 0; - } - - // Returns map of thread local instances. - static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() { - mutex_.AssertHeld(); -#ifdef _MSC_VER - MemoryIsNotDeallocated memory_is_not_deallocated; -#endif // _MSC_VER - static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals(); - return map; - } - - // Protects access to GetThreadLocalsMapLocked() and its return value. - static Mutex mutex_; - // Protects access to GetThreadMapLocked() and its return value. - static Mutex thread_map_mutex_; -}; - -Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex); -Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex); - -ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread( - const ThreadLocalBase* thread_local_instance) { - return ThreadLocalRegistryImpl::GetValueOnCurrentThread( - thread_local_instance); -} - -void ThreadLocalRegistry::OnThreadLocalDestroyed( - const ThreadLocalBase* thread_local_instance) { - ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance); -} - -#endif // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS - -#if GTEST_USES_POSIX_RE - -// Implements RE. Currently only needed for death tests. - -RE::~RE() { - if (is_valid_) { - // regfree'ing an invalid regex might crash because the content - // of the regex is undefined. Since the regex's are essentially - // the same, one cannot be valid (or invalid) without the other - // being so too. - regfree(&partial_regex_); - regfree(&full_regex_); - } - free(const_cast(pattern_)); -} - -// Returns true if and only if regular expression re matches the entire str. -bool RE::FullMatch(const char* str, const RE& re) { - if (!re.is_valid_) return false; - - regmatch_t match; - return regexec(&re.full_regex_, str, 1, &match, 0) == 0; -} - -// Returns true if and only if regular expression re matches a substring of -// str (including str itself). -bool RE::PartialMatch(const char* str, const RE& re) { - if (!re.is_valid_) return false; - - regmatch_t match; - return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; -} - -// Initializes an RE from its string representation. -void RE::Init(const char* regex) { - pattern_ = posix::StrDup(regex); - - // Reserves enough bytes to hold the regular expression used for a - // full match. - const size_t full_regex_len = strlen(regex) + 10; - char* const full_pattern = new char[full_regex_len]; - - snprintf(full_pattern, full_regex_len, "^(%s)$", regex); - is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; - // We want to call regcomp(&partial_regex_, ...) even if the - // previous expression returns false. Otherwise partial_regex_ may - // not be properly initialized can may cause trouble when it's - // freed. - // - // Some implementation of POSIX regex (e.g. on at least some - // versions of Cygwin) doesn't accept the empty string as a valid - // regex. We change it to an equivalent form "()" to be safe. - if (is_valid_) { - const char* const partial_regex = (*regex == '\0') ? "()" : regex; - is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; - } - EXPECT_TRUE(is_valid_) - << "Regular expression \"" << regex - << "\" is not a valid POSIX Extended regular expression."; - - delete[] full_pattern; -} - -#elif GTEST_USES_SIMPLE_RE - -// Returns true if and only if ch appears anywhere in str (excluding the -// terminating '\0' character). -bool IsInSet(char ch, const char* str) { - return ch != '\0' && strchr(str, ch) != nullptr; -} - -// Returns true if and only if ch belongs to the given classification. -// Unlike similar functions in , these aren't affected by the -// current locale. -bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } -bool IsAsciiPunct(char ch) { - return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); -} -bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } -bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } -bool IsAsciiWordChar(char ch) { - return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || - ('0' <= ch && ch <= '9') || ch == '_'; -} - -// Returns true if and only if "\\c" is a supported escape sequence. -bool IsValidEscape(char c) { - return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); -} - -// Returns true if and only if the given atom (specified by escaped and -// pattern) matches ch. The result is undefined if the atom is invalid. -bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { - if (escaped) { // "\\p" where p is pattern_char. - switch (pattern_char) { - case 'd': return IsAsciiDigit(ch); - case 'D': return !IsAsciiDigit(ch); - case 'f': return ch == '\f'; - case 'n': return ch == '\n'; - case 'r': return ch == '\r'; - case 's': return IsAsciiWhiteSpace(ch); - case 'S': return !IsAsciiWhiteSpace(ch); - case 't': return ch == '\t'; - case 'v': return ch == '\v'; - case 'w': return IsAsciiWordChar(ch); - case 'W': return !IsAsciiWordChar(ch); - } - return IsAsciiPunct(pattern_char) && pattern_char == ch; - } - - return (pattern_char == '.' && ch != '\n') || pattern_char == ch; -} - -// Helper function used by ValidateRegex() to format error messages. -static std::string FormatRegexSyntaxError(const char* regex, int index) { - return (Message() << "Syntax error at index " << index - << " in simple regular expression \"" << regex << "\": ").GetString(); -} - -// Generates non-fatal failures and returns false if regex is invalid; -// otherwise returns true. -bool ValidateRegex(const char* regex) { - if (regex == nullptr) { - ADD_FAILURE() << "NULL is not a valid simple regular expression."; - return false; - } - - bool is_valid = true; - - // True if and only if ?, *, or + can follow the previous atom. - bool prev_repeatable = false; - for (int i = 0; regex[i]; i++) { - if (regex[i] == '\\') { // An escape sequence - i++; - if (regex[i] == '\0') { - ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) - << "'\\' cannot appear at the end."; - return false; - } - - if (!IsValidEscape(regex[i])) { - ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) - << "invalid escape sequence \"\\" << regex[i] << "\"."; - is_valid = false; - } - prev_repeatable = true; - } else { // Not an escape sequence. - const char ch = regex[i]; - - if (ch == '^' && i > 0) { - ADD_FAILURE() << FormatRegexSyntaxError(regex, i) - << "'^' can only appear at the beginning."; - is_valid = false; - } else if (ch == '$' && regex[i + 1] != '\0') { - ADD_FAILURE() << FormatRegexSyntaxError(regex, i) - << "'$' can only appear at the end."; - is_valid = false; - } else if (IsInSet(ch, "()[]{}|")) { - ADD_FAILURE() << FormatRegexSyntaxError(regex, i) - << "'" << ch << "' is unsupported."; - is_valid = false; - } else if (IsRepeat(ch) && !prev_repeatable) { - ADD_FAILURE() << FormatRegexSyntaxError(regex, i) - << "'" << ch << "' can only follow a repeatable token."; - is_valid = false; - } - - prev_repeatable = !IsInSet(ch, "^$?*+"); - } - } - - return is_valid; -} - -// Matches a repeated regex atom followed by a valid simple regular -// expression. The regex atom is defined as c if escaped is false, -// or \c otherwise. repeat is the repetition meta character (?, *, -// or +). The behavior is undefined if str contains too many -// characters to be indexable by size_t, in which case the test will -// probably time out anyway. We are fine with this limitation as -// std::string has it too. -bool MatchRepetitionAndRegexAtHead( - bool escaped, char c, char repeat, const char* regex, - const char* str) { - const size_t min_count = (repeat == '+') ? 1 : 0; - const size_t max_count = (repeat == '?') ? 1 : - static_cast(-1) - 1; - // We cannot call numeric_limits::max() as it conflicts with the - // max() macro on Windows. - - for (size_t i = 0; i <= max_count; ++i) { - // We know that the atom matches each of the first i characters in str. - if (i >= min_count && MatchRegexAtHead(regex, str + i)) { - // We have enough matches at the head, and the tail matches too. - // Since we only care about *whether* the pattern matches str - // (as opposed to *how* it matches), there is no need to find a - // greedy match. - return true; - } - if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) - return false; - } - return false; -} - -// Returns true if and only if regex matches a prefix of str. regex must -// be a valid simple regular expression and not start with "^", or the -// result is undefined. -bool MatchRegexAtHead(const char* regex, const char* str) { - if (*regex == '\0') // An empty regex matches a prefix of anything. - return true; - - // "$" only matches the end of a string. Note that regex being - // valid guarantees that there's nothing after "$" in it. - if (*regex == '$') - return *str == '\0'; - - // Is the first thing in regex an escape sequence? - const bool escaped = *regex == '\\'; - if (escaped) - ++regex; - if (IsRepeat(regex[1])) { - // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so - // here's an indirect recursion. It terminates as the regex gets - // shorter in each recursion. - return MatchRepetitionAndRegexAtHead( - escaped, regex[0], regex[1], regex + 2, str); - } else { - // regex isn't empty, isn't "$", and doesn't start with a - // repetition. We match the first atom of regex with the first - // character of str and recurse. - return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && - MatchRegexAtHead(regex + 1, str + 1); - } -} - -// Returns true if and only if regex matches any substring of str. regex must -// be a valid simple regular expression, or the result is undefined. -// -// The algorithm is recursive, but the recursion depth doesn't exceed -// the regex length, so we won't need to worry about running out of -// stack space normally. In rare cases the time complexity can be -// exponential with respect to the regex length + the string length, -// but usually it's must faster (often close to linear). -bool MatchRegexAnywhere(const char* regex, const char* str) { - if (regex == nullptr || str == nullptr) return false; - - if (*regex == '^') - return MatchRegexAtHead(regex + 1, str); - - // A successful match can be anywhere in str. - do { - if (MatchRegexAtHead(regex, str)) - return true; - } while (*str++ != '\0'); - return false; -} - -// Implements the RE class. - -RE::~RE() { - free(const_cast(pattern_)); - free(const_cast(full_pattern_)); -} - -// Returns true if and only if regular expression re matches the entire str. -bool RE::FullMatch(const char* str, const RE& re) { - return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); -} - -// Returns true if and only if regular expression re matches a substring of -// str (including str itself). -bool RE::PartialMatch(const char* str, const RE& re) { - return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); -} - -// Initializes an RE from its string representation. -void RE::Init(const char* regex) { - pattern_ = full_pattern_ = nullptr; - if (regex != nullptr) { - pattern_ = posix::StrDup(regex); - } - - is_valid_ = ValidateRegex(regex); - if (!is_valid_) { - // No need to calculate the full pattern when the regex is invalid. - return; - } - - const size_t len = strlen(regex); - // Reserves enough bytes to hold the regular expression used for a - // full match: we need space to prepend a '^', append a '$', and - // terminate the string with '\0'. - char* buffer = static_cast(malloc(len + 3)); - full_pattern_ = buffer; - - if (*regex != '^') - *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. - - // We don't use snprintf or strncpy, as they trigger a warning when - // compiled with VC++ 8.0. - memcpy(buffer, regex, len); - buffer += len; - - if (len == 0 || regex[len - 1] != '$') - *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. - - *buffer = '\0'; -} - -#endif // GTEST_USES_POSIX_RE - -const char kUnknownFile[] = "unknown file"; - -// Formats a source file path and a line number as they would appear -// in an error message from the compiler used to compile this code. -GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { - const std::string file_name(file == nullptr ? kUnknownFile : file); - - if (line < 0) { - return file_name + ":"; - } -#ifdef _MSC_VER - return file_name + "(" + StreamableToString(line) + "):"; -#else - return file_name + ":" + StreamableToString(line) + ":"; -#endif // _MSC_VER -} - -// Formats a file location for compiler-independent XML output. -// Although this function is not platform dependent, we put it next to -// FormatFileLocation in order to contrast the two functions. -// Note that FormatCompilerIndependentFileLocation() does NOT append colon -// to the file location it produces, unlike FormatFileLocation(). -GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( - const char* file, int line) { - const std::string file_name(file == nullptr ? kUnknownFile : file); - - if (line < 0) - return file_name; - else - return file_name + ":" + StreamableToString(line); -} - -GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) - : severity_(severity) { - const char* const marker = - severity == GTEST_INFO ? "[ INFO ]" : - severity == GTEST_WARNING ? "[WARNING]" : - severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; - GetStream() << ::std::endl << marker << " " - << FormatFileLocation(file, line).c_str() << ": "; -} - -// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. -GTestLog::~GTestLog() { - GetStream() << ::std::endl; - if (severity_ == GTEST_FATAL) { - fflush(stderr); - posix::Abort(); - } -} - -// Disable Microsoft deprecation warnings for POSIX functions called from -// this class (creat, dup, dup2, and close) -GTEST_DISABLE_MSC_DEPRECATED_PUSH_() - -#if GTEST_HAS_STREAM_REDIRECTION - -// Object that captures an output stream (stdout/stderr). -class CapturedStream { - public: - // The ctor redirects the stream to a temporary file. - explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { -# if GTEST_OS_WINDOWS - char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT - char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT - - ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); - const UINT success = ::GetTempFileNameA(temp_dir_path, - "gtest_redir", - 0, // Generate unique file name. - temp_file_path); - GTEST_CHECK_(success != 0) - << "Unable to create a temporary file in " << temp_dir_path; - const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); - GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " - << temp_file_path; - filename_ = temp_file_path; -# else - // There's no guarantee that a test has write access to the current - // directory, so we create the temporary file in the /tmp directory - // instead. We use /tmp on most systems, and /sdcard on Android. - // That's because Android doesn't have /tmp. -# if GTEST_OS_LINUX_ANDROID - // Note: Android applications are expected to call the framework's - // Context.getExternalStorageDirectory() method through JNI to get - // the location of the world-writable SD Card directory. However, - // this requires a Context handle, which cannot be retrieved - // globally from native code. Doing so also precludes running the - // code as part of a regular standalone executable, which doesn't - // run in a Dalvik process (e.g. when running it through 'adb shell'). - // - // The location /data/local/tmp is directly accessible from native code. - // '/sdcard' and other variants cannot be relied on, as they are not - // guaranteed to be mounted, or may have a delay in mounting. - char name_template[] = "/data/local/tmp/gtest_captured_stream.XXXXXX"; -# else - char name_template[] = "/tmp/captured_stream.XXXXXX"; -# endif // GTEST_OS_LINUX_ANDROID - const int captured_fd = mkstemp(name_template); - if (captured_fd == -1) { - GTEST_LOG_(WARNING) - << "Failed to create tmp file " << name_template - << " for test; does the test have access to the /tmp directory?"; - } - filename_ = name_template; -# endif // GTEST_OS_WINDOWS - fflush(nullptr); - dup2(captured_fd, fd_); - close(captured_fd); - } - - ~CapturedStream() { - remove(filename_.c_str()); - } - - std::string GetCapturedString() { - if (uncaptured_fd_ != -1) { - // Restores the original stream. - fflush(nullptr); - dup2(uncaptured_fd_, fd_); - close(uncaptured_fd_); - uncaptured_fd_ = -1; - } - - FILE* const file = posix::FOpen(filename_.c_str(), "r"); - if (file == nullptr) { - GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_ - << " for capturing stream."; - } - const std::string content = ReadEntireFile(file); - posix::FClose(file); - return content; - } - - private: - const int fd_; // A stream to capture. - int uncaptured_fd_; - // Name of the temporary file holding the stderr output. - ::std::string filename_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); -}; - -GTEST_DISABLE_MSC_DEPRECATED_POP_() - -static CapturedStream* g_captured_stderr = nullptr; -static CapturedStream* g_captured_stdout = nullptr; - -// Starts capturing an output stream (stdout/stderr). -static void CaptureStream(int fd, const char* stream_name, - CapturedStream** stream) { - if (*stream != nullptr) { - GTEST_LOG_(FATAL) << "Only one " << stream_name - << " capturer can exist at a time."; - } - *stream = new CapturedStream(fd); -} - -// Stops capturing the output stream and returns the captured string. -static std::string GetCapturedStream(CapturedStream** captured_stream) { - const std::string content = (*captured_stream)->GetCapturedString(); - - delete *captured_stream; - *captured_stream = nullptr; - - return content; -} - -// Starts capturing stdout. -void CaptureStdout() { - CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); -} - -// Starts capturing stderr. -void CaptureStderr() { - CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); -} - -// Stops capturing stdout and returns the captured string. -std::string GetCapturedStdout() { - return GetCapturedStream(&g_captured_stdout); -} - -// Stops capturing stderr and returns the captured string. -std::string GetCapturedStderr() { - return GetCapturedStream(&g_captured_stderr); -} - -#endif // GTEST_HAS_STREAM_REDIRECTION - - - - - -size_t GetFileSize(FILE* file) { - fseek(file, 0, SEEK_END); - return static_cast(ftell(file)); -} - -std::string ReadEntireFile(FILE* file) { - const size_t file_size = GetFileSize(file); - char* const buffer = new char[file_size]; - - size_t bytes_last_read = 0; // # of bytes read in the last fread() - size_t bytes_read = 0; // # of bytes read so far - - fseek(file, 0, SEEK_SET); - - // Keeps reading the file until we cannot read further or the - // pre-determined file size is reached. - do { - bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); - bytes_read += bytes_last_read; - } while (bytes_last_read > 0 && bytes_read < file_size); - - const std::string content(buffer, bytes_read); - delete[] buffer; - - return content; -} - -#if GTEST_HAS_DEATH_TEST -static const std::vector* g_injected_test_argvs = - nullptr; // Owned. - -std::vector GetInjectableArgvs() { - if (g_injected_test_argvs != nullptr) { - return *g_injected_test_argvs; - } - return GetArgvs(); -} - -void SetInjectableArgvs(const std::vector* new_argvs) { - if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs; - g_injected_test_argvs = new_argvs; -} - -void SetInjectableArgvs(const std::vector& new_argvs) { - SetInjectableArgvs( - new std::vector(new_argvs.begin(), new_argvs.end())); -} - -void ClearInjectableArgvs() { - delete g_injected_test_argvs; - g_injected_test_argvs = nullptr; -} -#endif // GTEST_HAS_DEATH_TEST - -#if GTEST_OS_WINDOWS_MOBILE -namespace posix { -void Abort() { - DebugBreak(); - TerminateProcess(GetCurrentProcess(), 1); -} -} // namespace posix -#endif // GTEST_OS_WINDOWS_MOBILE - -// Returns the name of the environment variable corresponding to the -// given flag. For example, FlagToEnvVar("foo") will return -// "GTEST_FOO" in the open-source version. -static std::string FlagToEnvVar(const char* flag) { - const std::string full_flag = - (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); - - Message env_var; - for (size_t i = 0; i != full_flag.length(); i++) { - env_var << ToUpper(full_flag.c_str()[i]); - } - - return env_var.GetString(); -} - -// Parses 'str' for a 32-bit signed integer. If successful, writes -// the result to *value and returns true; otherwise leaves *value -// unchanged and returns false. -bool ParseInt32(const Message& src_text, const char* str, Int32* value) { - // Parses the environment variable as a decimal integer. - char* end = nullptr; - const long long_value = strtol(str, &end, 10); // NOLINT - - // Has strtol() consumed all characters in the string? - if (*end != '\0') { - // No - an invalid character was encountered. - Message msg; - msg << "WARNING: " << src_text - << " is expected to be a 32-bit integer, but actually" - << " has value \"" << str << "\".\n"; - printf("%s", msg.GetString().c_str()); - fflush(stdout); - return false; - } - - // Is the parsed value in the range of an Int32? - const Int32 result = static_cast(long_value); - if (long_value == LONG_MAX || long_value == LONG_MIN || - // The parsed value overflows as a long. (strtol() returns - // LONG_MAX or LONG_MIN when the input overflows.) - result != long_value - // The parsed value overflows as an Int32. - ) { - Message msg; - msg << "WARNING: " << src_text - << " is expected to be a 32-bit integer, but actually" - << " has value " << str << ", which overflows.\n"; - printf("%s", msg.GetString().c_str()); - fflush(stdout); - return false; - } - - *value = result; - return true; -} - -// Reads and returns the Boolean environment variable corresponding to -// the given flag; if it's not set, returns default_value. -// -// The value is considered true if and only if it's not "0". -bool BoolFromGTestEnv(const char* flag, bool default_value) { -#if defined(GTEST_GET_BOOL_FROM_ENV_) - return GTEST_GET_BOOL_FROM_ENV_(flag, default_value); -#else - const std::string env_var = FlagToEnvVar(flag); - const char* const string_value = posix::GetEnv(env_var.c_str()); - return string_value == nullptr ? default_value - : strcmp(string_value, "0") != 0; -#endif // defined(GTEST_GET_BOOL_FROM_ENV_) -} - -// Reads and returns a 32-bit integer stored in the environment -// variable corresponding to the given flag; if it isn't set or -// doesn't represent a valid 32-bit integer, returns default_value. -Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { -#if defined(GTEST_GET_INT32_FROM_ENV_) - return GTEST_GET_INT32_FROM_ENV_(flag, default_value); -#else - const std::string env_var = FlagToEnvVar(flag); - const char* const string_value = posix::GetEnv(env_var.c_str()); - if (string_value == nullptr) { - // The environment variable is not set. - return default_value; - } - - Int32 result = default_value; - if (!ParseInt32(Message() << "Environment variable " << env_var, - string_value, &result)) { - printf("The default value %s is used.\n", - (Message() << default_value).GetString().c_str()); - fflush(stdout); - return default_value; - } - - return result; -#endif // defined(GTEST_GET_INT32_FROM_ENV_) -} - -// As a special case for the 'output' flag, if GTEST_OUTPUT is not -// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build -// system. The value of XML_OUTPUT_FILE is a filename without the -// "xml:" prefix of GTEST_OUTPUT. -// Note that this is meant to be called at the call site so it does -// not check that the flag is 'output' -// In essence this checks an env variable called XML_OUTPUT_FILE -// and if it is set we prepend "xml:" to its value, if it not set we return "" -std::string OutputFlagAlsoCheckEnvVar(){ - std::string default_value_for_output_flag = ""; - const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE"); - if (nullptr != xml_output_file_env) { - default_value_for_output_flag = std::string("xml:") + xml_output_file_env; - } - return default_value_for_output_flag; -} - -// Reads and returns the string environment variable corresponding to -// the given flag; if it's not set, returns default_value. -const char* StringFromGTestEnv(const char* flag, const char* default_value) { -#if defined(GTEST_GET_STRING_FROM_ENV_) - return GTEST_GET_STRING_FROM_ENV_(flag, default_value); -#else - const std::string env_var = FlagToEnvVar(flag); - const char* const value = posix::GetEnv(env_var.c_str()); - return value == nullptr ? default_value : value; -#endif // defined(GTEST_GET_STRING_FROM_ENV_) -} - -} // namespace internal -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-printers.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-printers.cc deleted file mode 100644 index 3337be312ea..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-printers.cc +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2007, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -// Google Test - The Google C++ Testing and Mocking Framework -// -// This file implements a universal value printer that can print a -// value of any type T: -// -// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); -// -// It uses the << operator when possible, and prints the bytes in the -// object otherwise. A user can override its behavior for a class -// type Foo by defining either operator<<(::std::ostream&, const Foo&) -// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that -// defines Foo. - -#include "gtest/gtest-printers.h" -#include -#include -#include -#include // NOLINT -#include -#include "gtest/internal/gtest-port.h" -#include "src/gtest-internal-inl.h" - -namespace testing { - -namespace { - -using ::std::ostream; - -// Prints a segment of bytes in the given object. -GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ -GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ -void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, - size_t count, ostream* os) { - char text[5] = ""; - for (size_t i = 0; i != count; i++) { - const size_t j = start + i; - if (i != 0) { - // Organizes the bytes into groups of 2 for easy parsing by - // human. - if ((j % 2) == 0) - *os << ' '; - else - *os << '-'; - } - GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); - *os << text; - } -} - -// Prints the bytes in the given value to the given ostream. -void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, - ostream* os) { - // Tells the user how big the object is. - *os << count << "-byte object <"; - - const size_t kThreshold = 132; - const size_t kChunkSize = 64; - // If the object size is bigger than kThreshold, we'll have to omit - // some details by printing only the first and the last kChunkSize - // bytes. - if (count < kThreshold) { - PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); - } else { - PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); - *os << " ... "; - // Rounds up to 2-byte boundary. - const size_t resume_pos = (count - kChunkSize + 1)/2*2; - PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); - } - *os << ">"; -} - -} // namespace - -namespace internal2 { - -// Delegates to PrintBytesInObjectToImpl() to print the bytes in the -// given object. The delegation simplifies the implementation, which -// uses the << operator and thus is easier done outside of the -// ::testing::internal namespace, which contains a << operator that -// sometimes conflicts with the one in STL. -void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, - ostream* os) { - PrintBytesInObjectToImpl(obj_bytes, count, os); -} - -} // namespace internal2 - -namespace internal { - -// Depending on the value of a char (or wchar_t), we print it in one -// of three formats: -// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), -// - as a hexadecimal escape sequence (e.g. '\x7F'), or -// - as a special escape sequence (e.g. '\r', '\n'). -enum CharFormat { - kAsIs, - kHexEscape, - kSpecialEscape -}; - -// Returns true if c is a printable ASCII character. We test the -// value of c directly instead of calling isprint(), which is buggy on -// Windows Mobile. -inline bool IsPrintableAscii(wchar_t c) { - return 0x20 <= c && c <= 0x7E; -} - -// Prints a wide or narrow char c as a character literal without the -// quotes, escaping it when necessary; returns how c was formatted. -// The template argument UnsignedChar is the unsigned version of Char, -// which is the type of c. -template -static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { - wchar_t w_c = static_cast(c); - switch (w_c) { - case L'\0': - *os << "\\0"; - break; - case L'\'': - *os << "\\'"; - break; - case L'\\': - *os << "\\\\"; - break; - case L'\a': - *os << "\\a"; - break; - case L'\b': - *os << "\\b"; - break; - case L'\f': - *os << "\\f"; - break; - case L'\n': - *os << "\\n"; - break; - case L'\r': - *os << "\\r"; - break; - case L'\t': - *os << "\\t"; - break; - case L'\v': - *os << "\\v"; - break; - default: - if (IsPrintableAscii(w_c)) { - *os << static_cast(c); - return kAsIs; - } else { - ostream::fmtflags flags = os->flags(); - *os << "\\x" << std::hex << std::uppercase - << static_cast(static_cast(c)); - os->flags(flags); - return kHexEscape; - } - } - return kSpecialEscape; -} - -// Prints a wchar_t c as if it's part of a string literal, escaping it when -// necessary; returns how c was formatted. -static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { - switch (c) { - case L'\'': - *os << "'"; - return kAsIs; - case L'"': - *os << "\\\""; - return kSpecialEscape; - default: - return PrintAsCharLiteralTo(c, os); - } -} - -// Prints a char c as if it's part of a string literal, escaping it when -// necessary; returns how c was formatted. -static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { - return PrintAsStringLiteralTo( - static_cast(static_cast(c)), os); -} - -// Prints a wide or narrow character c and its code. '\0' is printed -// as "'\\0'", other unprintable characters are also properly escaped -// using the standard C++ escape sequence. The template argument -// UnsignedChar is the unsigned version of Char, which is the type of c. -template -void PrintCharAndCodeTo(Char c, ostream* os) { - // First, print c as a literal in the most readable form we can find. - *os << ((sizeof(c) > 1) ? "L'" : "'"); - const CharFormat format = PrintAsCharLiteralTo(c, os); - *os << "'"; - - // To aid user debugging, we also print c's code in decimal, unless - // it's 0 (in which case c was printed as '\\0', making the code - // obvious). - if (c == 0) - return; - *os << " (" << static_cast(c); - - // For more convenience, we print c's code again in hexadecimal, - // unless c was already printed in the form '\x##' or the code is in - // [1, 9]. - if (format == kHexEscape || (1 <= c && c <= 9)) { - // Do nothing. - } else { - *os << ", 0x" << String::FormatHexInt(static_cast(c)); - } - *os << ")"; -} - -void PrintTo(unsigned char c, ::std::ostream* os) { - PrintCharAndCodeTo(c, os); -} -void PrintTo(signed char c, ::std::ostream* os) { - PrintCharAndCodeTo(c, os); -} - -// Prints a wchar_t as a symbol if it is printable or as its internal -// code otherwise and also as its code. L'\0' is printed as "L'\\0'". -void PrintTo(wchar_t wc, ostream* os) { - PrintCharAndCodeTo(wc, os); -} - -// Prints the given array of characters to the ostream. CharType must be either -// char or wchar_t. -// The array starts at begin, the length is len, it may include '\0' characters -// and may not be NUL-terminated. -template -GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ -GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ -static CharFormat PrintCharsAsStringTo( - const CharType* begin, size_t len, ostream* os) { - const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; - *os << kQuoteBegin; - bool is_previous_hex = false; - CharFormat print_format = kAsIs; - for (size_t index = 0; index < len; ++index) { - const CharType cur = begin[index]; - if (is_previous_hex && IsXDigit(cur)) { - // Previous character is of '\x..' form and this character can be - // interpreted as another hexadecimal digit in its number. Break string to - // disambiguate. - *os << "\" " << kQuoteBegin; - } - is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; - // Remember if any characters required hex escaping. - if (is_previous_hex) { - print_format = kHexEscape; - } - } - *os << "\""; - return print_format; -} - -// Prints a (const) char/wchar_t array of 'len' elements, starting at address -// 'begin'. CharType must be either char or wchar_t. -template -GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ -GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ -GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ -static void UniversalPrintCharArray( - const CharType* begin, size_t len, ostream* os) { - // The code - // const char kFoo[] = "foo"; - // generates an array of 4, not 3, elements, with the last one being '\0'. - // - // Therefore when printing a char array, we don't print the last element if - // it's '\0', such that the output matches the string literal as it's - // written in the source code. - if (len > 0 && begin[len - 1] == '\0') { - PrintCharsAsStringTo(begin, len - 1, os); - return; - } - - // If, however, the last element in the array is not '\0', e.g. - // const char kFoo[] = { 'f', 'o', 'o' }; - // we must print the entire array. We also print a message to indicate - // that the array is not NUL-terminated. - PrintCharsAsStringTo(begin, len, os); - *os << " (no terminating NUL)"; -} - -// Prints a (const) char array of 'len' elements, starting at address 'begin'. -void UniversalPrintArray(const char* begin, size_t len, ostream* os) { - UniversalPrintCharArray(begin, len, os); -} - -// Prints a (const) wchar_t array of 'len' elements, starting at address -// 'begin'. -void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { - UniversalPrintCharArray(begin, len, os); -} - -// Prints the given C string to the ostream. -void PrintTo(const char* s, ostream* os) { - if (s == nullptr) { - *os << "NULL"; - } else { - *os << ImplicitCast_(s) << " pointing to "; - PrintCharsAsStringTo(s, strlen(s), os); - } -} - -// MSVC compiler can be configured to define whar_t as a typedef -// of unsigned short. Defining an overload for const wchar_t* in that case -// would cause pointers to unsigned shorts be printed as wide strings, -// possibly accessing more memory than intended and causing invalid -// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when -// wchar_t is implemented as a native type. -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) -// Prints the given wide C string to the ostream. -void PrintTo(const wchar_t* s, ostream* os) { - if (s == nullptr) { - *os << "NULL"; - } else { - *os << ImplicitCast_(s) << " pointing to "; - PrintCharsAsStringTo(s, wcslen(s), os); - } -} -#endif // wchar_t is native - -namespace { - -bool ContainsUnprintableControlCodes(const char* str, size_t length) { - const unsigned char *s = reinterpret_cast(str); - - for (size_t i = 0; i < length; i++) { - unsigned char ch = *s++; - if (std::iscntrl(ch)) { - switch (ch) { - case '\t': - case '\n': - case '\r': - break; - default: - return true; - } - } - } - return false; -} - -bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; } - -bool IsValidUTF8(const char* str, size_t length) { - const unsigned char *s = reinterpret_cast(str); - - for (size_t i = 0; i < length;) { - unsigned char lead = s[i++]; - - if (lead <= 0x7f) { - continue; // single-byte character (ASCII) 0..7F - } - if (lead < 0xc2) { - return false; // trail byte or non-shortest form - } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) { - ++i; // 2-byte character - } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length && - IsUTF8TrailByte(s[i]) && - IsUTF8TrailByte(s[i + 1]) && - // check for non-shortest form and surrogate - (lead != 0xe0 || s[i] >= 0xa0) && - (lead != 0xed || s[i] < 0xa0)) { - i += 2; // 3-byte character - } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length && - IsUTF8TrailByte(s[i]) && - IsUTF8TrailByte(s[i + 1]) && - IsUTF8TrailByte(s[i + 2]) && - // check for non-shortest form - (lead != 0xf0 || s[i] >= 0x90) && - (lead != 0xf4 || s[i] < 0x90)) { - i += 3; // 4-byte character - } else { - return false; - } - } - return true; -} - -void ConditionalPrintAsText(const char* str, size_t length, ostream* os) { - if (!ContainsUnprintableControlCodes(str, length) && - IsValidUTF8(str, length)) { - *os << "\n As Text: \"" << str << "\""; - } -} - -} // anonymous namespace - -void PrintStringTo(const ::std::string& s, ostream* os) { - if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) { - if (GTEST_FLAG(print_utf8)) { - ConditionalPrintAsText(s.data(), s.size(), os); - } - } -} - -#if GTEST_HAS_STD_WSTRING -void PrintWideStringTo(const ::std::wstring& s, ostream* os) { - PrintCharsAsStringTo(s.data(), s.size(), os); -} -#endif // GTEST_HAS_STD_WSTRING - -} // namespace internal - -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-test-part.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-test-part.cc deleted file mode 100644 index 178317a6bcd..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-test-part.cc +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2008, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// The Google C++ Testing and Mocking Framework (Google Test) - -#include "gtest/gtest-test-part.h" -#include "src/gtest-internal-inl.h" - -namespace testing { - -using internal::GetUnitTestImpl; - -// Gets the summary of the failure message by omitting the stack trace -// in it. -std::string TestPartResult::ExtractSummary(const char* message) { - const char* const stack_trace = strstr(message, internal::kStackTraceMarker); - return stack_trace == nullptr ? message : std::string(message, stack_trace); -} - -// Prints a TestPartResult object. -std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { - return os << result.file_name() << ":" << result.line_number() << ": " - << (result.type() == TestPartResult::kSuccess - ? "Success" - : result.type() == TestPartResult::kSkip - ? "Skipped" - : result.type() == TestPartResult::kFatalFailure - ? "Fatal failure" - : "Non-fatal failure") - << ":\n" - << result.message() << std::endl; -} - -// Appends a TestPartResult to the array. -void TestPartResultArray::Append(const TestPartResult& result) { - array_.push_back(result); -} - -// Returns the TestPartResult at the given index (0-based). -const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { - if (index < 0 || index >= size()) { - printf("\nInvalid index (%d) into TestPartResultArray.\n", index); - internal::posix::Abort(); - } - - return array_[static_cast(index)]; -} - -// Returns the number of TestPartResult objects in the array. -int TestPartResultArray::size() const { - return static_cast(array_.size()); -} - -namespace internal { - -HasNewFatalFailureHelper::HasNewFatalFailureHelper() - : has_new_fatal_failure_(false), - original_reporter_(GetUnitTestImpl()-> - GetTestPartResultReporterForCurrentThread()) { - GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); -} - -HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { - GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( - original_reporter_); -} - -void HasNewFatalFailureHelper::ReportTestPartResult( - const TestPartResult& result) { - if (result.fatally_failed()) - has_new_fatal_failure_ = true; - original_reporter_->ReportTestPartResult(result); -} - -} // namespace internal - -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest-typed-test.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest-typed-test.cc deleted file mode 100644 index 8677caf732b..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest-typed-test.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2008 Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - - -#include "gtest/gtest-typed-test.h" - -#include "gtest/gtest.h" - -namespace testing { -namespace internal { - -#if GTEST_HAS_TYPED_TEST_P - -// Skips to the first non-space char in str. Returns an empty string if str -// contains only whitespace characters. -static const char* SkipSpaces(const char* str) { - while (IsSpace(*str)) - str++; - return str; -} - -static std::vector SplitIntoTestNames(const char* src) { - std::vector name_vec; - src = SkipSpaces(src); - for (; src != nullptr; src = SkipComma(src)) { - name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); - } - return name_vec; -} - -// Verifies that registered_tests match the test names in -// registered_tests_; returns registered_tests if successful, or -// aborts the program otherwise. -const char* TypedTestSuitePState::VerifyRegisteredTestNames( - const char* file, int line, const char* registered_tests) { - typedef RegisteredTestsMap::const_iterator RegisteredTestIter; - registered_ = true; - - std::vector name_vec = SplitIntoTestNames(registered_tests); - - Message errors; - - std::set tests; - for (std::vector::const_iterator name_it = name_vec.begin(); - name_it != name_vec.end(); ++name_it) { - const std::string& name = *name_it; - if (tests.count(name) != 0) { - errors << "Test " << name << " is listed more than once.\n"; - continue; - } - - bool found = false; - for (RegisteredTestIter it = registered_tests_.begin(); - it != registered_tests_.end(); - ++it) { - if (name == it->first) { - found = true; - break; - } - } - - if (found) { - tests.insert(name); - } else { - errors << "No test named " << name - << " can be found in this test suite.\n"; - } - } - - for (RegisteredTestIter it = registered_tests_.begin(); - it != registered_tests_.end(); - ++it) { - if (tests.count(it->first) == 0) { - errors << "You forgot to list test " << it->first << ".\n"; - } - } - - const std::string& errors_str = errors.GetString(); - if (errors_str != "") { - fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), - errors_str.c_str()); - fflush(stderr); - posix::Abort(); - } - - return registered_tests; -} - -#endif // GTEST_HAS_TYPED_TEST_P - -} // namespace internal -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest.cc deleted file mode 100644 index a5b4e5ac78c..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest.cc +++ /dev/null @@ -1,6177 +0,0 @@ -// Copyright 2005, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -// -// The Google C++ Testing and Mocking Framework (Google Test) - -#include "gtest/gtest.h" -#include "gtest/internal/custom/gtest.h" -#include "gtest/gtest-spi.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include // NOLINT -#include -#include - -#if GTEST_OS_LINUX - -# define GTEST_HAS_GETTIMEOFDAY_ 1 - -# include // NOLINT -# include // NOLINT -# include // NOLINT -// Declares vsnprintf(). This header is not available on Windows. -# include // NOLINT -# include // NOLINT -# include // NOLINT -# include // NOLINT -# include - -#elif GTEST_OS_ZOS -# define GTEST_HAS_GETTIMEOFDAY_ 1 -# include // NOLINT - -// On z/OS we additionally need strings.h for strcasecmp. -# include // NOLINT - -#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. - -# include // NOLINT -# undef min - -#elif GTEST_OS_WINDOWS // We are on Windows proper. - -# include // NOLINT -# undef min - -# include // NOLINT -# include // NOLINT -# include // NOLINT -# include // NOLINT -# include // NOLINT -# include // NOLINT - -# if GTEST_OS_WINDOWS_MINGW -// MinGW has gettimeofday() but not _ftime64(). -# define GTEST_HAS_GETTIMEOFDAY_ 1 -# include // NOLINT -# endif // GTEST_OS_WINDOWS_MINGW - -#else - -// Assume other platforms have gettimeofday(). -# define GTEST_HAS_GETTIMEOFDAY_ 1 - -// cpplint thinks that the header is already included, so we want to -// silence it. -# include // NOLINT -# include // NOLINT - -#endif // GTEST_OS_LINUX - -#if GTEST_HAS_EXCEPTIONS -# include -#endif - -#if GTEST_CAN_STREAM_RESULTS_ -# include // NOLINT -# include // NOLINT -# include // NOLINT -# include // NOLINT -#endif - -#include "src/gtest-internal-inl.h" - -#if GTEST_OS_WINDOWS -# define vsnprintf _vsnprintf -#endif // GTEST_OS_WINDOWS - -#if GTEST_OS_MAC -#ifndef GTEST_OS_IOS -#include -#endif -#endif - -#if GTEST_HAS_ABSL -#include "absl/debugging/failure_signal_handler.h" -#include "absl/debugging/stacktrace.h" -#include "absl/debugging/symbolize.h" -#include "absl/strings/str_cat.h" -#endif // GTEST_HAS_ABSL - -namespace testing { - -using internal::CountIf; -using internal::ForEach; -using internal::GetElementOr; -using internal::Shuffle; - -// Constants. - -// A test whose test suite name or test name matches this filter is -// disabled and not run. -static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; - -// A test suite whose name matches this filter is considered a death -// test suite and will be run before test suites whose name doesn't -// match this filter. -static const char kDeathTestSuiteFilter[] = "*DeathTest:*DeathTest/*"; - -// A test filter that matches everything. -static const char kUniversalFilter[] = "*"; - -// The default output format. -static const char kDefaultOutputFormat[] = "xml"; -// The default output file. -static const char kDefaultOutputFile[] = "test_detail"; - -// The environment variable name for the test shard index. -static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; -// The environment variable name for the total number of test shards. -static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; -// The environment variable name for the test shard status file. -static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; - -namespace internal { - -// The text used in failure messages to indicate the start of the -// stack trace. -const char kStackTraceMarker[] = "\nStack trace:\n"; - -// g_help_flag is true if and only if the --help flag or an equivalent form -// is specified on the command line. -bool g_help_flag = false; - -// Utilty function to Open File for Writing -static FILE* OpenFileForWriting(const std::string& output_file) { - FILE* fileout = nullptr; - FilePath output_file_path(output_file); - FilePath output_dir(output_file_path.RemoveFileName()); - - if (output_dir.CreateDirectoriesRecursively()) { - fileout = posix::FOpen(output_file.c_str(), "w"); - } - if (fileout == nullptr) { - GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\""; - } - return fileout; -} - -} // namespace internal - -// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY -// environment variable. -static const char* GetDefaultFilter() { - const char* const testbridge_test_only = - internal::posix::GetEnv("TESTBRIDGE_TEST_ONLY"); - if (testbridge_test_only != nullptr) { - return testbridge_test_only; - } - return kUniversalFilter; -} - -GTEST_DEFINE_bool_( - also_run_disabled_tests, - internal::BoolFromGTestEnv("also_run_disabled_tests", false), - "Run disabled tests too, in addition to the tests normally being run."); - -GTEST_DEFINE_bool_( - break_on_failure, internal::BoolFromGTestEnv("break_on_failure", false), - "True if and only if a failed assertion should be a debugger " - "break-point."); - -GTEST_DEFINE_bool_(catch_exceptions, - internal::BoolFromGTestEnv("catch_exceptions", true), - "True if and only if " GTEST_NAME_ - " should catch exceptions and treat them as test failures."); - -GTEST_DEFINE_string_( - color, - internal::StringFromGTestEnv("color", "auto"), - "Whether to use colors in the output. Valid values: yes, no, " - "and auto. 'auto' means to use colors if the output is " - "being sent to a terminal and the TERM environment variable " - "is set to a terminal type that supports colors."); - -GTEST_DEFINE_string_( - filter, - internal::StringFromGTestEnv("filter", GetDefaultFilter()), - "A colon-separated list of glob (not regex) patterns " - "for filtering the tests to run, optionally followed by a " - "'-' and a : separated list of negative patterns (tests to " - "exclude). A test is run if it matches one of the positive " - "patterns and does not match any of the negative patterns."); - -GTEST_DEFINE_bool_( - install_failure_signal_handler, - internal::BoolFromGTestEnv("install_failure_signal_handler", false), - "If true and supported on the current platform, " GTEST_NAME_ " should " - "install a signal handler that dumps debugging information when fatal " - "signals are raised."); - -GTEST_DEFINE_bool_(list_tests, false, - "List all tests without running them."); - -// The net priority order after flag processing is thus: -// --gtest_output command line flag -// GTEST_OUTPUT environment variable -// XML_OUTPUT_FILE environment variable -// '' -GTEST_DEFINE_string_( - output, - internal::StringFromGTestEnv("output", - internal::OutputFlagAlsoCheckEnvVar().c_str()), - "A format (defaults to \"xml\" but can be specified to be \"json\"), " - "optionally followed by a colon and an output file name or directory. " - "A directory is indicated by a trailing pathname separator. " - "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " - "If a directory is specified, output files will be created " - "within that directory, with file-names based on the test " - "executable's name and, if necessary, made unique by adding " - "digits."); - -GTEST_DEFINE_bool_(print_time, internal::BoolFromGTestEnv("print_time", true), - "True if and only if " GTEST_NAME_ - " should display elapsed time in text output."); - -GTEST_DEFINE_bool_(print_utf8, internal::BoolFromGTestEnv("print_utf8", true), - "True if and only if " GTEST_NAME_ - " prints UTF8 characters as text."); - -GTEST_DEFINE_int32_( - random_seed, - internal::Int32FromGTestEnv("random_seed", 0), - "Random number seed to use when shuffling test orders. Must be in range " - "[1, 99999], or 0 to use a seed based on the current time."); - -GTEST_DEFINE_int32_( - repeat, - internal::Int32FromGTestEnv("repeat", 1), - "How many times to repeat each test. Specify a negative number " - "for repeating forever. Useful for shaking out flaky tests."); - -GTEST_DEFINE_bool_(show_internal_stack_frames, false, - "True if and only if " GTEST_NAME_ - " should include internal stack frames when " - "printing test failure stack traces."); - -GTEST_DEFINE_bool_(shuffle, internal::BoolFromGTestEnv("shuffle", false), - "True if and only if " GTEST_NAME_ - " should randomize tests' order on every run."); - -GTEST_DEFINE_int32_( - stack_trace_depth, - internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), - "The maximum number of stack frames to print when an " - "assertion fails. The valid range is 0 through 100, inclusive."); - -GTEST_DEFINE_string_( - stream_result_to, - internal::StringFromGTestEnv("stream_result_to", ""), - "This flag specifies the host name and the port number on which to stream " - "test results. Example: \"localhost:555\". The flag is effective only on " - "Linux."); - -GTEST_DEFINE_bool_( - throw_on_failure, - internal::BoolFromGTestEnv("throw_on_failure", false), - "When this flag is specified, a failed assertion will throw an exception " - "if exceptions are enabled or exit the program with a non-zero code " - "otherwise. For use with an external test framework."); - -#if GTEST_USE_OWN_FLAGFILE_FLAG_ -GTEST_DEFINE_string_( - flagfile, - internal::StringFromGTestEnv("flagfile", ""), - "This flag specifies the flagfile to read command-line flags from."); -#endif // GTEST_USE_OWN_FLAGFILE_FLAG_ - -namespace internal { - -// Generates a random number from [0, range), using a Linear -// Congruential Generator (LCG). Crashes if 'range' is 0 or greater -// than kMaxRange. -UInt32 Random::Generate(UInt32 range) { - // These constants are the same as are used in glibc's rand(3). - // Use wider types than necessary to prevent unsigned overflow diagnostics. - state_ = static_cast(1103515245ULL*state_ + 12345U) % kMaxRange; - - GTEST_CHECK_(range > 0) - << "Cannot generate a number in the range [0, 0)."; - GTEST_CHECK_(range <= kMaxRange) - << "Generation of a number in [0, " << range << ") was requested, " - << "but this can only generate numbers in [0, " << kMaxRange << ")."; - - // Converting via modulus introduces a bit of downward bias, but - // it's simple, and a linear congruential generator isn't too good - // to begin with. - return state_ % range; -} - -// GTestIsInitialized() returns true if and only if the user has initialized -// Google Test. Useful for catching the user mistake of not initializing -// Google Test before calling RUN_ALL_TESTS(). -static bool GTestIsInitialized() { return GetArgvs().size() > 0; } - -// Iterates over a vector of TestSuites, keeping a running sum of the -// results of calling a given int-returning method on each. -// Returns the sum. -static int SumOverTestSuiteList(const std::vector& case_list, - int (TestSuite::*method)() const) { - int sum = 0; - for (size_t i = 0; i < case_list.size(); i++) { - sum += (case_list[i]->*method)(); - } - return sum; -} - -// Returns true if and only if the test suite passed. -static bool TestSuitePassed(const TestSuite* test_suite) { - return test_suite->should_run() && test_suite->Passed(); -} - -// Returns true if and only if the test suite failed. -static bool TestSuiteFailed(const TestSuite* test_suite) { - return test_suite->should_run() && test_suite->Failed(); -} - -// Returns true if and only if test_suite contains at least one test that -// should run. -static bool ShouldRunTestSuite(const TestSuite* test_suite) { - return test_suite->should_run(); -} - -// AssertHelper constructor. -AssertHelper::AssertHelper(TestPartResult::Type type, - const char* file, - int line, - const char* message) - : data_(new AssertHelperData(type, file, line, message)) { -} - -AssertHelper::~AssertHelper() { - delete data_; -} - -// Message assignment, for assertion streaming support. -void AssertHelper::operator=(const Message& message) const { - UnitTest::GetInstance()-> - AddTestPartResult(data_->type, data_->file, data_->line, - AppendUserMessage(data_->message, message), - UnitTest::GetInstance()->impl() - ->CurrentOsStackTraceExceptTop(1) - // Skips the stack frame for this function itself. - ); // NOLINT -} - -// A copy of all command line arguments. Set by InitGoogleTest(). -static ::std::vector g_argvs; - -::std::vector GetArgvs() { -#if defined(GTEST_CUSTOM_GET_ARGVS_) - // GTEST_CUSTOM_GET_ARGVS_() may return a container of std::string or - // ::string. This code converts it to the appropriate type. - const auto& custom = GTEST_CUSTOM_GET_ARGVS_(); - return ::std::vector(custom.begin(), custom.end()); -#else // defined(GTEST_CUSTOM_GET_ARGVS_) - return g_argvs; -#endif // defined(GTEST_CUSTOM_GET_ARGVS_) -} - -// Returns the current application's name, removing directory path if that -// is present. -FilePath GetCurrentExecutableName() { - FilePath result; - -#if GTEST_OS_WINDOWS || GTEST_OS_OS2 - result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe")); -#else - result.Set(FilePath(GetArgvs()[0])); -#endif // GTEST_OS_WINDOWS - - return result.RemoveDirectoryName(); -} - -// Functions for processing the gtest_output flag. - -// Returns the output format, or "" for normal printed output. -std::string UnitTestOptions::GetOutputFormat() { - const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); - const char* const colon = strchr(gtest_output_flag, ':'); - return (colon == nullptr) - ? std::string(gtest_output_flag) - : std::string(gtest_output_flag, - static_cast(colon - gtest_output_flag)); -} - -// Returns the name of the requested output file, or the default if none -// was explicitly specified. -std::string UnitTestOptions::GetAbsolutePathToOutputFile() { - const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); - - std::string format = GetOutputFormat(); - if (format.empty()) - format = std::string(kDefaultOutputFormat); - - const char* const colon = strchr(gtest_output_flag, ':'); - if (colon == nullptr) - return internal::FilePath::MakeFileName( - internal::FilePath( - UnitTest::GetInstance()->original_working_dir()), - internal::FilePath(kDefaultOutputFile), 0, - format.c_str()).string(); - - internal::FilePath output_name(colon + 1); - if (!output_name.IsAbsolutePath()) - output_name = internal::FilePath::ConcatPaths( - internal::FilePath(UnitTest::GetInstance()->original_working_dir()), - internal::FilePath(colon + 1)); - - if (!output_name.IsDirectory()) - return output_name.string(); - - internal::FilePath result(internal::FilePath::GenerateUniqueFileName( - output_name, internal::GetCurrentExecutableName(), - GetOutputFormat().c_str())); - return result.string(); -} - -// Returns true if and only if the wildcard pattern matches the string. -// The first ':' or '\0' character in pattern marks the end of it. -// -// This recursive algorithm isn't very efficient, but is clear and -// works well enough for matching test names, which are short. -bool UnitTestOptions::PatternMatchesString(const char *pattern, - const char *str) { - switch (*pattern) { - case '\0': - case ':': // Either ':' or '\0' marks the end of the pattern. - return *str == '\0'; - case '?': // Matches any single character. - return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); - case '*': // Matches any string (possibly empty) of characters. - return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || - PatternMatchesString(pattern + 1, str); - default: // Non-special character. Matches itself. - return *pattern == *str && - PatternMatchesString(pattern + 1, str + 1); - } -} - -bool UnitTestOptions::MatchesFilter( - const std::string& name, const char* filter) { - const char *cur_pattern = filter; - for (;;) { - if (PatternMatchesString(cur_pattern, name.c_str())) { - return true; - } - - // Finds the next pattern in the filter. - cur_pattern = strchr(cur_pattern, ':'); - - // Returns if no more pattern can be found. - if (cur_pattern == nullptr) { - return false; - } - - // Skips the pattern separater (the ':' character). - cur_pattern++; - } -} - -// Returns true if and only if the user-specified filter matches the test -// suite name and the test name. -bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name, - const std::string& test_name) { - const std::string& full_name = test_suite_name + "." + test_name.c_str(); - - // Split --gtest_filter at '-', if there is one, to separate into - // positive filter and negative filter portions - const char* const p = GTEST_FLAG(filter).c_str(); - const char* const dash = strchr(p, '-'); - std::string positive; - std::string negative; - if (dash == nullptr) { - positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter - negative = ""; - } else { - positive = std::string(p, dash); // Everything up to the dash - negative = std::string(dash + 1); // Everything after the dash - if (positive.empty()) { - // Treat '-test1' as the same as '*-test1' - positive = kUniversalFilter; - } - } - - // A filter is a colon-separated list of patterns. It matches a - // test if any pattern in it matches the test. - return (MatchesFilter(full_name, positive.c_str()) && - !MatchesFilter(full_name, negative.c_str())); -} - -#if GTEST_HAS_SEH -// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the -// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. -// This function is useful as an __except condition. -int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { - // Google Test should handle a SEH exception if: - // 1. the user wants it to, AND - // 2. this is not a breakpoint exception, AND - // 3. this is not a C++ exception (VC++ implements them via SEH, - // apparently). - // - // SEH exception code for C++ exceptions. - // (see http://support.microsoft.com/kb/185294 for more information). - const DWORD kCxxExceptionCode = 0xe06d7363; - - bool should_handle = true; - - if (!GTEST_FLAG(catch_exceptions)) - should_handle = false; - else if (exception_code == EXCEPTION_BREAKPOINT) - should_handle = false; - else if (exception_code == kCxxExceptionCode) - should_handle = false; - - return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; -} -#endif // GTEST_HAS_SEH - -} // namespace internal - -// The c'tor sets this object as the test part result reporter used by -// Google Test. The 'result' parameter specifies where to report the -// results. Intercepts only failures from the current thread. -ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( - TestPartResultArray* result) - : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), - result_(result) { - Init(); -} - -// The c'tor sets this object as the test part result reporter used by -// Google Test. The 'result' parameter specifies where to report the -// results. -ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( - InterceptMode intercept_mode, TestPartResultArray* result) - : intercept_mode_(intercept_mode), - result_(result) { - Init(); -} - -void ScopedFakeTestPartResultReporter::Init() { - internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - if (intercept_mode_ == INTERCEPT_ALL_THREADS) { - old_reporter_ = impl->GetGlobalTestPartResultReporter(); - impl->SetGlobalTestPartResultReporter(this); - } else { - old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); - impl->SetTestPartResultReporterForCurrentThread(this); - } -} - -// The d'tor restores the test part result reporter used by Google Test -// before. -ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { - internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - if (intercept_mode_ == INTERCEPT_ALL_THREADS) { - impl->SetGlobalTestPartResultReporter(old_reporter_); - } else { - impl->SetTestPartResultReporterForCurrentThread(old_reporter_); - } -} - -// Increments the test part result count and remembers the result. -// This method is from the TestPartResultReporterInterface interface. -void ScopedFakeTestPartResultReporter::ReportTestPartResult( - const TestPartResult& result) { - result_->Append(result); -} - -namespace internal { - -// Returns the type ID of ::testing::Test. We should always call this -// instead of GetTypeId< ::testing::Test>() to get the type ID of -// testing::Test. This is to work around a suspected linker bug when -// using Google Test as a framework on Mac OS X. The bug causes -// GetTypeId< ::testing::Test>() to return different values depending -// on whether the call is from the Google Test framework itself or -// from user test code. GetTestTypeId() is guaranteed to always -// return the same value, as it always calls GetTypeId<>() from the -// gtest.cc, which is within the Google Test framework. -TypeId GetTestTypeId() { - return GetTypeId(); -} - -// The value of GetTestTypeId() as seen from within the Google Test -// library. This is solely for testing GetTestTypeId(). -extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); - -// This predicate-formatter checks that 'results' contains a test part -// failure of the given type and that the failure message contains the -// given substring. -static AssertionResult HasOneFailure(const char* /* results_expr */, - const char* /* type_expr */, - const char* /* substr_expr */, - const TestPartResultArray& results, - TestPartResult::Type type, - const std::string& substr) { - const std::string expected(type == TestPartResult::kFatalFailure ? - "1 fatal failure" : - "1 non-fatal failure"); - Message msg; - if (results.size() != 1) { - msg << "Expected: " << expected << "\n" - << " Actual: " << results.size() << " failures"; - for (int i = 0; i < results.size(); i++) { - msg << "\n" << results.GetTestPartResult(i); - } - return AssertionFailure() << msg; - } - - const TestPartResult& r = results.GetTestPartResult(0); - if (r.type() != type) { - return AssertionFailure() << "Expected: " << expected << "\n" - << " Actual:\n" - << r; - } - - if (strstr(r.message(), substr.c_str()) == nullptr) { - return AssertionFailure() << "Expected: " << expected << " containing \"" - << substr << "\"\n" - << " Actual:\n" - << r; - } - - return AssertionSuccess(); -} - -// The constructor of SingleFailureChecker remembers where to look up -// test part results, what type of failure we expect, and what -// substring the failure message should contain. -SingleFailureChecker::SingleFailureChecker(const TestPartResultArray* results, - TestPartResult::Type type, - const std::string& substr) - : results_(results), type_(type), substr_(substr) {} - -// The destructor of SingleFailureChecker verifies that the given -// TestPartResultArray contains exactly one failure that has the given -// type and contains the given substring. If that's not the case, a -// non-fatal failure will be generated. -SingleFailureChecker::~SingleFailureChecker() { - EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); -} - -DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( - UnitTestImpl* unit_test) : unit_test_(unit_test) {} - -void DefaultGlobalTestPartResultReporter::ReportTestPartResult( - const TestPartResult& result) { - unit_test_->current_test_result()->AddTestPartResult(result); - unit_test_->listeners()->repeater()->OnTestPartResult(result); -} - -DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( - UnitTestImpl* unit_test) : unit_test_(unit_test) {} - -void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( - const TestPartResult& result) { - unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); -} - -// Returns the global test part result reporter. -TestPartResultReporterInterface* -UnitTestImpl::GetGlobalTestPartResultReporter() { - internal::MutexLock lock(&global_test_part_result_reporter_mutex_); - return global_test_part_result_repoter_; -} - -// Sets the global test part result reporter. -void UnitTestImpl::SetGlobalTestPartResultReporter( - TestPartResultReporterInterface* reporter) { - internal::MutexLock lock(&global_test_part_result_reporter_mutex_); - global_test_part_result_repoter_ = reporter; -} - -// Returns the test part result reporter for the current thread. -TestPartResultReporterInterface* -UnitTestImpl::GetTestPartResultReporterForCurrentThread() { - return per_thread_test_part_result_reporter_.get(); -} - -// Sets the test part result reporter for the current thread. -void UnitTestImpl::SetTestPartResultReporterForCurrentThread( - TestPartResultReporterInterface* reporter) { - per_thread_test_part_result_reporter_.set(reporter); -} - -// Gets the number of successful test suites. -int UnitTestImpl::successful_test_suite_count() const { - return CountIf(test_suites_, TestSuitePassed); -} - -// Gets the number of failed test suites. -int UnitTestImpl::failed_test_suite_count() const { - return CountIf(test_suites_, TestSuiteFailed); -} - -// Gets the number of all test suites. -int UnitTestImpl::total_test_suite_count() const { - return static_cast(test_suites_.size()); -} - -// Gets the number of all test suites that contain at least one test -// that should run. -int UnitTestImpl::test_suite_to_run_count() const { - return CountIf(test_suites_, ShouldRunTestSuite); -} - -// Gets the number of successful tests. -int UnitTestImpl::successful_test_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::successful_test_count); -} - -// Gets the number of skipped tests. -int UnitTestImpl::skipped_test_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::skipped_test_count); -} - -// Gets the number of failed tests. -int UnitTestImpl::failed_test_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::failed_test_count); -} - -// Gets the number of disabled tests that will be reported in the XML report. -int UnitTestImpl::reportable_disabled_test_count() const { - return SumOverTestSuiteList(test_suites_, - &TestSuite::reportable_disabled_test_count); -} - -// Gets the number of disabled tests. -int UnitTestImpl::disabled_test_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::disabled_test_count); -} - -// Gets the number of tests to be printed in the XML report. -int UnitTestImpl::reportable_test_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::reportable_test_count); -} - -// Gets the number of all tests. -int UnitTestImpl::total_test_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::total_test_count); -} - -// Gets the number of tests that should run. -int UnitTestImpl::test_to_run_count() const { - return SumOverTestSuiteList(test_suites_, &TestSuite::test_to_run_count); -} - -// Returns the current OS stack trace as an std::string. -// -// The maximum number of stack frames to be included is specified by -// the gtest_stack_trace_depth flag. The skip_count parameter -// specifies the number of top frames to be skipped, which doesn't -// count against the number of frames to be included. -// -// For example, if Foo() calls Bar(), which in turn calls -// CurrentOsStackTraceExceptTop(1), Foo() will be included in the -// trace but Bar() and CurrentOsStackTraceExceptTop() won't. -std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { - return os_stack_trace_getter()->CurrentStackTrace( - static_cast(GTEST_FLAG(stack_trace_depth)), - skip_count + 1 - // Skips the user-specified number of frames plus this function - // itself. - ); // NOLINT -} - -// Returns the current time in milliseconds. -TimeInMillis GetTimeInMillis() { -#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) - // Difference between 1970-01-01 and 1601-01-01 in milliseconds. - // http://analogous.blogspot.com/2005/04/epoch.html - const TimeInMillis kJavaEpochToWinFileTimeDelta = - static_cast(116444736UL) * 100000UL; - const DWORD kTenthMicrosInMilliSecond = 10000; - - SYSTEMTIME now_systime; - FILETIME now_filetime; - ULARGE_INTEGER now_int64; - GetSystemTime(&now_systime); - if (SystemTimeToFileTime(&now_systime, &now_filetime)) { - now_int64.LowPart = now_filetime.dwLowDateTime; - now_int64.HighPart = now_filetime.dwHighDateTime; - now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - - kJavaEpochToWinFileTimeDelta; - return now_int64.QuadPart; - } - return 0; -#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ - __timeb64 now; - - // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 - // (deprecated function) there. - GTEST_DISABLE_MSC_DEPRECATED_PUSH_() - _ftime64(&now); - GTEST_DISABLE_MSC_DEPRECATED_POP_() - - return static_cast(now.time) * 1000 + now.millitm; -#elif GTEST_HAS_GETTIMEOFDAY_ - struct timeval now; - gettimeofday(&now, nullptr); - return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; -#else -# error "Don't know how to get the current time on your system." -#endif -} - -// Utilities - -// class String. - -#if GTEST_OS_WINDOWS_MOBILE -// Creates a UTF-16 wide string from the given ANSI string, allocating -// memory using new. The caller is responsible for deleting the return -// value using delete[]. Returns the wide string, or NULL if the -// input is NULL. -LPCWSTR String::AnsiToUtf16(const char* ansi) { - if (!ansi) return nullptr; - const int length = strlen(ansi); - const int unicode_length = - MultiByteToWideChar(CP_ACP, 0, ansi, length, nullptr, 0); - WCHAR* unicode = new WCHAR[unicode_length + 1]; - MultiByteToWideChar(CP_ACP, 0, ansi, length, - unicode, unicode_length); - unicode[unicode_length] = 0; - return unicode; -} - -// Creates an ANSI string from the given wide string, allocating -// memory using new. The caller is responsible for deleting the return -// value using delete[]. Returns the ANSI string, or NULL if the -// input is NULL. -const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { - if (!utf16_str) return nullptr; - const int ansi_length = WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, nullptr, - 0, nullptr, nullptr); - char* ansi = new char[ansi_length + 1]; - WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, ansi, ansi_length, nullptr, - nullptr); - ansi[ansi_length] = 0; - return ansi; -} - -#endif // GTEST_OS_WINDOWS_MOBILE - -// Compares two C strings. Returns true if and only if they have the same -// content. -// -// Unlike strcmp(), this function can handle NULL argument(s). A NULL -// C string is considered different to any non-NULL C string, -// including the empty string. -bool String::CStringEquals(const char * lhs, const char * rhs) { - if (lhs == nullptr) return rhs == nullptr; - - if (rhs == nullptr) return false; - - return strcmp(lhs, rhs) == 0; -} - -#if GTEST_HAS_STD_WSTRING - -// Converts an array of wide chars to a narrow string using the UTF-8 -// encoding, and streams the result to the given Message object. -static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, - Message* msg) { - for (size_t i = 0; i != length; ) { // NOLINT - if (wstr[i] != L'\0') { - *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); - while (i != length && wstr[i] != L'\0') - i++; - } else { - *msg << '\0'; - i++; - } - } -} - -#endif // GTEST_HAS_STD_WSTRING - -void SplitString(const ::std::string& str, char delimiter, - ::std::vector< ::std::string>* dest) { - ::std::vector< ::std::string> parsed; - ::std::string::size_type pos = 0; - while (::testing::internal::AlwaysTrue()) { - const ::std::string::size_type colon = str.find(delimiter, pos); - if (colon == ::std::string::npos) { - parsed.push_back(str.substr(pos)); - break; - } else { - parsed.push_back(str.substr(pos, colon - pos)); - pos = colon + 1; - } - } - dest->swap(parsed); -} - -} // namespace internal - -// Constructs an empty Message. -// We allocate the stringstream separately because otherwise each use of -// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's -// stack frame leading to huge stack frames in some cases; gcc does not reuse -// the stack space. -Message::Message() : ss_(new ::std::stringstream) { - // By default, we want there to be enough precision when printing - // a double to a Message. - *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); -} - -// These two overloads allow streaming a wide C string to a Message -// using the UTF-8 encoding. -Message& Message::operator <<(const wchar_t* wide_c_str) { - return *this << internal::String::ShowWideCString(wide_c_str); -} -Message& Message::operator <<(wchar_t* wide_c_str) { - return *this << internal::String::ShowWideCString(wide_c_str); -} - -#if GTEST_HAS_STD_WSTRING -// Converts the given wide string to a narrow string using the UTF-8 -// encoding, and streams the result to this Message object. -Message& Message::operator <<(const ::std::wstring& wstr) { - internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); - return *this; -} -#endif // GTEST_HAS_STD_WSTRING - -// Gets the text streamed to this object so far as an std::string. -// Each '\0' character in the buffer is replaced with "\\0". -std::string Message::GetString() const { - return internal::StringStreamToString(ss_.get()); -} - -// AssertionResult constructors. -// Used in EXPECT_TRUE/FALSE(assertion_result). -AssertionResult::AssertionResult(const AssertionResult& other) - : success_(other.success_), - message_(other.message_.get() != nullptr - ? new ::std::string(*other.message_) - : static_cast< ::std::string*>(nullptr)) {} - -// Swaps two AssertionResults. -void AssertionResult::swap(AssertionResult& other) { - using std::swap; - swap(success_, other.success_); - swap(message_, other.message_); -} - -// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. -AssertionResult AssertionResult::operator!() const { - AssertionResult negation(!success_); - if (message_.get() != nullptr) negation << *message_; - return negation; -} - -// Makes a successful assertion result. -AssertionResult AssertionSuccess() { - return AssertionResult(true); -} - -// Makes a failed assertion result. -AssertionResult AssertionFailure() { - return AssertionResult(false); -} - -// Makes a failed assertion result with the given failure message. -// Deprecated; use AssertionFailure() << message. -AssertionResult AssertionFailure(const Message& message) { - return AssertionFailure() << message; -} - -namespace internal { - -namespace edit_distance { -std::vector CalculateOptimalEdits(const std::vector& left, - const std::vector& right) { - std::vector > costs( - left.size() + 1, std::vector(right.size() + 1)); - std::vector > best_move( - left.size() + 1, std::vector(right.size() + 1)); - - // Populate for empty right. - for (size_t l_i = 0; l_i < costs.size(); ++l_i) { - costs[l_i][0] = static_cast(l_i); - best_move[l_i][0] = kRemove; - } - // Populate for empty left. - for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) { - costs[0][r_i] = static_cast(r_i); - best_move[0][r_i] = kAdd; - } - - for (size_t l_i = 0; l_i < left.size(); ++l_i) { - for (size_t r_i = 0; r_i < right.size(); ++r_i) { - if (left[l_i] == right[r_i]) { - // Found a match. Consume it. - costs[l_i + 1][r_i + 1] = costs[l_i][r_i]; - best_move[l_i + 1][r_i + 1] = kMatch; - continue; - } - - const double add = costs[l_i + 1][r_i]; - const double remove = costs[l_i][r_i + 1]; - const double replace = costs[l_i][r_i]; - if (add < remove && add < replace) { - costs[l_i + 1][r_i + 1] = add + 1; - best_move[l_i + 1][r_i + 1] = kAdd; - } else if (remove < add && remove < replace) { - costs[l_i + 1][r_i + 1] = remove + 1; - best_move[l_i + 1][r_i + 1] = kRemove; - } else { - // We make replace a little more expensive than add/remove to lower - // their priority. - costs[l_i + 1][r_i + 1] = replace + 1.00001; - best_move[l_i + 1][r_i + 1] = kReplace; - } - } - } - - // Reconstruct the best path. We do it in reverse order. - std::vector best_path; - for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) { - EditType move = best_move[l_i][r_i]; - best_path.push_back(move); - l_i -= move != kAdd; - r_i -= move != kRemove; - } - std::reverse(best_path.begin(), best_path.end()); - return best_path; -} - -namespace { - -// Helper class to convert string into ids with deduplication. -class InternalStrings { - public: - size_t GetId(const std::string& str) { - IdMap::iterator it = ids_.find(str); - if (it != ids_.end()) return it->second; - size_t id = ids_.size(); - return ids_[str] = id; - } - - private: - typedef std::map IdMap; - IdMap ids_; -}; - -} // namespace - -std::vector CalculateOptimalEdits( - const std::vector& left, - const std::vector& right) { - std::vector left_ids, right_ids; - { - InternalStrings intern_table; - for (size_t i = 0; i < left.size(); ++i) { - left_ids.push_back(intern_table.GetId(left[i])); - } - for (size_t i = 0; i < right.size(); ++i) { - right_ids.push_back(intern_table.GetId(right[i])); - } - } - return CalculateOptimalEdits(left_ids, right_ids); -} - -namespace { - -// Helper class that holds the state for one hunk and prints it out to the -// stream. -// It reorders adds/removes when possible to group all removes before all -// adds. It also adds the hunk header before printint into the stream. -class Hunk { - public: - Hunk(size_t left_start, size_t right_start) - : left_start_(left_start), - right_start_(right_start), - adds_(), - removes_(), - common_() {} - - void PushLine(char edit, const char* line) { - switch (edit) { - case ' ': - ++common_; - FlushEdits(); - hunk_.push_back(std::make_pair(' ', line)); - break; - case '-': - ++removes_; - hunk_removes_.push_back(std::make_pair('-', line)); - break; - case '+': - ++adds_; - hunk_adds_.push_back(std::make_pair('+', line)); - break; - } - } - - void PrintTo(std::ostream* os) { - PrintHeader(os); - FlushEdits(); - for (std::list >::const_iterator it = - hunk_.begin(); - it != hunk_.end(); ++it) { - *os << it->first << it->second << "\n"; - } - } - - bool has_edits() const { return adds_ || removes_; } - - private: - void FlushEdits() { - hunk_.splice(hunk_.end(), hunk_removes_); - hunk_.splice(hunk_.end(), hunk_adds_); - } - - // Print a unified diff header for one hunk. - // The format is - // "@@ -, +, @@" - // where the left/right parts are omitted if unnecessary. - void PrintHeader(std::ostream* ss) const { - *ss << "@@ "; - if (removes_) { - *ss << "-" << left_start_ << "," << (removes_ + common_); - } - if (removes_ && adds_) { - *ss << " "; - } - if (adds_) { - *ss << "+" << right_start_ << "," << (adds_ + common_); - } - *ss << " @@\n"; - } - - size_t left_start_, right_start_; - size_t adds_, removes_, common_; - std::list > hunk_, hunk_adds_, hunk_removes_; -}; - -} // namespace - -// Create a list of diff hunks in Unified diff format. -// Each hunk has a header generated by PrintHeader above plus a body with -// lines prefixed with ' ' for no change, '-' for deletion and '+' for -// addition. -// 'context' represents the desired unchanged prefix/suffix around the diff. -// If two hunks are close enough that their contexts overlap, then they are -// joined into one hunk. -std::string CreateUnifiedDiff(const std::vector& left, - const std::vector& right, - size_t context) { - const std::vector edits = CalculateOptimalEdits(left, right); - - size_t l_i = 0, r_i = 0, edit_i = 0; - std::stringstream ss; - while (edit_i < edits.size()) { - // Find first edit. - while (edit_i < edits.size() && edits[edit_i] == kMatch) { - ++l_i; - ++r_i; - ++edit_i; - } - - // Find the first line to include in the hunk. - const size_t prefix_context = std::min(l_i, context); - Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1); - for (size_t i = prefix_context; i > 0; --i) { - hunk.PushLine(' ', left[l_i - i].c_str()); - } - - // Iterate the edits until we found enough suffix for the hunk or the input - // is over. - size_t n_suffix = 0; - for (; edit_i < edits.size(); ++edit_i) { - if (n_suffix >= context) { - // Continue only if the next hunk is very close. - auto it = edits.begin() + static_cast(edit_i); - while (it != edits.end() && *it == kMatch) ++it; - if (it == edits.end() || - static_cast(it - edits.begin()) - edit_i >= context) { - // There is no next edit or it is too far away. - break; - } - } - - EditType edit = edits[edit_i]; - // Reset count when a non match is found. - n_suffix = edit == kMatch ? n_suffix + 1 : 0; - - if (edit == kMatch || edit == kRemove || edit == kReplace) { - hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str()); - } - if (edit == kAdd || edit == kReplace) { - hunk.PushLine('+', right[r_i].c_str()); - } - - // Advance indices, depending on edit type. - l_i += edit != kAdd; - r_i += edit != kRemove; - } - - if (!hunk.has_edits()) { - // We are done. We don't want this hunk. - break; - } - - hunk.PrintTo(&ss); - } - return ss.str(); -} - -} // namespace edit_distance - -namespace { - -// The string representation of the values received in EqFailure() are already -// escaped. Split them on escaped '\n' boundaries. Leave all other escaped -// characters the same. -std::vector SplitEscapedString(const std::string& str) { - std::vector lines; - size_t start = 0, end = str.size(); - if (end > 2 && str[0] == '"' && str[end - 1] == '"') { - ++start; - --end; - } - bool escaped = false; - for (size_t i = start; i + 1 < end; ++i) { - if (escaped) { - escaped = false; - if (str[i] == 'n') { - lines.push_back(str.substr(start, i - start - 1)); - start = i + 1; - } - } else { - escaped = str[i] == '\\'; - } - } - lines.push_back(str.substr(start, end - start)); - return lines; -} - -} // namespace - -// Constructs and returns the message for an equality assertion -// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. -// -// The first four parameters are the expressions used in the assertion -// and their values, as strings. For example, for ASSERT_EQ(foo, bar) -// where foo is 5 and bar is 6, we have: -// -// lhs_expression: "foo" -// rhs_expression: "bar" -// lhs_value: "5" -// rhs_value: "6" -// -// The ignoring_case parameter is true if and only if the assertion is a -// *_STRCASEEQ*. When it's true, the string "Ignoring case" will -// be inserted into the message. -AssertionResult EqFailure(const char* lhs_expression, - const char* rhs_expression, - const std::string& lhs_value, - const std::string& rhs_value, - bool ignoring_case) { - Message msg; - msg << "Expected equality of these values:"; - msg << "\n " << lhs_expression; - if (lhs_value != lhs_expression) { - msg << "\n Which is: " << lhs_value; - } - msg << "\n " << rhs_expression; - if (rhs_value != rhs_expression) { - msg << "\n Which is: " << rhs_value; - } - - if (ignoring_case) { - msg << "\nIgnoring case"; - } - - if (!lhs_value.empty() && !rhs_value.empty()) { - const std::vector lhs_lines = - SplitEscapedString(lhs_value); - const std::vector rhs_lines = - SplitEscapedString(rhs_value); - if (lhs_lines.size() > 1 || rhs_lines.size() > 1) { - msg << "\nWith diff:\n" - << edit_distance::CreateUnifiedDiff(lhs_lines, rhs_lines); - } - } - - return AssertionFailure() << msg; -} - -// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. -std::string GetBoolAssertionFailureMessage( - const AssertionResult& assertion_result, - const char* expression_text, - const char* actual_predicate_value, - const char* expected_predicate_value) { - const char* actual_message = assertion_result.message(); - Message msg; - msg << "Value of: " << expression_text - << "\n Actual: " << actual_predicate_value; - if (actual_message[0] != '\0') - msg << " (" << actual_message << ")"; - msg << "\nExpected: " << expected_predicate_value; - return msg.GetString(); -} - -// Helper function for implementing ASSERT_NEAR. -AssertionResult DoubleNearPredFormat(const char* expr1, - const char* expr2, - const char* abs_error_expr, - double val1, - double val2, - double abs_error) { - const double diff = fabs(val1 - val2); - if (diff <= abs_error) return AssertionSuccess(); - - return AssertionFailure() - << "The difference between " << expr1 << " and " << expr2 - << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" - << expr1 << " evaluates to " << val1 << ",\n" - << expr2 << " evaluates to " << val2 << ", and\n" - << abs_error_expr << " evaluates to " << abs_error << "."; -} - - -// Helper template for implementing FloatLE() and DoubleLE(). -template -AssertionResult FloatingPointLE(const char* expr1, - const char* expr2, - RawType val1, - RawType val2) { - // Returns success if val1 is less than val2, - if (val1 < val2) { - return AssertionSuccess(); - } - - // or if val1 is almost equal to val2. - const FloatingPoint lhs(val1), rhs(val2); - if (lhs.AlmostEquals(rhs)) { - return AssertionSuccess(); - } - - // Note that the above two checks will both fail if either val1 or - // val2 is NaN, as the IEEE floating-point standard requires that - // any predicate involving a NaN must return false. - - ::std::stringstream val1_ss; - val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) - << val1; - - ::std::stringstream val2_ss; - val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) - << val2; - - return AssertionFailure() - << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" - << " Actual: " << StringStreamToString(&val1_ss) << " vs " - << StringStreamToString(&val2_ss); -} - -} // namespace internal - -// Asserts that val1 is less than, or almost equal to, val2. Fails -// otherwise. In particular, it fails if either val1 or val2 is NaN. -AssertionResult FloatLE(const char* expr1, const char* expr2, - float val1, float val2) { - return internal::FloatingPointLE(expr1, expr2, val1, val2); -} - -// Asserts that val1 is less than, or almost equal to, val2. Fails -// otherwise. In particular, it fails if either val1 or val2 is NaN. -AssertionResult DoubleLE(const char* expr1, const char* expr2, - double val1, double val2) { - return internal::FloatingPointLE(expr1, expr2, val1, val2); -} - -namespace internal { - -// The helper function for {ASSERT|EXPECT}_EQ with int or enum -// arguments. -AssertionResult CmpHelperEQ(const char* lhs_expression, - const char* rhs_expression, - BiggestInt lhs, - BiggestInt rhs) { - if (lhs == rhs) { - return AssertionSuccess(); - } - - return EqFailure(lhs_expression, - rhs_expression, - FormatForComparisonFailureMessage(lhs, rhs), - FormatForComparisonFailureMessage(rhs, lhs), - false); -} - -// A macro for implementing the helper functions needed to implement -// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here -// just to avoid copy-and-paste of similar code. -#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ -AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ - BiggestInt val1, BiggestInt val2) {\ - if (val1 op val2) {\ - return AssertionSuccess();\ - } else {\ - return AssertionFailure() \ - << "Expected: (" << expr1 << ") " #op " (" << expr2\ - << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ - << " vs " << FormatForComparisonFailureMessage(val2, val1);\ - }\ -} - -// Implements the helper function for {ASSERT|EXPECT}_NE with int or -// enum arguments. -GTEST_IMPL_CMP_HELPER_(NE, !=) -// Implements the helper function for {ASSERT|EXPECT}_LE with int or -// enum arguments. -GTEST_IMPL_CMP_HELPER_(LE, <=) -// Implements the helper function for {ASSERT|EXPECT}_LT with int or -// enum arguments. -GTEST_IMPL_CMP_HELPER_(LT, < ) -// Implements the helper function for {ASSERT|EXPECT}_GE with int or -// enum arguments. -GTEST_IMPL_CMP_HELPER_(GE, >=) -// Implements the helper function for {ASSERT|EXPECT}_GT with int or -// enum arguments. -GTEST_IMPL_CMP_HELPER_(GT, > ) - -#undef GTEST_IMPL_CMP_HELPER_ - -// The helper function for {ASSERT|EXPECT}_STREQ. -AssertionResult CmpHelperSTREQ(const char* lhs_expression, - const char* rhs_expression, - const char* lhs, - const char* rhs) { - if (String::CStringEquals(lhs, rhs)) { - return AssertionSuccess(); - } - - return EqFailure(lhs_expression, - rhs_expression, - PrintToString(lhs), - PrintToString(rhs), - false); -} - -// The helper function for {ASSERT|EXPECT}_STRCASEEQ. -AssertionResult CmpHelperSTRCASEEQ(const char* lhs_expression, - const char* rhs_expression, - const char* lhs, - const char* rhs) { - if (String::CaseInsensitiveCStringEquals(lhs, rhs)) { - return AssertionSuccess(); - } - - return EqFailure(lhs_expression, - rhs_expression, - PrintToString(lhs), - PrintToString(rhs), - true); -} - -// The helper function for {ASSERT|EXPECT}_STRNE. -AssertionResult CmpHelperSTRNE(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2) { - if (!String::CStringEquals(s1, s2)) { - return AssertionSuccess(); - } else { - return AssertionFailure() << "Expected: (" << s1_expression << ") != (" - << s2_expression << "), actual: \"" - << s1 << "\" vs \"" << s2 << "\""; - } -} - -// The helper function for {ASSERT|EXPECT}_STRCASENE. -AssertionResult CmpHelperSTRCASENE(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2) { - if (!String::CaseInsensitiveCStringEquals(s1, s2)) { - return AssertionSuccess(); - } else { - return AssertionFailure() - << "Expected: (" << s1_expression << ") != (" - << s2_expression << ") (ignoring case), actual: \"" - << s1 << "\" vs \"" << s2 << "\""; - } -} - -} // namespace internal - -namespace { - -// Helper functions for implementing IsSubString() and IsNotSubstring(). - -// This group of overloaded functions return true if and only if needle -// is a substring of haystack. NULL is considered a substring of -// itself only. - -bool IsSubstringPred(const char* needle, const char* haystack) { - if (needle == nullptr || haystack == nullptr) return needle == haystack; - - return strstr(haystack, needle) != nullptr; -} - -bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { - if (needle == nullptr || haystack == nullptr) return needle == haystack; - - return wcsstr(haystack, needle) != nullptr; -} - -// StringType here can be either ::std::string or ::std::wstring. -template -bool IsSubstringPred(const StringType& needle, - const StringType& haystack) { - return haystack.find(needle) != StringType::npos; -} - -// This function implements either IsSubstring() or IsNotSubstring(), -// depending on the value of the expected_to_be_substring parameter. -// StringType here can be const char*, const wchar_t*, ::std::string, -// or ::std::wstring. -template -AssertionResult IsSubstringImpl( - bool expected_to_be_substring, - const char* needle_expr, const char* haystack_expr, - const StringType& needle, const StringType& haystack) { - if (IsSubstringPred(needle, haystack) == expected_to_be_substring) - return AssertionSuccess(); - - const bool is_wide_string = sizeof(needle[0]) > 1; - const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; - return AssertionFailure() - << "Value of: " << needle_expr << "\n" - << " Actual: " << begin_string_quote << needle << "\"\n" - << "Expected: " << (expected_to_be_substring ? "" : "not ") - << "a substring of " << haystack_expr << "\n" - << "Which is: " << begin_string_quote << haystack << "\""; -} - -} // namespace - -// IsSubstring() and IsNotSubstring() check whether needle is a -// substring of haystack (NULL is considered a substring of itself -// only), and return an appropriate error message when they fail. - -AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const char* needle, const char* haystack) { - return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); -} - -AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const wchar_t* needle, const wchar_t* haystack) { - return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); -} - -AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const char* needle, const char* haystack) { - return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); -} - -AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const wchar_t* needle, const wchar_t* haystack) { - return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); -} - -AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::string& needle, const ::std::string& haystack) { - return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); -} - -AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::string& needle, const ::std::string& haystack) { - return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); -} - -#if GTEST_HAS_STD_WSTRING -AssertionResult IsSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::wstring& needle, const ::std::wstring& haystack) { - return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); -} - -AssertionResult IsNotSubstring( - const char* needle_expr, const char* haystack_expr, - const ::std::wstring& needle, const ::std::wstring& haystack) { - return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); -} -#endif // GTEST_HAS_STD_WSTRING - -namespace internal { - -#if GTEST_OS_WINDOWS - -namespace { - -// Helper function for IsHRESULT{SuccessFailure} predicates -AssertionResult HRESULTFailureHelper(const char* expr, - const char* expected, - long hr) { // NOLINT -# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_TV_TITLE - - // Windows CE doesn't support FormatMessage. - const char error_text[] = ""; - -# else - - // Looks up the human-readable system message for the HRESULT code - // and since we're not passing any params to FormatMessage, we don't - // want inserts expanded. - const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS; - const DWORD kBufSize = 4096; - // Gets the system's human readable message string for this HRESULT. - char error_text[kBufSize] = { '\0' }; - DWORD message_length = ::FormatMessageA(kFlags, - 0, // no source, we're asking system - static_cast(hr), // the error - 0, // no line width restrictions - error_text, // output buffer - kBufSize, // buf size - nullptr); // no arguments for inserts - // Trims tailing white space (FormatMessage leaves a trailing CR-LF) - for (; message_length && IsSpace(error_text[message_length - 1]); - --message_length) { - error_text[message_length - 1] = '\0'; - } - -# endif // GTEST_OS_WINDOWS_MOBILE - - const std::string error_hex("0x" + String::FormatHexInt(hr)); - return ::testing::AssertionFailure() - << "Expected: " << expr << " " << expected << ".\n" - << " Actual: " << error_hex << " " << error_text << "\n"; -} - -} // namespace - -AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT - if (SUCCEEDED(hr)) { - return AssertionSuccess(); - } - return HRESULTFailureHelper(expr, "succeeds", hr); -} - -AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT - if (FAILED(hr)) { - return AssertionSuccess(); - } - return HRESULTFailureHelper(expr, "fails", hr); -} - -#endif // GTEST_OS_WINDOWS - -// Utility functions for encoding Unicode text (wide strings) in -// UTF-8. - -// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8 -// like this: -// -// Code-point length Encoding -// 0 - 7 bits 0xxxxxxx -// 8 - 11 bits 110xxxxx 10xxxxxx -// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx -// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - -// The maximum code-point a one-byte UTF-8 sequence can represent. -const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; - -// The maximum code-point a two-byte UTF-8 sequence can represent. -const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; - -// The maximum code-point a three-byte UTF-8 sequence can represent. -const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; - -// The maximum code-point a four-byte UTF-8 sequence can represent. -const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; - -// Chops off the n lowest bits from a bit pattern. Returns the n -// lowest bits. As a side effect, the original bit pattern will be -// shifted to the right by n bits. -inline UInt32 ChopLowBits(UInt32* bits, int n) { - const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); - *bits >>= n; - return low_bits; -} - -// Converts a Unicode code point to a narrow string in UTF-8 encoding. -// code_point parameter is of type UInt32 because wchar_t may not be -// wide enough to contain a code point. -// If the code_point is not a valid Unicode code point -// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted -// to "(Invalid Unicode 0xXXXXXXXX)". -std::string CodePointToUtf8(UInt32 code_point) { - if (code_point > kMaxCodePoint4) { - return "(Invalid Unicode 0x" + String::FormatHexUInt32(code_point) + ")"; - } - - char str[5]; // Big enough for the largest valid code point. - if (code_point <= kMaxCodePoint1) { - str[1] = '\0'; - str[0] = static_cast(code_point); // 0xxxxxxx - } else if (code_point <= kMaxCodePoint2) { - str[2] = '\0'; - str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx - str[0] = static_cast(0xC0 | code_point); // 110xxxxx - } else if (code_point <= kMaxCodePoint3) { - str[3] = '\0'; - str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx - str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx - str[0] = static_cast(0xE0 | code_point); // 1110xxxx - } else { // code_point <= kMaxCodePoint4 - str[4] = '\0'; - str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx - str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx - str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx - str[0] = static_cast(0xF0 | code_point); // 11110xxx - } - return str; -} - -// The following two functions only make sense if the system -// uses UTF-16 for wide string encoding. All supported systems -// with 16 bit wchar_t (Windows, Cygwin) do use UTF-16. - -// Determines if the arguments constitute UTF-16 surrogate pair -// and thus should be combined into a single Unicode code point -// using CreateCodePointFromUtf16SurrogatePair. -inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { - return sizeof(wchar_t) == 2 && - (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; -} - -// Creates a Unicode code point from UTF16 surrogate pair. -inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, - wchar_t second) { - const auto first_u = static_cast(first); - const auto second_u = static_cast(second); - const UInt32 mask = (1 << 10) - 1; - return (sizeof(wchar_t) == 2) - ? (((first_u & mask) << 10) | (second_u & mask)) + 0x10000 - : - // This function should not be called when the condition is - // false, but we provide a sensible default in case it is. - first_u; -} - -// Converts a wide string to a narrow string in UTF-8 encoding. -// The wide string is assumed to have the following encoding: -// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin) -// UTF-32 if sizeof(wchar_t) == 4 (on Linux) -// Parameter str points to a null-terminated wide string. -// Parameter num_chars may additionally limit the number -// of wchar_t characters processed. -1 is used when the entire string -// should be processed. -// If the string contains code points that are not valid Unicode code points -// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output -// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding -// and contains invalid UTF-16 surrogate pairs, values in those pairs -// will be encoded as individual Unicode characters from Basic Normal Plane. -std::string WideStringToUtf8(const wchar_t* str, int num_chars) { - if (num_chars == -1) - num_chars = static_cast(wcslen(str)); - - ::std::stringstream stream; - for (int i = 0; i < num_chars; ++i) { - UInt32 unicode_code_point; - - if (str[i] == L'\0') { - break; - } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { - unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], - str[i + 1]); - i++; - } else { - unicode_code_point = static_cast(str[i]); - } - - stream << CodePointToUtf8(unicode_code_point); - } - return StringStreamToString(&stream); -} - -// Converts a wide C string to an std::string using the UTF-8 encoding. -// NULL will be converted to "(null)". -std::string String::ShowWideCString(const wchar_t * wide_c_str) { - if (wide_c_str == nullptr) return "(null)"; - - return internal::WideStringToUtf8(wide_c_str, -1); -} - -// Compares two wide C strings. Returns true if and only if they have the -// same content. -// -// Unlike wcscmp(), this function can handle NULL argument(s). A NULL -// C string is considered different to any non-NULL C string, -// including the empty string. -bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { - if (lhs == nullptr) return rhs == nullptr; - - if (rhs == nullptr) return false; - - return wcscmp(lhs, rhs) == 0; -} - -// Helper function for *_STREQ on wide strings. -AssertionResult CmpHelperSTREQ(const char* lhs_expression, - const char* rhs_expression, - const wchar_t* lhs, - const wchar_t* rhs) { - if (String::WideCStringEquals(lhs, rhs)) { - return AssertionSuccess(); - } - - return EqFailure(lhs_expression, - rhs_expression, - PrintToString(lhs), - PrintToString(rhs), - false); -} - -// Helper function for *_STRNE on wide strings. -AssertionResult CmpHelperSTRNE(const char* s1_expression, - const char* s2_expression, - const wchar_t* s1, - const wchar_t* s2) { - if (!String::WideCStringEquals(s1, s2)) { - return AssertionSuccess(); - } - - return AssertionFailure() << "Expected: (" << s1_expression << ") != (" - << s2_expression << "), actual: " - << PrintToString(s1) - << " vs " << PrintToString(s2); -} - -// Compares two C strings, ignoring case. Returns true if and only if they have -// the same content. -// -// Unlike strcasecmp(), this function can handle NULL argument(s). A -// NULL C string is considered different to any non-NULL C string, -// including the empty string. -bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { - if (lhs == nullptr) return rhs == nullptr; - if (rhs == nullptr) return false; - return posix::StrCaseCmp(lhs, rhs) == 0; -} - -// Compares two wide C strings, ignoring case. Returns true if and only if they -// have the same content. -// -// Unlike wcscasecmp(), this function can handle NULL argument(s). -// A NULL C string is considered different to any non-NULL wide C string, -// including the empty string. -// NB: The implementations on different platforms slightly differ. -// On windows, this method uses _wcsicmp which compares according to LC_CTYPE -// environment variable. On GNU platform this method uses wcscasecmp -// which compares according to LC_CTYPE category of the current locale. -// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the -// current locale. -bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, - const wchar_t* rhs) { - if (lhs == nullptr) return rhs == nullptr; - - if (rhs == nullptr) return false; - -#if GTEST_OS_WINDOWS - return _wcsicmp(lhs, rhs) == 0; -#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID - return wcscasecmp(lhs, rhs) == 0; -#else - // Android, Mac OS X and Cygwin don't define wcscasecmp. - // Other unknown OSes may not define it either. - wint_t left, right; - do { - left = towlower(static_cast(*lhs++)); - right = towlower(static_cast(*rhs++)); - } while (left && left == right); - return left == right; -#endif // OS selector -} - -// Returns true if and only if str ends with the given suffix, ignoring case. -// Any string is considered to end with an empty suffix. -bool String::EndsWithCaseInsensitive( - const std::string& str, const std::string& suffix) { - const size_t str_len = str.length(); - const size_t suffix_len = suffix.length(); - return (str_len >= suffix_len) && - CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, - suffix.c_str()); -} - -// Formats an int value as "%02d". -std::string String::FormatIntWidth2(int value) { - std::stringstream ss; - ss << std::setfill('0') << std::setw(2) << value; - return ss.str(); -} - -// Formats an int value as "%X". -std::string String::FormatHexUInt32(UInt32 value) { - std::stringstream ss; - ss << std::hex << std::uppercase << value; - return ss.str(); -} - -// Formats an int value as "%X". -std::string String::FormatHexInt(int value) { - return FormatHexUInt32(static_cast(value)); -} - -// Formats a byte as "%02X". -std::string String::FormatByte(unsigned char value) { - std::stringstream ss; - ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase - << static_cast(value); - return ss.str(); -} - -// Converts the buffer in a stringstream to an std::string, converting NUL -// bytes to "\\0" along the way. -std::string StringStreamToString(::std::stringstream* ss) { - const ::std::string& str = ss->str(); - const char* const start = str.c_str(); - const char* const end = start + str.length(); - - std::string result; - result.reserve(static_cast(2 * (end - start))); - for (const char* ch = start; ch != end; ++ch) { - if (*ch == '\0') { - result += "\\0"; // Replaces NUL with "\\0"; - } else { - result += *ch; - } - } - - return result; -} - -// Appends the user-supplied message to the Google-Test-generated message. -std::string AppendUserMessage(const std::string& gtest_msg, - const Message& user_msg) { - // Appends the user message if it's non-empty. - const std::string user_msg_string = user_msg.GetString(); - if (user_msg_string.empty()) { - return gtest_msg; - } - - return gtest_msg + "\n" + user_msg_string; -} - -} // namespace internal - -// class TestResult - -// Creates an empty TestResult. -TestResult::TestResult() - : death_test_count_(0), start_timestamp_(0), elapsed_time_(0) {} - -// D'tor. -TestResult::~TestResult() { -} - -// Returns the i-th test part result among all the results. i can -// range from 0 to total_part_count() - 1. If i is not in that range, -// aborts the program. -const TestPartResult& TestResult::GetTestPartResult(int i) const { - if (i < 0 || i >= total_part_count()) - internal::posix::Abort(); - return test_part_results_.at(static_cast(i)); -} - -// Returns the i-th test property. i can range from 0 to -// test_property_count() - 1. If i is not in that range, aborts the -// program. -const TestProperty& TestResult::GetTestProperty(int i) const { - if (i < 0 || i >= test_property_count()) - internal::posix::Abort(); - return test_properties_.at(static_cast(i)); -} - -// Clears the test part results. -void TestResult::ClearTestPartResults() { - test_part_results_.clear(); -} - -// Adds a test part result to the list. -void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { - test_part_results_.push_back(test_part_result); -} - -// Adds a test property to the list. If a property with the same key as the -// supplied property is already represented, the value of this test_property -// replaces the old value for that key. -void TestResult::RecordProperty(const std::string& xml_element, - const TestProperty& test_property) { - if (!ValidateTestProperty(xml_element, test_property)) { - return; - } - internal::MutexLock lock(&test_properites_mutex_); - const std::vector::iterator property_with_matching_key = - std::find_if(test_properties_.begin(), test_properties_.end(), - internal::TestPropertyKeyIs(test_property.key())); - if (property_with_matching_key == test_properties_.end()) { - test_properties_.push_back(test_property); - return; - } - property_with_matching_key->SetValue(test_property.value()); -} - -// The list of reserved attributes used in the element of XML -// output. -static const char* const kReservedTestSuitesAttributes[] = { - "disabled", - "errors", - "failures", - "name", - "random_seed", - "tests", - "time", - "timestamp" -}; - -// The list of reserved attributes used in the element of XML -// output. -static const char* const kReservedTestSuiteAttributes[] = { - "disabled", "errors", "failures", "name", "tests", "time", "timestamp"}; - -// The list of reserved attributes used in the element of XML output. -static const char* const kReservedTestCaseAttributes[] = { - "classname", "name", "status", "time", "type_param", - "value_param", "file", "line"}; - -// Use a slightly different set for allowed output to ensure existing tests can -// still RecordProperty("result") or "RecordProperty(timestamp") -static const char* const kReservedOutputTestCaseAttributes[] = { - "classname", "name", "status", "time", "type_param", - "value_param", "file", "line", "result", "timestamp"}; - -template -std::vector ArrayAsVector(const char* const (&array)[kSize]) { - return std::vector(array, array + kSize); -} - -static std::vector GetReservedAttributesForElement( - const std::string& xml_element) { - if (xml_element == "testsuites") { - return ArrayAsVector(kReservedTestSuitesAttributes); - } else if (xml_element == "testsuite") { - return ArrayAsVector(kReservedTestSuiteAttributes); - } else if (xml_element == "testcase") { - return ArrayAsVector(kReservedTestCaseAttributes); - } else { - GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; - } - // This code is unreachable but some compilers may not realizes that. - return std::vector(); -} - -// TODO(jdesprez): Merge the two getReserved attributes once skip is improved -static std::vector GetReservedOutputAttributesForElement( - const std::string& xml_element) { - if (xml_element == "testsuites") { - return ArrayAsVector(kReservedTestSuitesAttributes); - } else if (xml_element == "testsuite") { - return ArrayAsVector(kReservedTestSuiteAttributes); - } else if (xml_element == "testcase") { - return ArrayAsVector(kReservedOutputTestCaseAttributes); - } else { - GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; - } - // This code is unreachable but some compilers may not realizes that. - return std::vector(); -} - -static std::string FormatWordList(const std::vector& words) { - Message word_list; - for (size_t i = 0; i < words.size(); ++i) { - if (i > 0 && words.size() > 2) { - word_list << ", "; - } - if (i == words.size() - 1) { - word_list << "and "; - } - word_list << "'" << words[i] << "'"; - } - return word_list.GetString(); -} - -static bool ValidateTestPropertyName( - const std::string& property_name, - const std::vector& reserved_names) { - if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != - reserved_names.end()) { - ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name - << " (" << FormatWordList(reserved_names) - << " are reserved by " << GTEST_NAME_ << ")"; - return false; - } - return true; -} - -// Adds a failure if the key is a reserved attribute of the element named -// xml_element. Returns true if the property is valid. -bool TestResult::ValidateTestProperty(const std::string& xml_element, - const TestProperty& test_property) { - return ValidateTestPropertyName(test_property.key(), - GetReservedAttributesForElement(xml_element)); -} - -// Clears the object. -void TestResult::Clear() { - test_part_results_.clear(); - test_properties_.clear(); - death_test_count_ = 0; - elapsed_time_ = 0; -} - -// Returns true off the test part was skipped. -static bool TestPartSkipped(const TestPartResult& result) { - return result.skipped(); -} - -// Returns true if and only if the test was skipped. -bool TestResult::Skipped() const { - return !Failed() && CountIf(test_part_results_, TestPartSkipped) > 0; -} - -// Returns true if and only if the test failed. -bool TestResult::Failed() const { - for (int i = 0; i < total_part_count(); ++i) { - if (GetTestPartResult(i).failed()) - return true; - } - return false; -} - -// Returns true if and only if the test part fatally failed. -static bool TestPartFatallyFailed(const TestPartResult& result) { - return result.fatally_failed(); -} - -// Returns true if and only if the test fatally failed. -bool TestResult::HasFatalFailure() const { - return CountIf(test_part_results_, TestPartFatallyFailed) > 0; -} - -// Returns true if and only if the test part non-fatally failed. -static bool TestPartNonfatallyFailed(const TestPartResult& result) { - return result.nonfatally_failed(); -} - -// Returns true if and only if the test has a non-fatal failure. -bool TestResult::HasNonfatalFailure() const { - return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; -} - -// Gets the number of all test parts. This is the sum of the number -// of successful test parts and the number of failed test parts. -int TestResult::total_part_count() const { - return static_cast(test_part_results_.size()); -} - -// Returns the number of the test properties. -int TestResult::test_property_count() const { - return static_cast(test_properties_.size()); -} - -// class Test - -// Creates a Test object. - -// The c'tor saves the states of all flags. -Test::Test() - : gtest_flag_saver_(new GTEST_FLAG_SAVER_) { -} - -// The d'tor restores the states of all flags. The actual work is -// done by the d'tor of the gtest_flag_saver_ field, and thus not -// visible here. -Test::~Test() { -} - -// Sets up the test fixture. -// -// A sub-class may override this. -void Test::SetUp() { -} - -// Tears down the test fixture. -// -// A sub-class may override this. -void Test::TearDown() { -} - -// Allows user supplied key value pairs to be recorded for later output. -void Test::RecordProperty(const std::string& key, const std::string& value) { - UnitTest::GetInstance()->RecordProperty(key, value); -} - -// Allows user supplied key value pairs to be recorded for later output. -void Test::RecordProperty(const std::string& key, int value) { - Message value_message; - value_message << value; - RecordProperty(key, value_message.GetString().c_str()); -} - -namespace internal { - -void ReportFailureInUnknownLocation(TestPartResult::Type result_type, - const std::string& message) { - // This function is a friend of UnitTest and as such has access to - // AddTestPartResult. - UnitTest::GetInstance()->AddTestPartResult( - result_type, - nullptr, // No info about the source file where the exception occurred. - -1, // We have no info on which line caused the exception. - message, - ""); // No stack trace, either. -} - -} // namespace internal - -// Google Test requires all tests in the same test suite to use the same test -// fixture class. This function checks if the current test has the -// same fixture class as the first test in the current test suite. If -// yes, it returns true; otherwise it generates a Google Test failure and -// returns false. -bool Test::HasSameFixtureClass() { - internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - const TestSuite* const test_suite = impl->current_test_suite(); - - // Info about the first test in the current test suite. - const TestInfo* const first_test_info = test_suite->test_info_list()[0]; - const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; - const char* const first_test_name = first_test_info->name(); - - // Info about the current test. - const TestInfo* const this_test_info = impl->current_test_info(); - const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; - const char* const this_test_name = this_test_info->name(); - - if (this_fixture_id != first_fixture_id) { - // Is the first test defined using TEST? - const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); - // Is this test defined using TEST? - const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); - - if (first_is_TEST || this_is_TEST) { - // Both TEST and TEST_F appear in same test suite, which is incorrect. - // Tell the user how to fix this. - - // Gets the name of the TEST and the name of the TEST_F. Note - // that first_is_TEST and this_is_TEST cannot both be true, as - // the fixture IDs are different for the two tests. - const char* const TEST_name = - first_is_TEST ? first_test_name : this_test_name; - const char* const TEST_F_name = - first_is_TEST ? this_test_name : first_test_name; - - ADD_FAILURE() - << "All tests in the same test suite must use the same test fixture\n" - << "class, so mixing TEST_F and TEST in the same test suite is\n" - << "illegal. In test suite " << this_test_info->test_suite_name() - << ",\n" - << "test " << TEST_F_name << " is defined using TEST_F but\n" - << "test " << TEST_name << " is defined using TEST. You probably\n" - << "want to change the TEST to TEST_F or move it to another test\n" - << "case."; - } else { - // Two fixture classes with the same name appear in two different - // namespaces, which is not allowed. Tell the user how to fix this. - ADD_FAILURE() - << "All tests in the same test suite must use the same test fixture\n" - << "class. However, in test suite " - << this_test_info->test_suite_name() << ",\n" - << "you defined test " << first_test_name << " and test " - << this_test_name << "\n" - << "using two different test fixture classes. This can happen if\n" - << "the two classes are from different namespaces or translation\n" - << "units and have the same name. You should probably rename one\n" - << "of the classes to put the tests into different test suites."; - } - return false; - } - - return true; -} - -#if GTEST_HAS_SEH - -// Adds an "exception thrown" fatal failure to the current test. This -// function returns its result via an output parameter pointer because VC++ -// prohibits creation of objects with destructors on stack in functions -// using __try (see error C2712). -static std::string* FormatSehExceptionMessage(DWORD exception_code, - const char* location) { - Message message; - message << "SEH exception with code 0x" << std::setbase(16) << - exception_code << std::setbase(10) << " thrown in " << location << "."; - - return new std::string(message.GetString()); -} - -#endif // GTEST_HAS_SEH - -namespace internal { - -#if GTEST_HAS_EXCEPTIONS - -// Adds an "exception thrown" fatal failure to the current test. -static std::string FormatCxxExceptionMessage(const char* description, - const char* location) { - Message message; - if (description != nullptr) { - message << "C++ exception with description \"" << description << "\""; - } else { - message << "Unknown C++ exception"; - } - message << " thrown in " << location << "."; - - return message.GetString(); -} - -static std::string PrintTestPartResultToString( - const TestPartResult& test_part_result); - -GoogleTestFailureException::GoogleTestFailureException( - const TestPartResult& failure) - : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} - -#endif // GTEST_HAS_EXCEPTIONS - -// We put these helper functions in the internal namespace as IBM's xlC -// compiler rejects the code if they were declared static. - -// Runs the given method and handles SEH exceptions it throws, when -// SEH is supported; returns the 0-value for type Result in case of an -// SEH exception. (Microsoft compilers cannot handle SEH and C++ -// exceptions in the same function. Therefore, we provide a separate -// wrapper function for handling SEH exceptions.) -template -Result HandleSehExceptionsInMethodIfSupported( - T* object, Result (T::*method)(), const char* location) { -#if GTEST_HAS_SEH - __try { - return (object->*method)(); - } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT - GetExceptionCode())) { - // We create the exception message on the heap because VC++ prohibits - // creation of objects with destructors on stack in functions using __try - // (see error C2712). - std::string* exception_message = FormatSehExceptionMessage( - GetExceptionCode(), location); - internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, - *exception_message); - delete exception_message; - return static_cast(0); - } -#else - (void)location; - return (object->*method)(); -#endif // GTEST_HAS_SEH -} - -// Runs the given method and catches and reports C++ and/or SEH-style -// exceptions, if they are supported; returns the 0-value for type -// Result in case of an SEH exception. -template -Result HandleExceptionsInMethodIfSupported( - T* object, Result (T::*method)(), const char* location) { - // NOTE: The user code can affect the way in which Google Test handles - // exceptions by setting GTEST_FLAG(catch_exceptions), but only before - // RUN_ALL_TESTS() starts. It is technically possible to check the flag - // after the exception is caught and either report or re-throw the - // exception based on the flag's value: - // - // try { - // // Perform the test method. - // } catch (...) { - // if (GTEST_FLAG(catch_exceptions)) - // // Report the exception as failure. - // else - // throw; // Re-throws the original exception. - // } - // - // However, the purpose of this flag is to allow the program to drop into - // the debugger when the exception is thrown. On most platforms, once the - // control enters the catch block, the exception origin information is - // lost and the debugger will stop the program at the point of the - // re-throw in this function -- instead of at the point of the original - // throw statement in the code under test. For this reason, we perform - // the check early, sacrificing the ability to affect Google Test's - // exception handling in the method where the exception is thrown. - if (internal::GetUnitTestImpl()->catch_exceptions()) { -#if GTEST_HAS_EXCEPTIONS - try { - return HandleSehExceptionsInMethodIfSupported(object, method, location); - } catch (const AssertionException&) { // NOLINT - // This failure was reported already. - } catch (const internal::GoogleTestFailureException&) { // NOLINT - // This exception type can only be thrown by a failed Google - // Test assertion with the intention of letting another testing - // framework catch it. Therefore we just re-throw it. - throw; - } catch (const std::exception& e) { // NOLINT - internal::ReportFailureInUnknownLocation( - TestPartResult::kFatalFailure, - FormatCxxExceptionMessage(e.what(), location)); - } catch (...) { // NOLINT - internal::ReportFailureInUnknownLocation( - TestPartResult::kFatalFailure, - FormatCxxExceptionMessage(nullptr, location)); - } - return static_cast(0); -#else - return HandleSehExceptionsInMethodIfSupported(object, method, location); -#endif // GTEST_HAS_EXCEPTIONS - } else { - return (object->*method)(); - } -} - -} // namespace internal - -// Runs the test and updates the test result. -void Test::Run() { - if (!HasSameFixtureClass()) return; - - internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); - // We will run the test only if SetUp() was successful and didn't call - // GTEST_SKIP(). - if (!HasFatalFailure() && !IsSkipped()) { - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported( - this, &Test::TestBody, "the test body"); - } - - // However, we want to clean up as much as possible. Hence we will - // always call TearDown(), even if SetUp() or the test body has - // failed. - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported( - this, &Test::TearDown, "TearDown()"); -} - -// Returns true if and only if the current test has a fatal failure. -bool Test::HasFatalFailure() { - return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); -} - -// Returns true if and only if the current test has a non-fatal failure. -bool Test::HasNonfatalFailure() { - return internal::GetUnitTestImpl()->current_test_result()-> - HasNonfatalFailure(); -} - -// Returns true if and only if the current test was skipped. -bool Test::IsSkipped() { - return internal::GetUnitTestImpl()->current_test_result()->Skipped(); -} - -// class TestInfo - -// Constructs a TestInfo object. It assumes ownership of the test factory -// object. -TestInfo::TestInfo(const std::string& a_test_suite_name, - const std::string& a_name, const char* a_type_param, - const char* a_value_param, - internal::CodeLocation a_code_location, - internal::TypeId fixture_class_id, - internal::TestFactoryBase* factory) - : test_suite_name_(a_test_suite_name), - name_(a_name), - type_param_(a_type_param ? new std::string(a_type_param) : nullptr), - value_param_(a_value_param ? new std::string(a_value_param) : nullptr), - location_(a_code_location), - fixture_class_id_(fixture_class_id), - should_run_(false), - is_disabled_(false), - matches_filter_(false), - factory_(factory), - result_() {} - -// Destructs a TestInfo object. -TestInfo::~TestInfo() { delete factory_; } - -namespace internal { - -// Creates a new TestInfo object and registers it with Google Test; -// returns the created object. -// -// Arguments: -// -// test_suite_name: name of the test suite -// name: name of the test -// type_param: the name of the test's type parameter, or NULL if -// this is not a typed or a type-parameterized test. -// value_param: text representation of the test's value parameter, -// or NULL if this is not a value-parameterized test. -// code_location: code location where the test is defined -// fixture_class_id: ID of the test fixture class -// set_up_tc: pointer to the function that sets up the test suite -// tear_down_tc: pointer to the function that tears down the test suite -// factory: pointer to the factory that creates a test object. -// The newly created TestInfo instance will assume -// ownership of the factory object. -TestInfo* MakeAndRegisterTestInfo( - const char* test_suite_name, const char* name, const char* type_param, - const char* value_param, CodeLocation code_location, - TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, - TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) { - TestInfo* const test_info = - new TestInfo(test_suite_name, name, type_param, value_param, - code_location, fixture_class_id, factory); - GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); - return test_info; -} - -void ReportInvalidTestSuiteType(const char* test_suite_name, - CodeLocation code_location) { - Message errors; - errors - << "Attempted redefinition of test suite " << test_suite_name << ".\n" - << "All tests in the same test suite must use the same test fixture\n" - << "class. However, in test suite " << test_suite_name << ", you tried\n" - << "to define a test using a fixture class different from the one\n" - << "used earlier. This can happen if the two fixture classes are\n" - << "from different namespaces and have the same name. You should\n" - << "probably rename one of the classes to put the tests into different\n" - << "test suites."; - - GTEST_LOG_(ERROR) << FormatFileLocation(code_location.file.c_str(), - code_location.line) - << " " << errors.GetString(); -} -} // namespace internal - -namespace { - -// A predicate that checks the test name of a TestInfo against a known -// value. -// -// This is used for implementation of the TestSuite class only. We put -// it in the anonymous namespace to prevent polluting the outer -// namespace. -// -// TestNameIs is copyable. -class TestNameIs { - public: - // Constructor. - // - // TestNameIs has NO default constructor. - explicit TestNameIs(const char* name) - : name_(name) {} - - // Returns true if and only if the test name of test_info matches name_. - bool operator()(const TestInfo * test_info) const { - return test_info && test_info->name() == name_; - } - - private: - std::string name_; -}; - -} // namespace - -namespace internal { - -// This method expands all parameterized tests registered with macros TEST_P -// and INSTANTIATE_TEST_SUITE_P into regular tests and registers those. -// This will be done just once during the program runtime. -void UnitTestImpl::RegisterParameterizedTests() { - if (!parameterized_tests_registered_) { - parameterized_test_registry_.RegisterTests(); - parameterized_tests_registered_ = true; - } -} - -} // namespace internal - -// Creates the test object, runs it, records its result, and then -// deletes it. -void TestInfo::Run() { - if (!should_run_) return; - - // Tells UnitTest where to store test result. - internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - impl->set_current_test_info(this); - - TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); - - // Notifies the unit test event listeners that a test is about to start. - repeater->OnTestStart(*this); - - const TimeInMillis start = internal::GetTimeInMillis(); - - impl->os_stack_trace_getter()->UponLeavingGTest(); - - // Creates the test object. - Test* const test = internal::HandleExceptionsInMethodIfSupported( - factory_, &internal::TestFactoryBase::CreateTest, - "the test fixture's constructor"); - - // Runs the test if the constructor didn't generate a fatal failure or invoke - // GTEST_SKIP(). - // Note that the object will not be null - if (!Test::HasFatalFailure() && !Test::IsSkipped()) { - // This doesn't throw as all user code that can throw are wrapped into - // exception handling code. - test->Run(); - } - - if (test != nullptr) { - // Deletes the test object. - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported( - test, &Test::DeleteSelf_, "the test fixture's destructor"); - } - - result_.set_start_timestamp(start); - result_.set_elapsed_time(internal::GetTimeInMillis() - start); - - // Notifies the unit test event listener that a test has just finished. - repeater->OnTestEnd(*this); - - // Tells UnitTest to stop associating assertion results to this - // test. - impl->set_current_test_info(nullptr); -} - -// class TestSuite - -// Gets the number of successful tests in this test suite. -int TestSuite::successful_test_count() const { - return CountIf(test_info_list_, TestPassed); -} - -// Gets the number of successful tests in this test suite. -int TestSuite::skipped_test_count() const { - return CountIf(test_info_list_, TestSkipped); -} - -// Gets the number of failed tests in this test suite. -int TestSuite::failed_test_count() const { - return CountIf(test_info_list_, TestFailed); -} - -// Gets the number of disabled tests that will be reported in the XML report. -int TestSuite::reportable_disabled_test_count() const { - return CountIf(test_info_list_, TestReportableDisabled); -} - -// Gets the number of disabled tests in this test suite. -int TestSuite::disabled_test_count() const { - return CountIf(test_info_list_, TestDisabled); -} - -// Gets the number of tests to be printed in the XML report. -int TestSuite::reportable_test_count() const { - return CountIf(test_info_list_, TestReportable); -} - -// Get the number of tests in this test suite that should run. -int TestSuite::test_to_run_count() const { - return CountIf(test_info_list_, ShouldRunTest); -} - -// Gets the number of all tests. -int TestSuite::total_test_count() const { - return static_cast(test_info_list_.size()); -} - -// Creates a TestSuite with the given name. -// -// Arguments: -// -// name: name of the test suite -// a_type_param: the name of the test suite's type parameter, or NULL if -// this is not a typed or a type-parameterized test suite. -// set_up_tc: pointer to the function that sets up the test suite -// tear_down_tc: pointer to the function that tears down the test suite -TestSuite::TestSuite(const char* a_name, const char* a_type_param, - internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc) - : name_(a_name), - type_param_(a_type_param ? new std::string(a_type_param) : nullptr), - set_up_tc_(set_up_tc), - tear_down_tc_(tear_down_tc), - should_run_(false), - start_timestamp_(0), - elapsed_time_(0) {} - -// Destructor of TestSuite. -TestSuite::~TestSuite() { - // Deletes every Test in the collection. - ForEach(test_info_list_, internal::Delete); -} - -// Returns the i-th test among all the tests. i can range from 0 to -// total_test_count() - 1. If i is not in that range, returns NULL. -const TestInfo* TestSuite::GetTestInfo(int i) const { - const int index = GetElementOr(test_indices_, i, -1); - return index < 0 ? nullptr : test_info_list_[static_cast(index)]; -} - -// Returns the i-th test among all the tests. i can range from 0 to -// total_test_count() - 1. If i is not in that range, returns NULL. -TestInfo* TestSuite::GetMutableTestInfo(int i) { - const int index = GetElementOr(test_indices_, i, -1); - return index < 0 ? nullptr : test_info_list_[static_cast(index)]; -} - -// Adds a test to this test suite. Will delete the test upon -// destruction of the TestSuite object. -void TestSuite::AddTestInfo(TestInfo* test_info) { - test_info_list_.push_back(test_info); - test_indices_.push_back(static_cast(test_indices_.size())); -} - -// Runs every test in this TestSuite. -void TestSuite::Run() { - if (!should_run_) return; - - internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - impl->set_current_test_suite(this); - - TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); - - // Call both legacy and the new API - repeater->OnTestSuiteStart(*this); -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI - repeater->OnTestCaseStart(*this); -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI - - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported( - this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()"); - - start_timestamp_ = internal::GetTimeInMillis(); - for (int i = 0; i < total_test_count(); i++) { - GetMutableTestInfo(i)->Run(); - } - elapsed_time_ = internal::GetTimeInMillis() - start_timestamp_; - - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported( - this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()"); - - // Call both legacy and the new API - repeater->OnTestSuiteEnd(*this); -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI - repeater->OnTestCaseEnd(*this); -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI - - impl->set_current_test_suite(nullptr); -} - -// Clears the results of all tests in this test suite. -void TestSuite::ClearResult() { - ad_hoc_test_result_.Clear(); - ForEach(test_info_list_, TestInfo::ClearTestResult); -} - -// Shuffles the tests in this test suite. -void TestSuite::ShuffleTests(internal::Random* random) { - Shuffle(random, &test_indices_); -} - -// Restores the test order to before the first shuffle. -void TestSuite::UnshuffleTests() { - for (size_t i = 0; i < test_indices_.size(); i++) { - test_indices_[i] = static_cast(i); - } -} - -// Formats a countable noun. Depending on its quantity, either the -// singular form or the plural form is used. e.g. -// -// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". -// FormatCountableNoun(5, "book", "books") returns "5 books". -static std::string FormatCountableNoun(int count, - const char * singular_form, - const char * plural_form) { - return internal::StreamableToString(count) + " " + - (count == 1 ? singular_form : plural_form); -} - -// Formats the count of tests. -static std::string FormatTestCount(int test_count) { - return FormatCountableNoun(test_count, "test", "tests"); -} - -// Formats the count of test suites. -static std::string FormatTestSuiteCount(int test_suite_count) { - return FormatCountableNoun(test_suite_count, "test suite", "test suites"); -} - -// Converts a TestPartResult::Type enum to human-friendly string -// representation. Both kNonFatalFailure and kFatalFailure are translated -// to "Failure", as the user usually doesn't care about the difference -// between the two when viewing the test result. -static const char * TestPartResultTypeToString(TestPartResult::Type type) { - switch (type) { - case TestPartResult::kSkip: - return "Skipped"; - case TestPartResult::kSuccess: - return "Success"; - - case TestPartResult::kNonFatalFailure: - case TestPartResult::kFatalFailure: -#ifdef _MSC_VER - return "error: "; -#else - return "Failure\n"; -#endif - default: - return "Unknown result type"; - } -} - -namespace internal { - -// Prints a TestPartResult to an std::string. -static std::string PrintTestPartResultToString( - const TestPartResult& test_part_result) { - return (Message() - << internal::FormatFileLocation(test_part_result.file_name(), - test_part_result.line_number()) - << " " << TestPartResultTypeToString(test_part_result.type()) - << test_part_result.message()).GetString(); -} - -// Prints a TestPartResult. -static void PrintTestPartResult(const TestPartResult& test_part_result) { - const std::string& result = - PrintTestPartResultToString(test_part_result); - printf("%s\n", result.c_str()); - fflush(stdout); - // If the test program runs in Visual Studio or a debugger, the - // following statements add the test part result message to the Output - // window such that the user can double-click on it to jump to the - // corresponding source code location; otherwise they do nothing. -#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE - // We don't call OutputDebugString*() on Windows Mobile, as printing - // to stdout is done by OutputDebugString() there already - we don't - // want the same message printed twice. - ::OutputDebugStringA(result.c_str()); - ::OutputDebugStringA("\n"); -#endif -} - -// class PrettyUnitTestResultPrinter -#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \ - !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW - -// Returns the character attribute for the given color. -static WORD GetColorAttribute(GTestColor color) { - switch (color) { - case COLOR_RED: return FOREGROUND_RED; - case COLOR_GREEN: return FOREGROUND_GREEN; - case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; - default: return 0; - } -} - -static int GetBitOffset(WORD color_mask) { - if (color_mask == 0) return 0; - - int bitOffset = 0; - while ((color_mask & 1) == 0) { - color_mask >>= 1; - ++bitOffset; - } - return bitOffset; -} - -static WORD GetNewColor(GTestColor color, WORD old_color_attrs) { - // Let's reuse the BG - static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN | - BACKGROUND_RED | BACKGROUND_INTENSITY; - static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN | - FOREGROUND_RED | FOREGROUND_INTENSITY; - const WORD existing_bg = old_color_attrs & background_mask; - - WORD new_color = - GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY; - static const int bg_bitOffset = GetBitOffset(background_mask); - static const int fg_bitOffset = GetBitOffset(foreground_mask); - - if (((new_color & background_mask) >> bg_bitOffset) == - ((new_color & foreground_mask) >> fg_bitOffset)) { - new_color ^= FOREGROUND_INTENSITY; // invert intensity - } - return new_color; -} - -#else - -// Returns the ANSI color code for the given color. COLOR_DEFAULT is -// an invalid input. -static const char* GetAnsiColorCode(GTestColor color) { - switch (color) { - case COLOR_RED: return "1"; - case COLOR_GREEN: return "2"; - case COLOR_YELLOW: return "3"; - default: - return nullptr; - } -} - -#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE - -// Returns true if and only if Google Test should use colors in the output. -bool ShouldUseColor(bool stdout_is_tty) { - const char* const gtest_color = GTEST_FLAG(color).c_str(); - - if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { -#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW - // On Windows the TERM variable is usually not set, but the - // console there does support colors. - return stdout_is_tty; -#else - // On non-Windows platforms, we rely on the TERM variable. - const char* const term = posix::GetEnv("TERM"); - const bool term_supports_color = - String::CStringEquals(term, "xterm") || - String::CStringEquals(term, "xterm-color") || - String::CStringEquals(term, "xterm-256color") || - String::CStringEquals(term, "screen") || - String::CStringEquals(term, "screen-256color") || - String::CStringEquals(term, "tmux") || - String::CStringEquals(term, "tmux-256color") || - String::CStringEquals(term, "rxvt-unicode") || - String::CStringEquals(term, "rxvt-unicode-256color") || - String::CStringEquals(term, "linux") || - String::CStringEquals(term, "cygwin"); - return stdout_is_tty && term_supports_color; -#endif // GTEST_OS_WINDOWS - } - - return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || - String::CaseInsensitiveCStringEquals(gtest_color, "true") || - String::CaseInsensitiveCStringEquals(gtest_color, "t") || - String::CStringEquals(gtest_color, "1"); - // We take "yes", "true", "t", and "1" as meaning "yes". If the - // value is neither one of these nor "auto", we treat it as "no" to - // be conservative. -} - -// Helpers for printing colored strings to stdout. Note that on Windows, we -// cannot simply emit special characters and have the terminal change colors. -// This routine must actually emit the characters rather than return a string -// that would be colored when printed, as can be done on Linux. -void ColoredPrintf(GTestColor color, const char* fmt, ...) { - va_list args; - va_start(args, fmt); - -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS || GTEST_OS_IOS || \ - GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT || defined(ESP_PLATFORM) - const bool use_color = AlwaysFalse(); -#else - static const bool in_color_mode = - ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); - const bool use_color = in_color_mode && (color != COLOR_DEFAULT); -#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS - - if (!use_color) { - vprintf(fmt, args); - va_end(args); - return; - } - -#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \ - !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW - const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); - - // Gets the current text color. - CONSOLE_SCREEN_BUFFER_INFO buffer_info; - GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); - const WORD old_color_attrs = buffer_info.wAttributes; - const WORD new_color = GetNewColor(color, old_color_attrs); - - // We need to flush the stream buffers into the console before each - // SetConsoleTextAttribute call lest it affect the text that is already - // printed but has not yet reached the console. - fflush(stdout); - SetConsoleTextAttribute(stdout_handle, new_color); - - vprintf(fmt, args); - - fflush(stdout); - // Restores the text color. - SetConsoleTextAttribute(stdout_handle, old_color_attrs); -#else - printf("\033[0;3%sm", GetAnsiColorCode(color)); - vprintf(fmt, args); - printf("\033[m"); // Resets the terminal to default. -#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE - va_end(args); -} - -// Text printed in Google Test's text output and --gtest_list_tests -// output to label the type parameter and value parameter for a test. -static const char kTypeParamLabel[] = "TypeParam"; -static const char kValueParamLabel[] = "GetParam()"; - -static void PrintFullTestCommentIfPresent(const TestInfo& test_info) { - const char* const type_param = test_info.type_param(); - const char* const value_param = test_info.value_param(); - - if (type_param != nullptr || value_param != nullptr) { - printf(", where "); - if (type_param != nullptr) { - printf("%s = %s", kTypeParamLabel, type_param); - if (value_param != nullptr) printf(" and "); - } - if (value_param != nullptr) { - printf("%s = %s", kValueParamLabel, value_param); - } - } -} - -// This class implements the TestEventListener interface. -// -// Class PrettyUnitTestResultPrinter is copyable. -class PrettyUnitTestResultPrinter : public TestEventListener { - public: - PrettyUnitTestResultPrinter() {} - static void PrintTestName(const char* test_suite, const char* test) { - printf("%s.%s", test_suite, test); - } - - // The following methods override what's in the TestEventListener class. - void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} - void OnTestIterationStart(const UnitTest& unit_test, int iteration) override; - void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override; - void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestCaseStart(const TestCase& test_case) override; -#else - void OnTestSuiteStart(const TestSuite& test_suite) override; -#endif // OnTestCaseStart - - void OnTestStart(const TestInfo& test_info) override; - - void OnTestPartResult(const TestPartResult& result) override; - void OnTestEnd(const TestInfo& test_info) override; -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestCaseEnd(const TestCase& test_case) override; -#else - void OnTestSuiteEnd(const TestSuite& test_suite) override; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - - void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override; - void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} - void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; - void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} - - private: - static void PrintFailedTests(const UnitTest& unit_test); - static void PrintSkippedTests(const UnitTest& unit_test); -}; - - // Fired before each iteration of tests starts. -void PrettyUnitTestResultPrinter::OnTestIterationStart( - const UnitTest& unit_test, int iteration) { - if (GTEST_FLAG(repeat) != 1) - printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); - - const char* const filter = GTEST_FLAG(filter).c_str(); - - // Prints the filter if it's not *. This reminds the user that some - // tests may be skipped. - if (!String::CStringEquals(filter, kUniversalFilter)) { - ColoredPrintf(COLOR_YELLOW, - "Note: %s filter = %s\n", GTEST_NAME_, filter); - } - - if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { - const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); - ColoredPrintf(COLOR_YELLOW, - "Note: This is test shard %d of %s.\n", - static_cast(shard_index) + 1, - internal::posix::GetEnv(kTestTotalShards)); - } - - if (GTEST_FLAG(shuffle)) { - ColoredPrintf(COLOR_YELLOW, - "Note: Randomizing tests' orders with a seed of %d .\n", - unit_test.random_seed()); - } - - ColoredPrintf(COLOR_GREEN, "[==========] "); - printf("Running %s from %s.\n", - FormatTestCount(unit_test.test_to_run_count()).c_str(), - FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str()); - fflush(stdout); -} - -void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( - const UnitTest& /*unit_test*/) { - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("Global test environment set-up.\n"); - fflush(stdout); -} - -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { - const std::string counts = - FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("%s from %s", counts.c_str(), test_case.name()); - if (test_case.type_param() == nullptr) { - printf("\n"); - } else { - printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); - } - fflush(stdout); -} -#else -void PrettyUnitTestResultPrinter::OnTestSuiteStart( - const TestSuite& test_suite) { - const std::string counts = - FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests"); - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("%s from %s", counts.c_str(), test_suite.name()); - if (test_suite.type_param() == nullptr) { - printf("\n"); - } else { - printf(", where %s = %s\n", kTypeParamLabel, test_suite.type_param()); - } - fflush(stdout); -} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { - ColoredPrintf(COLOR_GREEN, "[ RUN ] "); - PrintTestName(test_info.test_suite_name(), test_info.name()); - printf("\n"); - fflush(stdout); -} - -// Called after an assertion failure. -void PrettyUnitTestResultPrinter::OnTestPartResult( - const TestPartResult& result) { - switch (result.type()) { - // If the test part succeeded, or was skipped, - // we don't need to do anything. - case TestPartResult::kSkip: - case TestPartResult::kSuccess: - return; - default: - // Print failure message from the assertion - // (e.g. expected this and got that). - PrintTestPartResult(result); - fflush(stdout); - } -} - -void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { - if (test_info.result()->Passed()) { - ColoredPrintf(COLOR_GREEN, "[ OK ] "); - } else if (test_info.result()->Skipped()) { - ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); - } else { - ColoredPrintf(COLOR_RED, "[ FAILED ] "); - } - PrintTestName(test_info.test_suite_name(), test_info.name()); - if (test_info.result()->Failed()) - PrintFullTestCommentIfPresent(test_info); - - if (GTEST_FLAG(print_time)) { - printf(" (%s ms)\n", internal::StreamableToString( - test_info.result()->elapsed_time()).c_str()); - } else { - printf("\n"); - } - fflush(stdout); -} - -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { - if (!GTEST_FLAG(print_time)) return; - - const std::string counts = - FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_case.name(), - internal::StreamableToString(test_case.elapsed_time()).c_str()); - fflush(stdout); -} -#else -void PrettyUnitTestResultPrinter::OnTestSuiteEnd(const TestSuite& test_suite) { - if (!GTEST_FLAG(print_time)) return; - - const std::string counts = - FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests"); - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_suite.name(), - internal::StreamableToString(test_suite.elapsed_time()).c_str()); - fflush(stdout); -} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( - const UnitTest& /*unit_test*/) { - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("Global test environment tear-down\n"); - fflush(stdout); -} - -// Internal helper for printing the list of failed tests. -void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { - const int failed_test_count = unit_test.failed_test_count(); - if (failed_test_count == 0) { - return; - } - - for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { - const TestSuite& test_suite = *unit_test.GetTestSuite(i); - if (!test_suite.should_run() || (test_suite.failed_test_count() == 0)) { - continue; - } - for (int j = 0; j < test_suite.total_test_count(); ++j) { - const TestInfo& test_info = *test_suite.GetTestInfo(j); - if (!test_info.should_run() || !test_info.result()->Failed()) { - continue; - } - ColoredPrintf(COLOR_RED, "[ FAILED ] "); - printf("%s.%s", test_suite.name(), test_info.name()); - PrintFullTestCommentIfPresent(test_info); - printf("\n"); - } - } -} - -// Internal helper for printing the list of skipped tests. -void PrettyUnitTestResultPrinter::PrintSkippedTests(const UnitTest& unit_test) { - const int skipped_test_count = unit_test.skipped_test_count(); - if (skipped_test_count == 0) { - return; - } - - for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { - const TestSuite& test_suite = *unit_test.GetTestSuite(i); - if (!test_suite.should_run() || (test_suite.skipped_test_count() == 0)) { - continue; - } - for (int j = 0; j < test_suite.total_test_count(); ++j) { - const TestInfo& test_info = *test_suite.GetTestInfo(j); - if (!test_info.should_run() || !test_info.result()->Skipped()) { - continue; - } - ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); - printf("%s.%s", test_suite.name(), test_info.name()); - printf("\n"); - } - } -} - -void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, - int /*iteration*/) { - ColoredPrintf(COLOR_GREEN, "[==========] "); - printf("%s from %s ran.", - FormatTestCount(unit_test.test_to_run_count()).c_str(), - FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str()); - if (GTEST_FLAG(print_time)) { - printf(" (%s ms total)", - internal::StreamableToString(unit_test.elapsed_time()).c_str()); - } - printf("\n"); - ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); - printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); - - const int skipped_test_count = unit_test.skipped_test_count(); - if (skipped_test_count > 0) { - ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); - printf("%s, listed below:\n", FormatTestCount(skipped_test_count).c_str()); - PrintSkippedTests(unit_test); - } - - int num_failures = unit_test.failed_test_count(); - if (!unit_test.Passed()) { - const int failed_test_count = unit_test.failed_test_count(); - ColoredPrintf(COLOR_RED, "[ FAILED ] "); - printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); - PrintFailedTests(unit_test); - printf("\n%2d FAILED %s\n", num_failures, - num_failures == 1 ? "TEST" : "TESTS"); - } - - int num_disabled = unit_test.reportable_disabled_test_count(); - if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { - if (!num_failures) { - printf("\n"); // Add a spacer if no FAILURE banner is displayed. - } - ColoredPrintf(COLOR_YELLOW, - " YOU HAVE %d DISABLED %s\n\n", - num_disabled, - num_disabled == 1 ? "TEST" : "TESTS"); - } - // Ensure that Google Test output is printed before, e.g., heapchecker output. - fflush(stdout); -} - -// End PrettyUnitTestResultPrinter - -// class TestEventRepeater -// -// This class forwards events to other event listeners. -class TestEventRepeater : public TestEventListener { - public: - TestEventRepeater() : forwarding_enabled_(true) {} - ~TestEventRepeater() override; - void Append(TestEventListener *listener); - TestEventListener* Release(TestEventListener* listener); - - // Controls whether events will be forwarded to listeners_. Set to false - // in death test child processes. - bool forwarding_enabled() const { return forwarding_enabled_; } - void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } - - void OnTestProgramStart(const UnitTest& unit_test) override; - void OnTestIterationStart(const UnitTest& unit_test, int iteration) override; - void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override; - void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override; -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestCaseStart(const TestSuite& parameter) override; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestSuiteStart(const TestSuite& parameter) override; - void OnTestStart(const TestInfo& test_info) override; - void OnTestPartResult(const TestPartResult& result) override; - void OnTestEnd(const TestInfo& test_info) override; -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestCaseEnd(const TestCase& parameter) override; -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - void OnTestSuiteEnd(const TestSuite& parameter) override; - void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override; - void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override; - void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; - void OnTestProgramEnd(const UnitTest& unit_test) override; - - private: - // Controls whether events will be forwarded to listeners_. Set to false - // in death test child processes. - bool forwarding_enabled_; - // The list of listeners that receive events. - std::vector listeners_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); -}; - -TestEventRepeater::~TestEventRepeater() { - ForEach(listeners_, Delete); -} - -void TestEventRepeater::Append(TestEventListener *listener) { - listeners_.push_back(listener); -} - -TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { - for (size_t i = 0; i < listeners_.size(); ++i) { - if (listeners_[i] == listener) { - listeners_.erase(listeners_.begin() + static_cast(i)); - return listener; - } - } - - return nullptr; -} - -// Since most methods are very similar, use macros to reduce boilerplate. -// This defines a member that forwards the call to all listeners. -#define GTEST_REPEATER_METHOD_(Name, Type) \ -void TestEventRepeater::Name(const Type& parameter) { \ - if (forwarding_enabled_) { \ - for (size_t i = 0; i < listeners_.size(); i++) { \ - listeners_[i]->Name(parameter); \ - } \ - } \ -} -// This defines a member that forwards the call to all listeners in reverse -// order. -#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ - void TestEventRepeater::Name(const Type& parameter) { \ - if (forwarding_enabled_) { \ - for (size_t i = listeners_.size(); i != 0; i--) { \ - listeners_[i - 1]->Name(parameter); \ - } \ - } \ - } - -GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) -GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -GTEST_REPEATER_METHOD_(OnTestCaseStart, TestSuite) -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite) -GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) -GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) -GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) -GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) -GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) -GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestSuite) -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -GTEST_REVERSE_REPEATER_METHOD_(OnTestSuiteEnd, TestSuite) -GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) - -#undef GTEST_REPEATER_METHOD_ -#undef GTEST_REVERSE_REPEATER_METHOD_ - -void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, - int iteration) { - if (forwarding_enabled_) { - for (size_t i = 0; i < listeners_.size(); i++) { - listeners_[i]->OnTestIterationStart(unit_test, iteration); - } - } -} - -void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, - int iteration) { - if (forwarding_enabled_) { - for (size_t i = listeners_.size(); i > 0; i--) { - listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration); - } - } -} - -// End TestEventRepeater - -// This class generates an XML output file. -class XmlUnitTestResultPrinter : public EmptyTestEventListener { - public: - explicit XmlUnitTestResultPrinter(const char* output_file); - - void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; - void ListTestsMatchingFilter(const std::vector& test_suites); - - // Prints an XML summary of all unit tests. - static void PrintXmlTestsList(std::ostream* stream, - const std::vector& test_suites); - - private: - // Is c a whitespace character that is normalized to a space character - // when it appears in an XML attribute value? - static bool IsNormalizableWhitespace(char c) { - return c == 0x9 || c == 0xA || c == 0xD; - } - - // May c appear in a well-formed XML document? - static bool IsValidXmlCharacter(char c) { - return IsNormalizableWhitespace(c) || c >= 0x20; - } - - // Returns an XML-escaped copy of the input string str. If - // is_attribute is true, the text is meant to appear as an attribute - // value, and normalizable whitespace is preserved by replacing it - // with character references. - static std::string EscapeXml(const std::string& str, bool is_attribute); - - // Returns the given string with all characters invalid in XML removed. - static std::string RemoveInvalidXmlCharacters(const std::string& str); - - // Convenience wrapper around EscapeXml when str is an attribute value. - static std::string EscapeXmlAttribute(const std::string& str) { - return EscapeXml(str, true); - } - - // Convenience wrapper around EscapeXml when str is not an attribute value. - static std::string EscapeXmlText(const char* str) { - return EscapeXml(str, false); - } - - // Verifies that the given attribute belongs to the given element and - // streams the attribute as XML. - static void OutputXmlAttribute(std::ostream* stream, - const std::string& element_name, - const std::string& name, - const std::string& value); - - // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. - static void OutputXmlCDataSection(::std::ostream* stream, const char* data); - - // Streams an XML representation of a TestInfo object. - static void OutputXmlTestInfo(::std::ostream* stream, - const char* test_suite_name, - const TestInfo& test_info); - - // Prints an XML representation of a TestSuite object - static void PrintXmlTestSuite(::std::ostream* stream, - const TestSuite& test_suite); - - // Prints an XML summary of unit_test to output stream out. - static void PrintXmlUnitTest(::std::ostream* stream, - const UnitTest& unit_test); - - // Produces a string representing the test properties in a result as space - // delimited XML attributes based on the property key="value" pairs. - // When the std::string is not empty, it includes a space at the beginning, - // to delimit this attribute from prior attributes. - static std::string TestPropertiesAsXmlAttributes(const TestResult& result); - - // Streams an XML representation of the test properties of a TestResult - // object. - static void OutputXmlTestProperties(std::ostream* stream, - const TestResult& result); - - // The output file. - const std::string output_file_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); -}; - -// Creates a new XmlUnitTestResultPrinter. -XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) - : output_file_(output_file) { - if (output_file_.empty()) { - GTEST_LOG_(FATAL) << "XML output file may not be null"; - } -} - -// Called after the unit test ends. -void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, - int /*iteration*/) { - FILE* xmlout = OpenFileForWriting(output_file_); - std::stringstream stream; - PrintXmlUnitTest(&stream, unit_test); - fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); - fclose(xmlout); -} - -void XmlUnitTestResultPrinter::ListTestsMatchingFilter( - const std::vector& test_suites) { - FILE* xmlout = OpenFileForWriting(output_file_); - std::stringstream stream; - PrintXmlTestsList(&stream, test_suites); - fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); - fclose(xmlout); -} - -// Returns an XML-escaped copy of the input string str. If is_attribute -// is true, the text is meant to appear as an attribute value, and -// normalizable whitespace is preserved by replacing it with character -// references. -// -// Invalid XML characters in str, if any, are stripped from the output. -// It is expected that most, if not all, of the text processed by this -// module will consist of ordinary English text. -// If this module is ever modified to produce version 1.1 XML output, -// most invalid characters can be retained using character references. -std::string XmlUnitTestResultPrinter::EscapeXml( - const std::string& str, bool is_attribute) { - Message m; - - for (size_t i = 0; i < str.size(); ++i) { - const char ch = str[i]; - switch (ch) { - case '<': - m << "<"; - break; - case '>': - m << ">"; - break; - case '&': - m << "&"; - break; - case '\'': - if (is_attribute) - m << "'"; - else - m << '\''; - break; - case '"': - if (is_attribute) - m << """; - else - m << '"'; - break; - default: - if (IsValidXmlCharacter(ch)) { - if (is_attribute && IsNormalizableWhitespace(ch)) - m << "&#x" << String::FormatByte(static_cast(ch)) - << ";"; - else - m << ch; - } - break; - } - } - - return m.GetString(); -} - -// Returns the given string with all characters invalid in XML removed. -// Currently invalid characters are dropped from the string. An -// alternative is to replace them with certain characters such as . or ?. -std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( - const std::string& str) { - std::string output; - output.reserve(str.size()); - for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) - if (IsValidXmlCharacter(*it)) - output.push_back(*it); - - return output; -} - -// The following routines generate an XML representation of a UnitTest -// object. -// GOOGLETEST_CM0009 DO NOT DELETE -// -// This is how Google Test concepts map to the DTD: -// -// <-- corresponds to a UnitTest object -// <-- corresponds to a TestSuite object -// <-- corresponds to a TestInfo object -// ... -// ... -// ... -// <-- individual assertion failures -// -// -// - -// Formats the given time in milliseconds as seconds. -std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { - ::std::stringstream ss; - ss << (static_cast(ms) * 1e-3); - return ss.str(); -} - -static bool PortableLocaltime(time_t seconds, struct tm* out) { -#if defined(_MSC_VER) - return localtime_s(out, &seconds) == 0; -#elif defined(__MINGW32__) || defined(__MINGW64__) - // MINGW provides neither localtime_r nor localtime_s, but uses - // Windows' localtime(), which has a thread-local tm buffer. - struct tm* tm_ptr = localtime(&seconds); // NOLINT - if (tm_ptr == nullptr) return false; - *out = *tm_ptr; - return true; -#else - return localtime_r(&seconds, out) != nullptr; -#endif -} - -// Converts the given epoch time in milliseconds to a date string in the ISO -// 8601 format, without the timezone information. -std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { - struct tm time_struct; - if (!PortableLocaltime(static_cast(ms / 1000), &time_struct)) - return ""; - // YYYY-MM-DDThh:mm:ss - return StreamableToString(time_struct.tm_year + 1900) + "-" + - String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" + - String::FormatIntWidth2(time_struct.tm_mday) + "T" + - String::FormatIntWidth2(time_struct.tm_hour) + ":" + - String::FormatIntWidth2(time_struct.tm_min) + ":" + - String::FormatIntWidth2(time_struct.tm_sec); -} - -// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. -void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, - const char* data) { - const char* segment = data; - *stream << ""); - if (next_segment != nullptr) { - stream->write( - segment, static_cast(next_segment - segment)); - *stream << "]]>]]>"); - } else { - *stream << segment; - break; - } - } - *stream << "]]>"; -} - -void XmlUnitTestResultPrinter::OutputXmlAttribute( - std::ostream* stream, - const std::string& element_name, - const std::string& name, - const std::string& value) { - const std::vector& allowed_names = - GetReservedOutputAttributesForElement(element_name); - - GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != - allowed_names.end()) - << "Attribute " << name << " is not allowed for element <" << element_name - << ">."; - - *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; -} - -// Prints an XML representation of a TestInfo object. -void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, - const char* test_suite_name, - const TestInfo& test_info) { - const TestResult& result = *test_info.result(); - const std::string kTestsuite = "testcase"; - - if (test_info.is_in_another_shard()) { - return; - } - - *stream << " \n"; - return; - } - - OutputXmlAttribute(stream, kTestsuite, "status", - test_info.should_run() ? "run" : "notrun"); - OutputXmlAttribute(stream, kTestsuite, "result", - test_info.should_run() - ? (result.Skipped() ? "skipped" : "completed") - : "suppressed"); - OutputXmlAttribute(stream, kTestsuite, "time", - FormatTimeInMillisAsSeconds(result.elapsed_time())); - OutputXmlAttribute( - stream, kTestsuite, "timestamp", - FormatEpochTimeInMillisAsIso8601(result.start_timestamp())); - OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name); - - int failures = 0; - for (int i = 0; i < result.total_part_count(); ++i) { - const TestPartResult& part = result.GetTestPartResult(i); - if (part.failed()) { - if (++failures == 1) { - *stream << ">\n"; - } - const std::string location = - internal::FormatCompilerIndependentFileLocation(part.file_name(), - part.line_number()); - const std::string summary = location + "\n" + part.summary(); - *stream << " "; - const std::string detail = location + "\n" + part.message(); - OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); - *stream << "\n"; - } - } - - if (failures == 0 && result.test_property_count() == 0) { - *stream << " />\n"; - } else { - if (failures == 0) { - *stream << ">\n"; - } - OutputXmlTestProperties(stream, result); - *stream << " \n"; - } -} - -// Prints an XML representation of a TestSuite object -void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream, - const TestSuite& test_suite) { - const std::string kTestsuite = "testsuite"; - *stream << " <" << kTestsuite; - OutputXmlAttribute(stream, kTestsuite, "name", test_suite.name()); - OutputXmlAttribute(stream, kTestsuite, "tests", - StreamableToString(test_suite.reportable_test_count())); - if (!GTEST_FLAG(list_tests)) { - OutputXmlAttribute(stream, kTestsuite, "failures", - StreamableToString(test_suite.failed_test_count())); - OutputXmlAttribute( - stream, kTestsuite, "disabled", - StreamableToString(test_suite.reportable_disabled_test_count())); - OutputXmlAttribute(stream, kTestsuite, "errors", "0"); - OutputXmlAttribute(stream, kTestsuite, "time", - FormatTimeInMillisAsSeconds(test_suite.elapsed_time())); - OutputXmlAttribute( - stream, kTestsuite, "timestamp", - FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp())); - *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result()); - } - *stream << ">\n"; - for (int i = 0; i < test_suite.total_test_count(); ++i) { - if (test_suite.GetTestInfo(i)->is_reportable()) - OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i)); - } - *stream << " \n"; -} - -// Prints an XML summary of unit_test to output stream out. -void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, - const UnitTest& unit_test) { - const std::string kTestsuites = "testsuites"; - - *stream << "\n"; - *stream << "<" << kTestsuites; - - OutputXmlAttribute(stream, kTestsuites, "tests", - StreamableToString(unit_test.reportable_test_count())); - OutputXmlAttribute(stream, kTestsuites, "failures", - StreamableToString(unit_test.failed_test_count())); - OutputXmlAttribute( - stream, kTestsuites, "disabled", - StreamableToString(unit_test.reportable_disabled_test_count())); - OutputXmlAttribute(stream, kTestsuites, "errors", "0"); - OutputXmlAttribute(stream, kTestsuites, "time", - FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); - OutputXmlAttribute( - stream, kTestsuites, "timestamp", - FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); - - if (GTEST_FLAG(shuffle)) { - OutputXmlAttribute(stream, kTestsuites, "random_seed", - StreamableToString(unit_test.random_seed())); - } - *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); - - OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); - *stream << ">\n"; - - for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { - if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) - PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i)); - } - *stream << "\n"; -} - -void XmlUnitTestResultPrinter::PrintXmlTestsList( - std::ostream* stream, const std::vector& test_suites) { - const std::string kTestsuites = "testsuites"; - - *stream << "\n"; - *stream << "<" << kTestsuites; - - int total_tests = 0; - for (auto test_suite : test_suites) { - total_tests += test_suite->total_test_count(); - } - OutputXmlAttribute(stream, kTestsuites, "tests", - StreamableToString(total_tests)); - OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); - *stream << ">\n"; - - for (auto test_suite : test_suites) { - PrintXmlTestSuite(stream, *test_suite); - } - *stream << "\n"; -} - -// Produces a string representing the test properties in a result as space -// delimited XML attributes based on the property key="value" pairs. -std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( - const TestResult& result) { - Message attributes; - for (int i = 0; i < result.test_property_count(); ++i) { - const TestProperty& property = result.GetTestProperty(i); - attributes << " " << property.key() << "=" - << "\"" << EscapeXmlAttribute(property.value()) << "\""; - } - return attributes.GetString(); -} - -void XmlUnitTestResultPrinter::OutputXmlTestProperties( - std::ostream* stream, const TestResult& result) { - const std::string kProperties = "properties"; - const std::string kProperty = "property"; - - if (result.test_property_count() <= 0) { - return; - } - - *stream << "<" << kProperties << ">\n"; - for (int i = 0; i < result.test_property_count(); ++i) { - const TestProperty& property = result.GetTestProperty(i); - *stream << "<" << kProperty; - *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\""; - *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\""; - *stream << "/>\n"; - } - *stream << "\n"; -} - -// End XmlUnitTestResultPrinter - -// This class generates an JSON output file. -class JsonUnitTestResultPrinter : public EmptyTestEventListener { - public: - explicit JsonUnitTestResultPrinter(const char* output_file); - - void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; - - // Prints an JSON summary of all unit tests. - static void PrintJsonTestList(::std::ostream* stream, - const std::vector& test_suites); - - private: - // Returns an JSON-escaped copy of the input string str. - static std::string EscapeJson(const std::string& str); - - //// Verifies that the given attribute belongs to the given element and - //// streams the attribute as JSON. - static void OutputJsonKey(std::ostream* stream, - const std::string& element_name, - const std::string& name, - const std::string& value, - const std::string& indent, - bool comma = true); - static void OutputJsonKey(std::ostream* stream, - const std::string& element_name, - const std::string& name, - int value, - const std::string& indent, - bool comma = true); - - // Streams a JSON representation of a TestInfo object. - static void OutputJsonTestInfo(::std::ostream* stream, - const char* test_suite_name, - const TestInfo& test_info); - - // Prints a JSON representation of a TestSuite object - static void PrintJsonTestSuite(::std::ostream* stream, - const TestSuite& test_suite); - - // Prints a JSON summary of unit_test to output stream out. - static void PrintJsonUnitTest(::std::ostream* stream, - const UnitTest& unit_test); - - // Produces a string representing the test properties in a result as - // a JSON dictionary. - static std::string TestPropertiesAsJson(const TestResult& result, - const std::string& indent); - - // The output file. - const std::string output_file_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(JsonUnitTestResultPrinter); -}; - -// Creates a new JsonUnitTestResultPrinter. -JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file) - : output_file_(output_file) { - if (output_file_.empty()) { - GTEST_LOG_(FATAL) << "JSON output file may not be null"; - } -} - -void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, - int /*iteration*/) { - FILE* jsonout = OpenFileForWriting(output_file_); - std::stringstream stream; - PrintJsonUnitTest(&stream, unit_test); - fprintf(jsonout, "%s", StringStreamToString(&stream).c_str()); - fclose(jsonout); -} - -// Returns an JSON-escaped copy of the input string str. -std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) { - Message m; - - for (size_t i = 0; i < str.size(); ++i) { - const char ch = str[i]; - switch (ch) { - case '\\': - case '"': - case '/': - m << '\\' << ch; - break; - case '\b': - m << "\\b"; - break; - case '\t': - m << "\\t"; - break; - case '\n': - m << "\\n"; - break; - case '\f': - m << "\\f"; - break; - case '\r': - m << "\\r"; - break; - default: - if (ch < ' ') { - m << "\\u00" << String::FormatByte(static_cast(ch)); - } else { - m << ch; - } - break; - } - } - - return m.GetString(); -} - -// The following routines generate an JSON representation of a UnitTest -// object. - -// Formats the given time in milliseconds as seconds. -static std::string FormatTimeInMillisAsDuration(TimeInMillis ms) { - ::std::stringstream ss; - ss << (static_cast(ms) * 1e-3) << "s"; - return ss.str(); -} - -// Converts the given epoch time in milliseconds to a date string in the -// RFC3339 format, without the timezone information. -static std::string FormatEpochTimeInMillisAsRFC3339(TimeInMillis ms) { - struct tm time_struct; - if (!PortableLocaltime(static_cast(ms / 1000), &time_struct)) - return ""; - // YYYY-MM-DDThh:mm:ss - return StreamableToString(time_struct.tm_year + 1900) + "-" + - String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" + - String::FormatIntWidth2(time_struct.tm_mday) + "T" + - String::FormatIntWidth2(time_struct.tm_hour) + ":" + - String::FormatIntWidth2(time_struct.tm_min) + ":" + - String::FormatIntWidth2(time_struct.tm_sec) + "Z"; -} - -static inline std::string Indent(size_t width) { - return std::string(width, ' '); -} - -void JsonUnitTestResultPrinter::OutputJsonKey( - std::ostream* stream, - const std::string& element_name, - const std::string& name, - const std::string& value, - const std::string& indent, - bool comma) { - const std::vector& allowed_names = - GetReservedOutputAttributesForElement(element_name); - - GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != - allowed_names.end()) - << "Key \"" << name << "\" is not allowed for value \"" << element_name - << "\"."; - - *stream << indent << "\"" << name << "\": \"" << EscapeJson(value) << "\""; - if (comma) - *stream << ",\n"; -} - -void JsonUnitTestResultPrinter::OutputJsonKey( - std::ostream* stream, - const std::string& element_name, - const std::string& name, - int value, - const std::string& indent, - bool comma) { - const std::vector& allowed_names = - GetReservedOutputAttributesForElement(element_name); - - GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != - allowed_names.end()) - << "Key \"" << name << "\" is not allowed for value \"" << element_name - << "\"."; - - *stream << indent << "\"" << name << "\": " << StreamableToString(value); - if (comma) - *stream << ",\n"; -} - -// Prints a JSON representation of a TestInfo object. -void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream, - const char* test_suite_name, - const TestInfo& test_info) { - const TestResult& result = *test_info.result(); - const std::string kTestsuite = "testcase"; - const std::string kIndent = Indent(10); - - *stream << Indent(8) << "{\n"; - OutputJsonKey(stream, kTestsuite, "name", test_info.name(), kIndent); - - if (test_info.value_param() != nullptr) { - OutputJsonKey(stream, kTestsuite, "value_param", test_info.value_param(), - kIndent); - } - if (test_info.type_param() != nullptr) { - OutputJsonKey(stream, kTestsuite, "type_param", test_info.type_param(), - kIndent); - } - if (GTEST_FLAG(list_tests)) { - OutputJsonKey(stream, kTestsuite, "file", test_info.file(), kIndent); - OutputJsonKey(stream, kTestsuite, "line", test_info.line(), kIndent, false); - *stream << "\n" << Indent(8) << "}"; - return; - } - - OutputJsonKey(stream, kTestsuite, "status", - test_info.should_run() ? "RUN" : "NOTRUN", kIndent); - OutputJsonKey(stream, kTestsuite, "result", - test_info.should_run() - ? (result.Skipped() ? "SKIPPED" : "COMPLETED") - : "SUPPRESSED", - kIndent); - OutputJsonKey(stream, kTestsuite, "timestamp", - FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()), - kIndent); - OutputJsonKey(stream, kTestsuite, "time", - FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent); - OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent, - false); - *stream << TestPropertiesAsJson(result, kIndent); - - int failures = 0; - for (int i = 0; i < result.total_part_count(); ++i) { - const TestPartResult& part = result.GetTestPartResult(i); - if (part.failed()) { - *stream << ",\n"; - if (++failures == 1) { - *stream << kIndent << "\"" << "failures" << "\": [\n"; - } - const std::string location = - internal::FormatCompilerIndependentFileLocation(part.file_name(), - part.line_number()); - const std::string message = EscapeJson(location + "\n" + part.message()); - *stream << kIndent << " {\n" - << kIndent << " \"failure\": \"" << message << "\",\n" - << kIndent << " \"type\": \"\"\n" - << kIndent << " }"; - } - } - - if (failures > 0) - *stream << "\n" << kIndent << "]"; - *stream << "\n" << Indent(8) << "}"; -} - -// Prints an JSON representation of a TestSuite object -void JsonUnitTestResultPrinter::PrintJsonTestSuite( - std::ostream* stream, const TestSuite& test_suite) { - const std::string kTestsuite = "testsuite"; - const std::string kIndent = Indent(6); - - *stream << Indent(4) << "{\n"; - OutputJsonKey(stream, kTestsuite, "name", test_suite.name(), kIndent); - OutputJsonKey(stream, kTestsuite, "tests", test_suite.reportable_test_count(), - kIndent); - if (!GTEST_FLAG(list_tests)) { - OutputJsonKey(stream, kTestsuite, "failures", - test_suite.failed_test_count(), kIndent); - OutputJsonKey(stream, kTestsuite, "disabled", - test_suite.reportable_disabled_test_count(), kIndent); - OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent); - OutputJsonKey( - stream, kTestsuite, "timestamp", - FormatEpochTimeInMillisAsRFC3339(test_suite.start_timestamp()), - kIndent); - OutputJsonKey(stream, kTestsuite, "time", - FormatTimeInMillisAsDuration(test_suite.elapsed_time()), - kIndent, false); - *stream << TestPropertiesAsJson(test_suite.ad_hoc_test_result(), kIndent) - << ",\n"; - } - - *stream << kIndent << "\"" << kTestsuite << "\": [\n"; - - bool comma = false; - for (int i = 0; i < test_suite.total_test_count(); ++i) { - if (test_suite.GetTestInfo(i)->is_reportable()) { - if (comma) { - *stream << ",\n"; - } else { - comma = true; - } - OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i)); - } - } - *stream << "\n" << kIndent << "]\n" << Indent(4) << "}"; -} - -// Prints a JSON summary of unit_test to output stream out. -void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream, - const UnitTest& unit_test) { - const std::string kTestsuites = "testsuites"; - const std::string kIndent = Indent(2); - *stream << "{\n"; - - OutputJsonKey(stream, kTestsuites, "tests", unit_test.reportable_test_count(), - kIndent); - OutputJsonKey(stream, kTestsuites, "failures", unit_test.failed_test_count(), - kIndent); - OutputJsonKey(stream, kTestsuites, "disabled", - unit_test.reportable_disabled_test_count(), kIndent); - OutputJsonKey(stream, kTestsuites, "errors", 0, kIndent); - if (GTEST_FLAG(shuffle)) { - OutputJsonKey(stream, kTestsuites, "random_seed", unit_test.random_seed(), - kIndent); - } - OutputJsonKey(stream, kTestsuites, "timestamp", - FormatEpochTimeInMillisAsRFC3339(unit_test.start_timestamp()), - kIndent); - OutputJsonKey(stream, kTestsuites, "time", - FormatTimeInMillisAsDuration(unit_test.elapsed_time()), kIndent, - false); - - *stream << TestPropertiesAsJson(unit_test.ad_hoc_test_result(), kIndent) - << ",\n"; - - OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent); - *stream << kIndent << "\"" << kTestsuites << "\": [\n"; - - bool comma = false; - for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { - if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) { - if (comma) { - *stream << ",\n"; - } else { - comma = true; - } - PrintJsonTestSuite(stream, *unit_test.GetTestSuite(i)); - } - } - - *stream << "\n" << kIndent << "]\n" << "}\n"; -} - -void JsonUnitTestResultPrinter::PrintJsonTestList( - std::ostream* stream, const std::vector& test_suites) { - const std::string kTestsuites = "testsuites"; - const std::string kIndent = Indent(2); - *stream << "{\n"; - int total_tests = 0; - for (auto test_suite : test_suites) { - total_tests += test_suite->total_test_count(); - } - OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent); - - OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent); - *stream << kIndent << "\"" << kTestsuites << "\": [\n"; - - for (size_t i = 0; i < test_suites.size(); ++i) { - if (i != 0) { - *stream << ",\n"; - } - PrintJsonTestSuite(stream, *test_suites[i]); - } - - *stream << "\n" - << kIndent << "]\n" - << "}\n"; -} -// Produces a string representing the test properties in a result as -// a JSON dictionary. -std::string JsonUnitTestResultPrinter::TestPropertiesAsJson( - const TestResult& result, const std::string& indent) { - Message attributes; - for (int i = 0; i < result.test_property_count(); ++i) { - const TestProperty& property = result.GetTestProperty(i); - attributes << ",\n" << indent << "\"" << property.key() << "\": " - << "\"" << EscapeJson(property.value()) << "\""; - } - return attributes.GetString(); -} - -// End JsonUnitTestResultPrinter - -#if GTEST_CAN_STREAM_RESULTS_ - -// Checks if str contains '=', '&', '%' or '\n' characters. If yes, -// replaces them by "%xx" where xx is their hexadecimal value. For -// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) -// in both time and space -- important as the input str may contain an -// arbitrarily long test failure message and stack trace. -std::string StreamingListener::UrlEncode(const char* str) { - std::string result; - result.reserve(strlen(str) + 1); - for (char ch = *str; ch != '\0'; ch = *++str) { - switch (ch) { - case '%': - case '=': - case '&': - case '\n': - result.append("%" + String::FormatByte(static_cast(ch))); - break; - default: - result.push_back(ch); - break; - } - } - return result; -} - -void StreamingListener::SocketWriter::MakeConnection() { - GTEST_CHECK_(sockfd_ == -1) - << "MakeConnection() can't be called when there is already a connection."; - - addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. - hints.ai_socktype = SOCK_STREAM; - addrinfo* servinfo = nullptr; - - // Use the getaddrinfo() to get a linked list of IP addresses for - // the given host name. - const int error_num = getaddrinfo( - host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); - if (error_num != 0) { - GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " - << gai_strerror(error_num); - } - - // Loop through all the results and connect to the first we can. - for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != nullptr; - cur_addr = cur_addr->ai_next) { - sockfd_ = socket( - cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); - if (sockfd_ != -1) { - // Connect the client socket to the server socket. - if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { - close(sockfd_); - sockfd_ = -1; - } - } - } - - freeaddrinfo(servinfo); // all done with this structure - - if (sockfd_ == -1) { - GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " - << host_name_ << ":" << port_num_; - } -} - -// End of class Streaming Listener -#endif // GTEST_CAN_STREAM_RESULTS__ - -// class OsStackTraceGetter - -const char* const OsStackTraceGetterInterface::kElidedFramesMarker = - "... " GTEST_NAME_ " internal frames ..."; - -std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count) - GTEST_LOCK_EXCLUDED_(mutex_) { -#if GTEST_HAS_ABSL - std::string result; - - if (max_depth <= 0) { - return result; - } - - max_depth = std::min(max_depth, kMaxStackTraceDepth); - - std::vector raw_stack(max_depth); - // Skips the frames requested by the caller, plus this function. - const int raw_stack_size = - absl::GetStackTrace(&raw_stack[0], max_depth, skip_count + 1); - - void* caller_frame = nullptr; - { - MutexLock lock(&mutex_); - caller_frame = caller_frame_; - } - - for (int i = 0; i < raw_stack_size; ++i) { - if (raw_stack[i] == caller_frame && - !GTEST_FLAG(show_internal_stack_frames)) { - // Add a marker to the trace and stop adding frames. - absl::StrAppend(&result, kElidedFramesMarker, "\n"); - break; - } - - char tmp[1024]; - const char* symbol = "(unknown)"; - if (absl::Symbolize(raw_stack[i], tmp, sizeof(tmp))) { - symbol = tmp; - } - - char line[1024]; - snprintf(line, sizeof(line), " %p: %s\n", raw_stack[i], symbol); - result += line; - } - - return result; - -#else // !GTEST_HAS_ABSL - static_cast(max_depth); - static_cast(skip_count); - return ""; -#endif // GTEST_HAS_ABSL -} - -void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) { -#if GTEST_HAS_ABSL - void* caller_frame = nullptr; - if (absl::GetStackTrace(&caller_frame, 1, 3) <= 0) { - caller_frame = nullptr; - } - - MutexLock lock(&mutex_); - caller_frame_ = caller_frame; -#endif // GTEST_HAS_ABSL -} - -// A helper class that creates the premature-exit file in its -// constructor and deletes the file in its destructor. -class ScopedPrematureExitFile { - public: - explicit ScopedPrematureExitFile(const char* premature_exit_filepath) - : premature_exit_filepath_(premature_exit_filepath ? - premature_exit_filepath : "") { - // If a path to the premature-exit file is specified... - if (!premature_exit_filepath_.empty()) { - // create the file with a single "0" character in it. I/O - // errors are ignored as there's nothing better we can do and we - // don't want to fail the test because of this. - FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); - fwrite("0", 1, 1, pfile); - fclose(pfile); - } - } - - ~ScopedPrematureExitFile() { - if (!premature_exit_filepath_.empty()) { - int retval = remove(premature_exit_filepath_.c_str()); - if (retval) { - GTEST_LOG_(ERROR) << "Failed to remove premature exit filepath \"" - << premature_exit_filepath_ << "\" with error " - << retval; - } - } - } - - private: - const std::string premature_exit_filepath_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); -}; - -} // namespace internal - -// class TestEventListeners - -TestEventListeners::TestEventListeners() - : repeater_(new internal::TestEventRepeater()), - default_result_printer_(nullptr), - default_xml_generator_(nullptr) {} - -TestEventListeners::~TestEventListeners() { delete repeater_; } - -// Returns the standard listener responsible for the default console -// output. Can be removed from the listeners list to shut down default -// console output. Note that removing this object from the listener list -// with Release transfers its ownership to the user. -void TestEventListeners::Append(TestEventListener* listener) { - repeater_->Append(listener); -} - -// Removes the given event listener from the list and returns it. It then -// becomes the caller's responsibility to delete the listener. Returns -// NULL if the listener is not found in the list. -TestEventListener* TestEventListeners::Release(TestEventListener* listener) { - if (listener == default_result_printer_) - default_result_printer_ = nullptr; - else if (listener == default_xml_generator_) - default_xml_generator_ = nullptr; - return repeater_->Release(listener); -} - -// Returns repeater that broadcasts the TestEventListener events to all -// subscribers. -TestEventListener* TestEventListeners::repeater() { return repeater_; } - -// Sets the default_result_printer attribute to the provided listener. -// The listener is also added to the listener list and previous -// default_result_printer is removed from it and deleted. The listener can -// also be NULL in which case it will not be added to the list. Does -// nothing if the previous and the current listener objects are the same. -void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { - if (default_result_printer_ != listener) { - // It is an error to pass this method a listener that is already in the - // list. - delete Release(default_result_printer_); - default_result_printer_ = listener; - if (listener != nullptr) Append(listener); - } -} - -// Sets the default_xml_generator attribute to the provided listener. The -// listener is also added to the listener list and previous -// default_xml_generator is removed from it and deleted. The listener can -// also be NULL in which case it will not be added to the list. Does -// nothing if the previous and the current listener objects are the same. -void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { - if (default_xml_generator_ != listener) { - // It is an error to pass this method a listener that is already in the - // list. - delete Release(default_xml_generator_); - default_xml_generator_ = listener; - if (listener != nullptr) Append(listener); - } -} - -// Controls whether events will be forwarded by the repeater to the -// listeners in the list. -bool TestEventListeners::EventForwardingEnabled() const { - return repeater_->forwarding_enabled(); -} - -void TestEventListeners::SuppressEventForwarding() { - repeater_->set_forwarding_enabled(false); -} - -// class UnitTest - -// Gets the singleton UnitTest object. The first time this method is -// called, a UnitTest object is constructed and returned. Consecutive -// calls will return the same object. -// -// We don't protect this under mutex_ as a user is not supposed to -// call this before main() starts, from which point on the return -// value will never change. -UnitTest* UnitTest::GetInstance() { - // CodeGear C++Builder insists on a public destructor for the - // default implementation. Use this implementation to keep good OO - // design with private destructor. - -#if defined(__BORLANDC__) - static UnitTest* const instance = new UnitTest; - return instance; -#else - static UnitTest instance; - return &instance; -#endif // defined(__BORLANDC__) -} - -// Gets the number of successful test suites. -int UnitTest::successful_test_suite_count() const { - return impl()->successful_test_suite_count(); -} - -// Gets the number of failed test suites. -int UnitTest::failed_test_suite_count() const { - return impl()->failed_test_suite_count(); -} - -// Gets the number of all test suites. -int UnitTest::total_test_suite_count() const { - return impl()->total_test_suite_count(); -} - -// Gets the number of all test suites that contain at least one test -// that should run. -int UnitTest::test_suite_to_run_count() const { - return impl()->test_suite_to_run_count(); -} - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -int UnitTest::successful_test_case_count() const { - return impl()->successful_test_suite_count(); -} -int UnitTest::failed_test_case_count() const { - return impl()->failed_test_suite_count(); -} -int UnitTest::total_test_case_count() const { - return impl()->total_test_suite_count(); -} -int UnitTest::test_case_to_run_count() const { - return impl()->test_suite_to_run_count(); -} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -// Gets the number of successful tests. -int UnitTest::successful_test_count() const { - return impl()->successful_test_count(); -} - -// Gets the number of skipped tests. -int UnitTest::skipped_test_count() const { - return impl()->skipped_test_count(); -} - -// Gets the number of failed tests. -int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } - -// Gets the number of disabled tests that will be reported in the XML report. -int UnitTest::reportable_disabled_test_count() const { - return impl()->reportable_disabled_test_count(); -} - -// Gets the number of disabled tests. -int UnitTest::disabled_test_count() const { - return impl()->disabled_test_count(); -} - -// Gets the number of tests to be printed in the XML report. -int UnitTest::reportable_test_count() const { - return impl()->reportable_test_count(); -} - -// Gets the number of all tests. -int UnitTest::total_test_count() const { return impl()->total_test_count(); } - -// Gets the number of tests that should run. -int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } - -// Gets the time of the test program start, in ms from the start of the -// UNIX epoch. -internal::TimeInMillis UnitTest::start_timestamp() const { - return impl()->start_timestamp(); -} - -// Gets the elapsed time, in milliseconds. -internal::TimeInMillis UnitTest::elapsed_time() const { - return impl()->elapsed_time(); -} - -// Returns true if and only if the unit test passed (i.e. all test suites -// passed). -bool UnitTest::Passed() const { return impl()->Passed(); } - -// Returns true if and only if the unit test failed (i.e. some test suite -// failed or something outside of all tests failed). -bool UnitTest::Failed() const { return impl()->Failed(); } - -// Gets the i-th test suite among all the test suites. i can range from 0 to -// total_test_suite_count() - 1. If i is not in that range, returns NULL. -const TestSuite* UnitTest::GetTestSuite(int i) const { - return impl()->GetTestSuite(i); -} - -// Legacy API is deprecated but still available -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -const TestCase* UnitTest::GetTestCase(int i) const { - return impl()->GetTestCase(i); -} -#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - -// Returns the TestResult containing information on test failures and -// properties logged outside of individual test suites. -const TestResult& UnitTest::ad_hoc_test_result() const { - return *impl()->ad_hoc_test_result(); -} - -// Gets the i-th test suite among all the test suites. i can range from 0 to -// total_test_suite_count() - 1. If i is not in that range, returns NULL. -TestSuite* UnitTest::GetMutableTestSuite(int i) { - return impl()->GetMutableSuiteCase(i); -} - -// Returns the list of event listeners that can be used to track events -// inside Google Test. -TestEventListeners& UnitTest::listeners() { - return *impl()->listeners(); -} - -// Registers and returns a global test environment. When a test -// program is run, all global test environments will be set-up in the -// order they were registered. After all tests in the program have -// finished, all global test environments will be torn-down in the -// *reverse* order they were registered. -// -// The UnitTest object takes ownership of the given environment. -// -// We don't protect this under mutex_, as we only support calling it -// from the main thread. -Environment* UnitTest::AddEnvironment(Environment* env) { - if (env == nullptr) { - return nullptr; - } - - impl_->environments().push_back(env); - return env; -} - -// Adds a TestPartResult to the current TestResult object. All Google Test -// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call -// this to report their results. The user code should use the -// assertion macros instead of calling this directly. -void UnitTest::AddTestPartResult( - TestPartResult::Type result_type, - const char* file_name, - int line_number, - const std::string& message, - const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { - Message msg; - msg << message; - - internal::MutexLock lock(&mutex_); - if (impl_->gtest_trace_stack().size() > 0) { - msg << "\n" << GTEST_NAME_ << " trace:"; - - for (size_t i = impl_->gtest_trace_stack().size(); i > 0; --i) { - const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; - msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) - << " " << trace.message; - } - } - - if (os_stack_trace.c_str() != nullptr && !os_stack_trace.empty()) { - msg << internal::kStackTraceMarker << os_stack_trace; - } - - const TestPartResult result = TestPartResult( - result_type, file_name, line_number, msg.GetString().c_str()); - impl_->GetTestPartResultReporterForCurrentThread()-> - ReportTestPartResult(result); - - if (result_type != TestPartResult::kSuccess && - result_type != TestPartResult::kSkip) { - // gtest_break_on_failure takes precedence over - // gtest_throw_on_failure. This allows a user to set the latter - // in the code (perhaps in order to use Google Test assertions - // with another testing framework) and specify the former on the - // command line for debugging. - if (GTEST_FLAG(break_on_failure)) { -#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT - // Using DebugBreak on Windows allows gtest to still break into a debugger - // when a failure happens and both the --gtest_break_on_failure and - // the --gtest_catch_exceptions flags are specified. - DebugBreak(); -#elif (!defined(__native_client__)) && \ - ((defined(__clang__) || defined(__GNUC__)) && \ - (defined(__x86_64__) || defined(__i386__))) - // with clang/gcc we can achieve the same effect on x86 by invoking int3 - asm("int3"); -#else - // Dereference nullptr through a volatile pointer to prevent the compiler - // from removing. We use this rather than abort() or __builtin_trap() for - // portability: some debuggers don't correctly trap abort(). - *static_cast(nullptr) = 1; -#endif // GTEST_OS_WINDOWS - } else if (GTEST_FLAG(throw_on_failure)) { -#if GTEST_HAS_EXCEPTIONS - throw internal::GoogleTestFailureException(result); -#else - // We cannot call abort() as it generates a pop-up in debug mode - // that cannot be suppressed in VC 7.1 or below. - exit(1); -#endif - } - } -} - -// Adds a TestProperty to the current TestResult object when invoked from -// inside a test, to current TestSuite's ad_hoc_test_result_ when invoked -// from SetUpTestSuite or TearDownTestSuite, or to the global property set -// when invoked elsewhere. If the result already contains a property with -// the same key, the value will be updated. -void UnitTest::RecordProperty(const std::string& key, - const std::string& value) { - impl_->RecordProperty(TestProperty(key, value)); -} - -// Runs all tests in this UnitTest object and prints the result. -// Returns 0 if successful, or 1 otherwise. -// -// We don't protect this under mutex_, as we only support calling it -// from the main thread. -int UnitTest::Run() { - const bool in_death_test_child_process = - internal::GTEST_FLAG(internal_run_death_test).length() > 0; - - // Google Test implements this protocol for catching that a test - // program exits before returning control to Google Test: - // - // 1. Upon start, Google Test creates a file whose absolute path - // is specified by the environment variable - // TEST_PREMATURE_EXIT_FILE. - // 2. When Google Test has finished its work, it deletes the file. - // - // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before - // running a Google-Test-based test program and check the existence - // of the file at the end of the test execution to see if it has - // exited prematurely. - - // If we are in the child process of a death test, don't - // create/delete the premature exit file, as doing so is unnecessary - // and will confuse the parent process. Otherwise, create/delete - // the file upon entering/leaving this function. If the program - // somehow exits before this function has a chance to return, the - // premature-exit file will be left undeleted, causing a test runner - // that understands the premature-exit-file protocol to report the - // test as having failed. - const internal::ScopedPrematureExitFile premature_exit_file( - in_death_test_child_process - ? nullptr - : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); - - // Captures the value of GTEST_FLAG(catch_exceptions). This value will be - // used for the duration of the program. - impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); - -#if GTEST_OS_WINDOWS - // Either the user wants Google Test to catch exceptions thrown by the - // tests or this is executing in the context of death test child - // process. In either case the user does not want to see pop-up dialogs - // about crashes - they are expected. - if (impl()->catch_exceptions() || in_death_test_child_process) { -# if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT - // SetErrorMode doesn't exist on CE. - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | - SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); -# endif // !GTEST_OS_WINDOWS_MOBILE - -# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE - // Death test children can be terminated with _abort(). On Windows, - // _abort() can show a dialog with a warning message. This forces the - // abort message to go to stderr instead. - _set_error_mode(_OUT_TO_STDERR); -# endif - -# if defined(_MSC_VER) && !GTEST_OS_WINDOWS_MOBILE - // In the debug version, Visual Studio pops up a separate dialog - // offering a choice to debug the aborted program. We need to suppress - // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement - // executed. Google Test will notify the user of any unexpected - // failure via stderr. - if (!GTEST_FLAG(break_on_failure)) - _set_abort_behavior( - 0x0, // Clear the following flags: - _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. -# endif - - // In debug mode, the Windows CRT can crash with an assertion over invalid - // input (e.g. passing an invalid file descriptor). The default handling - // for these assertions is to pop up a dialog and wait for user input. - // Instead ask the CRT to dump such assertions to stderr non-interactively. - if (!IsDebuggerPresent()) { - (void)_CrtSetReportMode(_CRT_ASSERT, - _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - } - } -#endif // GTEST_OS_WINDOWS - - return internal::HandleExceptionsInMethodIfSupported( - impl(), - &internal::UnitTestImpl::RunAllTests, - "auxiliary test code (environments or event listeners)") ? 0 : 1; -} - -// Returns the working directory when the first TEST() or TEST_F() was -// executed. -const char* UnitTest::original_working_dir() const { - return impl_->original_working_dir_.c_str(); -} - -// Returns the TestSuite object for the test that's currently running, -// or NULL if no test is running. -const TestSuite* UnitTest::current_test_suite() const - GTEST_LOCK_EXCLUDED_(mutex_) { - internal::MutexLock lock(&mutex_); - return impl_->current_test_suite(); -} - -// Legacy API is still available but deprecated -#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -const TestCase* UnitTest::current_test_case() const - GTEST_LOCK_EXCLUDED_(mutex_) { - internal::MutexLock lock(&mutex_); - return impl_->current_test_suite(); -} -#endif - -// Returns the TestInfo object for the test that's currently running, -// or NULL if no test is running. -const TestInfo* UnitTest::current_test_info() const - GTEST_LOCK_EXCLUDED_(mutex_) { - internal::MutexLock lock(&mutex_); - return impl_->current_test_info(); -} - -// Returns the random seed used at the start of the current test run. -int UnitTest::random_seed() const { return impl_->random_seed(); } - -// Returns ParameterizedTestSuiteRegistry object used to keep track of -// value-parameterized tests and instantiate and register them. -internal::ParameterizedTestSuiteRegistry& -UnitTest::parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_) { - return impl_->parameterized_test_registry(); -} - -// Creates an empty UnitTest. -UnitTest::UnitTest() { - impl_ = new internal::UnitTestImpl(this); -} - -// Destructor of UnitTest. -UnitTest::~UnitTest() { - delete impl_; -} - -// Pushes a trace defined by SCOPED_TRACE() on to the per-thread -// Google Test trace stack. -void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) - GTEST_LOCK_EXCLUDED_(mutex_) { - internal::MutexLock lock(&mutex_); - impl_->gtest_trace_stack().push_back(trace); -} - -// Pops a trace from the per-thread Google Test trace stack. -void UnitTest::PopGTestTrace() - GTEST_LOCK_EXCLUDED_(mutex_) { - internal::MutexLock lock(&mutex_); - impl_->gtest_trace_stack().pop_back(); -} - -namespace internal { - -UnitTestImpl::UnitTestImpl(UnitTest* parent) - : parent_(parent), - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */) - default_global_test_part_result_reporter_(this), - default_per_thread_test_part_result_reporter_(this), - GTEST_DISABLE_MSC_WARNINGS_POP_() global_test_part_result_repoter_( - &default_global_test_part_result_reporter_), - per_thread_test_part_result_reporter_( - &default_per_thread_test_part_result_reporter_), - parameterized_test_registry_(), - parameterized_tests_registered_(false), - last_death_test_suite_(-1), - current_test_suite_(nullptr), - current_test_info_(nullptr), - ad_hoc_test_result_(), - os_stack_trace_getter_(nullptr), - post_flag_parse_init_performed_(false), - random_seed_(0), // Will be overridden by the flag before first use. - random_(0), // Will be reseeded before first use. - start_timestamp_(0), - elapsed_time_(0), -#if GTEST_HAS_DEATH_TEST - death_test_factory_(new DefaultDeathTestFactory), -#endif - // Will be overridden by the flag before first use. - catch_exceptions_(false) { - listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); -} - -UnitTestImpl::~UnitTestImpl() { - // Deletes every TestSuite. - ForEach(test_suites_, internal::Delete); - - // Deletes every Environment. - ForEach(environments_, internal::Delete); - - delete os_stack_trace_getter_; -} - -// Adds a TestProperty to the current TestResult object when invoked in a -// context of a test, to current test suite's ad_hoc_test_result when invoke -// from SetUpTestSuite/TearDownTestSuite, or to the global property set -// otherwise. If the result already contains a property with the same key, -// the value will be updated. -void UnitTestImpl::RecordProperty(const TestProperty& test_property) { - std::string xml_element; - TestResult* test_result; // TestResult appropriate for property recording. - - if (current_test_info_ != nullptr) { - xml_element = "testcase"; - test_result = &(current_test_info_->result_); - } else if (current_test_suite_ != nullptr) { - xml_element = "testsuite"; - test_result = &(current_test_suite_->ad_hoc_test_result_); - } else { - xml_element = "testsuites"; - test_result = &ad_hoc_test_result_; - } - test_result->RecordProperty(xml_element, test_property); -} - -#if GTEST_HAS_DEATH_TEST -// Disables event forwarding if the control is currently in a death test -// subprocess. Must not be called before InitGoogleTest. -void UnitTestImpl::SuppressTestEventsIfInSubprocess() { - if (internal_run_death_test_flag_.get() != nullptr) - listeners()->SuppressEventForwarding(); -} -#endif // GTEST_HAS_DEATH_TEST - -// Initializes event listeners performing XML output as specified by -// UnitTestOptions. Must not be called before InitGoogleTest. -void UnitTestImpl::ConfigureXmlOutput() { - const std::string& output_format = UnitTestOptions::GetOutputFormat(); - if (output_format == "xml") { - listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( - UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); - } else if (output_format == "json") { - listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter( - UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); - } else if (output_format != "") { - GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \"" - << output_format << "\" ignored."; - } -} - -#if GTEST_CAN_STREAM_RESULTS_ -// Initializes event listeners for streaming test results in string form. -// Must not be called before InitGoogleTest. -void UnitTestImpl::ConfigureStreamingOutput() { - const std::string& target = GTEST_FLAG(stream_result_to); - if (!target.empty()) { - const size_t pos = target.find(':'); - if (pos != std::string::npos) { - listeners()->Append(new StreamingListener(target.substr(0, pos), - target.substr(pos+1))); - } else { - GTEST_LOG_(WARNING) << "unrecognized streaming target \"" << target - << "\" ignored."; - } - } -} -#endif // GTEST_CAN_STREAM_RESULTS_ - -// Performs initialization dependent upon flag values obtained in -// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to -// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest -// this function is also called from RunAllTests. Since this function can be -// called more than once, it has to be idempotent. -void UnitTestImpl::PostFlagParsingInit() { - // Ensures that this function does not execute more than once. - if (!post_flag_parse_init_performed_) { - post_flag_parse_init_performed_ = true; - -#if defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_) - // Register to send notifications about key process state changes. - listeners()->Append(new GTEST_CUSTOM_TEST_EVENT_LISTENER_()); -#endif // defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_) - -#if GTEST_HAS_DEATH_TEST - InitDeathTestSubprocessControlInfo(); - SuppressTestEventsIfInSubprocess(); -#endif // GTEST_HAS_DEATH_TEST - - // Registers parameterized tests. This makes parameterized tests - // available to the UnitTest reflection API without running - // RUN_ALL_TESTS. - RegisterParameterizedTests(); - - // Configures listeners for XML output. This makes it possible for users - // to shut down the default XML output before invoking RUN_ALL_TESTS. - ConfigureXmlOutput(); - -#if GTEST_CAN_STREAM_RESULTS_ - // Configures listeners for streaming test results to the specified server. - ConfigureStreamingOutput(); -#endif // GTEST_CAN_STREAM_RESULTS_ - -#if GTEST_HAS_ABSL - if (GTEST_FLAG(install_failure_signal_handler)) { - absl::FailureSignalHandlerOptions options; - absl::InstallFailureSignalHandler(options); - } -#endif // GTEST_HAS_ABSL - } -} - -// A predicate that checks the name of a TestSuite against a known -// value. -// -// This is used for implementation of the UnitTest class only. We put -// it in the anonymous namespace to prevent polluting the outer -// namespace. -// -// TestSuiteNameIs is copyable. -class TestSuiteNameIs { - public: - // Constructor. - explicit TestSuiteNameIs(const std::string& name) : name_(name) {} - - // Returns true if and only if the name of test_suite matches name_. - bool operator()(const TestSuite* test_suite) const { - return test_suite != nullptr && - strcmp(test_suite->name(), name_.c_str()) == 0; - } - - private: - std::string name_; -}; - -// Finds and returns a TestSuite with the given name. If one doesn't -// exist, creates one and returns it. It's the CALLER'S -// RESPONSIBILITY to ensure that this function is only called WHEN THE -// TESTS ARE NOT SHUFFLED. -// -// Arguments: -// -// test_suite_name: name of the test suite -// type_param: the name of the test suite's type parameter, or NULL if -// this is not a typed or a type-parameterized test suite. -// set_up_tc: pointer to the function that sets up the test suite -// tear_down_tc: pointer to the function that tears down the test suite -TestSuite* UnitTestImpl::GetTestSuite( - const char* test_suite_name, const char* type_param, - internal::SetUpTestSuiteFunc set_up_tc, - internal::TearDownTestSuiteFunc tear_down_tc) { - // Can we find a TestSuite with the given name? - const auto test_suite = - std::find_if(test_suites_.rbegin(), test_suites_.rend(), - TestSuiteNameIs(test_suite_name)); - - if (test_suite != test_suites_.rend()) return *test_suite; - - // No. Let's create one. - auto* const new_test_suite = - new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc); - - // Is this a death test suite? - if (internal::UnitTestOptions::MatchesFilter(test_suite_name, - kDeathTestSuiteFilter)) { - // Yes. Inserts the test suite after the last death test suite - // defined so far. This only works when the test suites haven't - // been shuffled. Otherwise we may end up running a death test - // after a non-death test. - ++last_death_test_suite_; - test_suites_.insert(test_suites_.begin() + last_death_test_suite_, - new_test_suite); - } else { - // No. Appends to the end of the list. - test_suites_.push_back(new_test_suite); - } - - test_suite_indices_.push_back(static_cast(test_suite_indices_.size())); - return new_test_suite; -} - -// Helpers for setting up / tearing down the given environment. They -// are for use in the ForEach() function. -static void SetUpEnvironment(Environment* env) { env->SetUp(); } -static void TearDownEnvironment(Environment* env) { env->TearDown(); } - -// Runs all tests in this UnitTest object, prints the result, and -// returns true if all tests are successful. If any exception is -// thrown during a test, the test is considered to be failed, but the -// rest of the tests will still be run. -// -// When parameterized tests are enabled, it expands and registers -// parameterized tests first in RegisterParameterizedTests(). -// All other functions called from RunAllTests() may safely assume that -// parameterized tests are ready to be counted and run. -bool UnitTestImpl::RunAllTests() { - // True if and only if Google Test is initialized before RUN_ALL_TESTS() is - // called. - const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized(); - - // Do not run any test if the --help flag was specified. - if (g_help_flag) - return true; - - // Repeats the call to the post-flag parsing initialization in case the - // user didn't call InitGoogleTest. - PostFlagParsingInit(); - - // Even if sharding is not on, test runners may want to use the - // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding - // protocol. - internal::WriteToShardStatusFileIfNeeded(); - - // True if and only if we are in a subprocess for running a thread-safe-style - // death test. - bool in_subprocess_for_death_test = false; - -#if GTEST_HAS_DEATH_TEST - in_subprocess_for_death_test = - (internal_run_death_test_flag_.get() != nullptr); -# if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_) - if (in_subprocess_for_death_test) { - GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_(); - } -# endif // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_) -#endif // GTEST_HAS_DEATH_TEST - - const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, - in_subprocess_for_death_test); - - // Compares the full test names with the filter to decide which - // tests to run. - const bool has_tests_to_run = FilterTests(should_shard - ? HONOR_SHARDING_PROTOCOL - : IGNORE_SHARDING_PROTOCOL) > 0; - - // Lists the tests and exits if the --gtest_list_tests flag was specified. - if (GTEST_FLAG(list_tests)) { - // This must be called *after* FilterTests() has been called. - ListTestsMatchingFilter(); - return true; - } - - random_seed_ = GTEST_FLAG(shuffle) ? - GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; - - // True if and only if at least one test has failed. - bool failed = false; - - TestEventListener* repeater = listeners()->repeater(); - - start_timestamp_ = GetTimeInMillis(); - repeater->OnTestProgramStart(*parent_); - - // How many times to repeat the tests? We don't want to repeat them - // when we are inside the subprocess of a death test. - const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); - // Repeats forever if the repeat count is negative. - const bool gtest_repeat_forever = repeat < 0; - for (int i = 0; gtest_repeat_forever || i != repeat; i++) { - // We want to preserve failures generated by ad-hoc test - // assertions executed before RUN_ALL_TESTS(). - ClearNonAdHocTestResult(); - - const TimeInMillis start = GetTimeInMillis(); - - // Shuffles test suites and tests if requested. - if (has_tests_to_run && GTEST_FLAG(shuffle)) { - random()->Reseed(static_cast(random_seed_)); - // This should be done before calling OnTestIterationStart(), - // such that a test event listener can see the actual test order - // in the event. - ShuffleTests(); - } - - // Tells the unit test event listeners that the tests are about to start. - repeater->OnTestIterationStart(*parent_, i); - - // Runs each test suite if there is at least one test to run. - if (has_tests_to_run) { - // Sets up all environments beforehand. - repeater->OnEnvironmentsSetUpStart(*parent_); - ForEach(environments_, SetUpEnvironment); - repeater->OnEnvironmentsSetUpEnd(*parent_); - - // Runs the tests only if there was no fatal failure or skip triggered - // during global set-up. - if (Test::IsSkipped()) { - // Emit diagnostics when global set-up calls skip, as it will not be - // emitted by default. - TestResult& test_result = - *internal::GetUnitTestImpl()->current_test_result(); - for (int j = 0; j < test_result.total_part_count(); ++j) { - const TestPartResult& test_part_result = - test_result.GetTestPartResult(j); - if (test_part_result.type() == TestPartResult::kSkip) { - const std::string& result = test_part_result.message(); - printf("%s\n", result.c_str()); - } - } - fflush(stdout); - } else if (!Test::HasFatalFailure()) { - for (int test_index = 0; test_index < total_test_suite_count(); - test_index++) { - GetMutableSuiteCase(test_index)->Run(); - } - } - - // Tears down all environments in reverse order afterwards. - repeater->OnEnvironmentsTearDownStart(*parent_); - std::for_each(environments_.rbegin(), environments_.rend(), - TearDownEnvironment); - repeater->OnEnvironmentsTearDownEnd(*parent_); - } - - elapsed_time_ = GetTimeInMillis() - start; - - // Tells the unit test event listener that the tests have just finished. - repeater->OnTestIterationEnd(*parent_, i); - - // Gets the result and clears it. - if (!Passed()) { - failed = true; - } - - // Restores the original test order after the iteration. This - // allows the user to quickly repro a failure that happens in the - // N-th iteration without repeating the first (N - 1) iterations. - // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in - // case the user somehow changes the value of the flag somewhere - // (it's always safe to unshuffle the tests). - UnshuffleTests(); - - if (GTEST_FLAG(shuffle)) { - // Picks a new random seed for each iteration. - random_seed_ = GetNextRandomSeed(random_seed_); - } - } - - repeater->OnTestProgramEnd(*parent_); - - if (!gtest_is_initialized_before_run_all_tests) { - ColoredPrintf( - COLOR_RED, - "\nIMPORTANT NOTICE - DO NOT IGNORE:\n" - "This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_ - "() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_ - " will start to enforce the valid usage. " - "Please fix it ASAP, or IT WILL START TO FAIL.\n"); // NOLINT -#if GTEST_FOR_GOOGLE_ - ColoredPrintf(COLOR_RED, - "For more details, see http://wiki/Main/ValidGUnitMain.\n"); -#endif // GTEST_FOR_GOOGLE_ - } - - return !failed; -} - -// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file -// if the variable is present. If a file already exists at this location, this -// function will write over it. If the variable is present, but the file cannot -// be created, prints an error and exits. -void WriteToShardStatusFileIfNeeded() { - const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); - if (test_shard_file != nullptr) { - FILE* const file = posix::FOpen(test_shard_file, "w"); - if (file == nullptr) { - ColoredPrintf(COLOR_RED, - "Could not write to the test shard status file \"%s\" " - "specified by the %s environment variable.\n", - test_shard_file, kTestShardStatusFile); - fflush(stdout); - exit(EXIT_FAILURE); - } - fclose(file); - } -} - -// Checks whether sharding is enabled by examining the relevant -// environment variable values. If the variables are present, -// but inconsistent (i.e., shard_index >= total_shards), prints -// an error and exits. If in_subprocess_for_death_test, sharding is -// disabled because it must only be applied to the original test -// process. Otherwise, we could filter out death tests we intended to execute. -bool ShouldShard(const char* total_shards_env, - const char* shard_index_env, - bool in_subprocess_for_death_test) { - if (in_subprocess_for_death_test) { - return false; - } - - const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); - const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); - - if (total_shards == -1 && shard_index == -1) { - return false; - } else if (total_shards == -1 && shard_index != -1) { - const Message msg = Message() - << "Invalid environment variables: you have " - << kTestShardIndex << " = " << shard_index - << ", but have left " << kTestTotalShards << " unset.\n"; - ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str()); - fflush(stdout); - exit(EXIT_FAILURE); - } else if (total_shards != -1 && shard_index == -1) { - const Message msg = Message() - << "Invalid environment variables: you have " - << kTestTotalShards << " = " << total_shards - << ", but have left " << kTestShardIndex << " unset.\n"; - ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str()); - fflush(stdout); - exit(EXIT_FAILURE); - } else if (shard_index < 0 || shard_index >= total_shards) { - const Message msg = Message() - << "Invalid environment variables: we require 0 <= " - << kTestShardIndex << " < " << kTestTotalShards - << ", but you have " << kTestShardIndex << "=" << shard_index - << ", " << kTestTotalShards << "=" << total_shards << ".\n"; - ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str()); - fflush(stdout); - exit(EXIT_FAILURE); - } - - return total_shards > 1; -} - -// Parses the environment variable var as an Int32. If it is unset, -// returns default_val. If it is not an Int32, prints an error -// and aborts. -Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { - const char* str_val = posix::GetEnv(var); - if (str_val == nullptr) { - return default_val; - } - - Int32 result; - if (!ParseInt32(Message() << "The value of environment variable " << var, - str_val, &result)) { - exit(EXIT_FAILURE); - } - return result; -} - -// Given the total number of shards, the shard index, and the test id, -// returns true if and only if the test should be run on this shard. The test id -// is some arbitrary but unique non-negative integer assigned to each test -// method. Assumes that 0 <= shard_index < total_shards. -bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { - return (test_id % total_shards) == shard_index; -} - -// Compares the name of each test with the user-specified filter to -// decide whether the test should be run, then records the result in -// each TestSuite and TestInfo object. -// If shard_tests == true, further filters tests based on sharding -// variables in the environment - see -// https://github.com/google/googletest/blob/master/googletest/docs/advanced.md -// . Returns the number of tests that should run. -int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { - const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? - Int32FromEnvOrDie(kTestTotalShards, -1) : -1; - const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? - Int32FromEnvOrDie(kTestShardIndex, -1) : -1; - - // num_runnable_tests are the number of tests that will - // run across all shards (i.e., match filter and are not disabled). - // num_selected_tests are the number of tests to be run on - // this shard. - int num_runnable_tests = 0; - int num_selected_tests = 0; - for (auto* test_suite : test_suites_) { - const std::string& test_suite_name = test_suite->name(); - test_suite->set_should_run(false); - - for (size_t j = 0; j < test_suite->test_info_list().size(); j++) { - TestInfo* const test_info = test_suite->test_info_list()[j]; - const std::string test_name(test_info->name()); - // A test is disabled if test suite name or test name matches - // kDisableTestFilter. - const bool is_disabled = internal::UnitTestOptions::MatchesFilter( - test_suite_name, kDisableTestFilter) || - internal::UnitTestOptions::MatchesFilter( - test_name, kDisableTestFilter); - test_info->is_disabled_ = is_disabled; - - const bool matches_filter = internal::UnitTestOptions::FilterMatchesTest( - test_suite_name, test_name); - test_info->matches_filter_ = matches_filter; - - const bool is_runnable = - (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && - matches_filter; - - const bool is_in_another_shard = - shard_tests != IGNORE_SHARDING_PROTOCOL && - !ShouldRunTestOnShard(total_shards, shard_index, num_runnable_tests); - test_info->is_in_another_shard_ = is_in_another_shard; - const bool is_selected = is_runnable && !is_in_another_shard; - - num_runnable_tests += is_runnable; - num_selected_tests += is_selected; - - test_info->should_run_ = is_selected; - test_suite->set_should_run(test_suite->should_run() || is_selected); - } - } - return num_selected_tests; -} - -// Prints the given C-string on a single line by replacing all '\n' -// characters with string "\\n". If the output takes more than -// max_length characters, only prints the first max_length characters -// and "...". -static void PrintOnOneLine(const char* str, int max_length) { - if (str != nullptr) { - for (int i = 0; *str != '\0'; ++str) { - if (i >= max_length) { - printf("..."); - break; - } - if (*str == '\n') { - printf("\\n"); - i += 2; - } else { - printf("%c", *str); - ++i; - } - } - } -} - -// Prints the names of the tests matching the user-specified filter flag. -void UnitTestImpl::ListTestsMatchingFilter() { - // Print at most this many characters for each type/value parameter. - const int kMaxParamLength = 250; - - for (auto* test_suite : test_suites_) { - bool printed_test_suite_name = false; - - for (size_t j = 0; j < test_suite->test_info_list().size(); j++) { - const TestInfo* const test_info = test_suite->test_info_list()[j]; - if (test_info->matches_filter_) { - if (!printed_test_suite_name) { - printed_test_suite_name = true; - printf("%s.", test_suite->name()); - if (test_suite->type_param() != nullptr) { - printf(" # %s = ", kTypeParamLabel); - // We print the type parameter on a single line to make - // the output easy to parse by a program. - PrintOnOneLine(test_suite->type_param(), kMaxParamLength); - } - printf("\n"); - } - printf(" %s", test_info->name()); - if (test_info->value_param() != nullptr) { - printf(" # %s = ", kValueParamLabel); - // We print the value parameter on a single line to make the - // output easy to parse by a program. - PrintOnOneLine(test_info->value_param(), kMaxParamLength); - } - printf("\n"); - } - } - } - fflush(stdout); - const std::string& output_format = UnitTestOptions::GetOutputFormat(); - if (output_format == "xml" || output_format == "json") { - FILE* fileout = OpenFileForWriting( - UnitTestOptions::GetAbsolutePathToOutputFile().c_str()); - std::stringstream stream; - if (output_format == "xml") { - XmlUnitTestResultPrinter( - UnitTestOptions::GetAbsolutePathToOutputFile().c_str()) - .PrintXmlTestsList(&stream, test_suites_); - } else if (output_format == "json") { - JsonUnitTestResultPrinter( - UnitTestOptions::GetAbsolutePathToOutputFile().c_str()) - .PrintJsonTestList(&stream, test_suites_); - } - fprintf(fileout, "%s", StringStreamToString(&stream).c_str()); - fclose(fileout); - } -} - -// Sets the OS stack trace getter. -// -// Does nothing if the input and the current OS stack trace getter are -// the same; otherwise, deletes the old getter and makes the input the -// current getter. -void UnitTestImpl::set_os_stack_trace_getter( - OsStackTraceGetterInterface* getter) { - if (os_stack_trace_getter_ != getter) { - delete os_stack_trace_getter_; - os_stack_trace_getter_ = getter; - } -} - -// Returns the current OS stack trace getter if it is not NULL; -// otherwise, creates an OsStackTraceGetter, makes it the current -// getter, and returns it. -OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { - if (os_stack_trace_getter_ == nullptr) { -#ifdef GTEST_OS_STACK_TRACE_GETTER_ - os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_; -#else - os_stack_trace_getter_ = new OsStackTraceGetter; -#endif // GTEST_OS_STACK_TRACE_GETTER_ - } - - return os_stack_trace_getter_; -} - -// Returns the most specific TestResult currently running. -TestResult* UnitTestImpl::current_test_result() { - if (current_test_info_ != nullptr) { - return ¤t_test_info_->result_; - } - if (current_test_suite_ != nullptr) { - return ¤t_test_suite_->ad_hoc_test_result_; - } - return &ad_hoc_test_result_; -} - -// Shuffles all test suites, and the tests within each test suite, -// making sure that death tests are still run first. -void UnitTestImpl::ShuffleTests() { - // Shuffles the death test suites. - ShuffleRange(random(), 0, last_death_test_suite_ + 1, &test_suite_indices_); - - // Shuffles the non-death test suites. - ShuffleRange(random(), last_death_test_suite_ + 1, - static_cast(test_suites_.size()), &test_suite_indices_); - - // Shuffles the tests inside each test suite. - for (auto& test_suite : test_suites_) { - test_suite->ShuffleTests(random()); - } -} - -// Restores the test suites and tests to their order before the first shuffle. -void UnitTestImpl::UnshuffleTests() { - for (size_t i = 0; i < test_suites_.size(); i++) { - // Unshuffles the tests in each test suite. - test_suites_[i]->UnshuffleTests(); - // Resets the index of each test suite. - test_suite_indices_[i] = static_cast(i); - } -} - -// Returns the current OS stack trace as an std::string. -// -// The maximum number of stack frames to be included is specified by -// the gtest_stack_trace_depth flag. The skip_count parameter -// specifies the number of top frames to be skipped, which doesn't -// count against the number of frames to be included. -// -// For example, if Foo() calls Bar(), which in turn calls -// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in -// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. -std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, - int skip_count) { - // We pass skip_count + 1 to skip this wrapper function in addition - // to what the user really wants to skip. - return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); -} - -// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to -// suppress unreachable code warnings. -namespace { -class ClassUniqueToAlwaysTrue {}; -} - -bool IsTrue(bool condition) { return condition; } - -bool AlwaysTrue() { -#if GTEST_HAS_EXCEPTIONS - // This condition is always false so AlwaysTrue() never actually throws, - // but it makes the compiler think that it may throw. - if (IsTrue(false)) - throw ClassUniqueToAlwaysTrue(); -#endif // GTEST_HAS_EXCEPTIONS - return true; -} - -// If *pstr starts with the given prefix, modifies *pstr to be right -// past the prefix and returns true; otherwise leaves *pstr unchanged -// and returns false. None of pstr, *pstr, and prefix can be NULL. -bool SkipPrefix(const char* prefix, const char** pstr) { - const size_t prefix_len = strlen(prefix); - if (strncmp(*pstr, prefix, prefix_len) == 0) { - *pstr += prefix_len; - return true; - } - return false; -} - -// Parses a string as a command line flag. The string should have -// the format "--flag=value". When def_optional is true, the "=value" -// part can be omitted. -// -// Returns the value of the flag, or NULL if the parsing failed. -static const char* ParseFlagValue(const char* str, const char* flag, - bool def_optional) { - // str and flag must not be NULL. - if (str == nullptr || flag == nullptr) return nullptr; - - // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. - const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag; - const size_t flag_len = flag_str.length(); - if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr; - - // Skips the flag name. - const char* flag_end = str + flag_len; - - // When def_optional is true, it's OK to not have a "=value" part. - if (def_optional && (flag_end[0] == '\0')) { - return flag_end; - } - - // If def_optional is true and there are more characters after the - // flag name, or if def_optional is false, there must be a '=' after - // the flag name. - if (flag_end[0] != '=') return nullptr; - - // Returns the string after "=". - return flag_end + 1; -} - -// Parses a string for a bool flag, in the form of either -// "--flag=value" or "--flag". -// -// In the former case, the value is taken as true as long as it does -// not start with '0', 'f', or 'F'. -// -// In the latter case, the value is taken as true. -// -// On success, stores the value of the flag in *value, and returns -// true. On failure, returns false without changing *value. -static bool ParseBoolFlag(const char* str, const char* flag, bool* value) { - // Gets the value of the flag as a string. - const char* const value_str = ParseFlagValue(str, flag, true); - - // Aborts if the parsing failed. - if (value_str == nullptr) return false; - - // Converts the string value to a bool. - *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); - return true; -} - -// Parses a string for an Int32 flag, in the form of -// "--flag=value". -// -// On success, stores the value of the flag in *value, and returns -// true. On failure, returns false without changing *value. -bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { - // Gets the value of the flag as a string. - const char* const value_str = ParseFlagValue(str, flag, false); - - // Aborts if the parsing failed. - if (value_str == nullptr) return false; - - // Sets *value to the value of the flag. - return ParseInt32(Message() << "The value of flag --" << flag, - value_str, value); -} - -// Parses a string for a string flag, in the form of -// "--flag=value". -// -// On success, stores the value of the flag in *value, and returns -// true. On failure, returns false without changing *value. -template -static bool ParseStringFlag(const char* str, const char* flag, String* value) { - // Gets the value of the flag as a string. - const char* const value_str = ParseFlagValue(str, flag, false); - - // Aborts if the parsing failed. - if (value_str == nullptr) return false; - - // Sets *value to the value of the flag. - *value = value_str; - return true; -} - -// Determines whether a string has a prefix that Google Test uses for its -// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. -// If Google Test detects that a command line flag has its prefix but is not -// recognized, it will print its help message. Flags starting with -// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test -// internal flags and do not trigger the help message. -static bool HasGoogleTestFlagPrefix(const char* str) { - return (SkipPrefix("--", &str) || - SkipPrefix("-", &str) || - SkipPrefix("/", &str)) && - !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && - (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || - SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); -} - -// Prints a string containing code-encoded text. The following escape -// sequences can be used in the string to control the text color: -// -// @@ prints a single '@' character. -// @R changes the color to red. -// @G changes the color to green. -// @Y changes the color to yellow. -// @D changes to the default terminal text color. -// -static void PrintColorEncoded(const char* str) { - GTestColor color = COLOR_DEFAULT; // The current color. - - // Conceptually, we split the string into segments divided by escape - // sequences. Then we print one segment at a time. At the end of - // each iteration, the str pointer advances to the beginning of the - // next segment. - for (;;) { - const char* p = strchr(str, '@'); - if (p == nullptr) { - ColoredPrintf(color, "%s", str); - return; - } - - ColoredPrintf(color, "%s", std::string(str, p).c_str()); - - const char ch = p[1]; - str = p + 2; - if (ch == '@') { - ColoredPrintf(color, "@"); - } else if (ch == 'D') { - color = COLOR_DEFAULT; - } else if (ch == 'R') { - color = COLOR_RED; - } else if (ch == 'G') { - color = COLOR_GREEN; - } else if (ch == 'Y') { - color = COLOR_YELLOW; - } else { - --str; - } - } -} - -static const char kColorEncodedHelpMessage[] = -"This program contains tests written using " GTEST_NAME_ ". You can use the\n" -"following command line flags to control its behavior:\n" -"\n" -"Test Selection:\n" -" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" -" List the names of all tests instead of running them. The name of\n" -" TEST(Foo, Bar) is \"Foo.Bar\".\n" -" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" - "[@G-@YNEGATIVE_PATTERNS]@D\n" -" Run only the tests whose name matches one of the positive patterns but\n" -" none of the negative patterns. '?' matches any single character; '*'\n" -" matches any substring; ':' separates two patterns.\n" -" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" -" Run all disabled tests too.\n" -"\n" -"Test Execution:\n" -" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" -" Run the tests repeatedly; use a negative count to repeat forever.\n" -" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" -" Randomize tests' orders on every iteration.\n" -" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" -" Random number seed to use for shuffling test orders (between 1 and\n" -" 99999, or 0 to use a seed based on the current time).\n" -"\n" -"Test Output:\n" -" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" -" Enable/disable colored output. The default is @Gauto@D.\n" -" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" -" Don't print the elapsed time of each test.\n" -" @G--" GTEST_FLAG_PREFIX_ "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" - GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" -" Generate a JSON or XML report in the given directory or with the given\n" -" file name. @YFILE_PATH@D defaults to @Gtest_detail.xml@D.\n" -# if GTEST_CAN_STREAM_RESULTS_ -" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" -" Stream test results to the given server.\n" -# endif // GTEST_CAN_STREAM_RESULTS_ -"\n" -"Assertion Behavior:\n" -# if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS -" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" -" Set the default death test style.\n" -# endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS -" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" -" Turn assertion failures into debugger break-points.\n" -" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" -" Turn assertion failures into C++ exceptions for use by an external\n" -" test framework.\n" -" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" -" Do not report exceptions as test failures. Instead, allow them\n" -" to crash the program or throw a pop-up (on Windows).\n" -"\n" -"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " - "the corresponding\n" -"environment variable of a flag (all letters in upper-case). For example, to\n" -"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ - "color=no@D or set\n" -"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" -"\n" -"For more information, please read the " GTEST_NAME_ " documentation at\n" -"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" -"(not one in your own code or tests), please report it to\n" -"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; - -static bool ParseGoogleTestFlag(const char* const arg) { - return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, - >EST_FLAG(also_run_disabled_tests)) || - ParseBoolFlag(arg, kBreakOnFailureFlag, - >EST_FLAG(break_on_failure)) || - ParseBoolFlag(arg, kCatchExceptionsFlag, - >EST_FLAG(catch_exceptions)) || - ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || - ParseStringFlag(arg, kDeathTestStyleFlag, - >EST_FLAG(death_test_style)) || - ParseBoolFlag(arg, kDeathTestUseFork, - >EST_FLAG(death_test_use_fork)) || - ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || - ParseStringFlag(arg, kInternalRunDeathTestFlag, - >EST_FLAG(internal_run_death_test)) || - ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || - ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || - ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || - ParseBoolFlag(arg, kPrintUTF8Flag, >EST_FLAG(print_utf8)) || - ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || - ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || - ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || - ParseInt32Flag(arg, kStackTraceDepthFlag, - >EST_FLAG(stack_trace_depth)) || - ParseStringFlag(arg, kStreamResultToFlag, - >EST_FLAG(stream_result_to)) || - ParseBoolFlag(arg, kThrowOnFailureFlag, - >EST_FLAG(throw_on_failure)); -} - -#if GTEST_USE_OWN_FLAGFILE_FLAG_ -static void LoadFlagsFromFile(const std::string& path) { - FILE* flagfile = posix::FOpen(path.c_str(), "r"); - if (!flagfile) { - GTEST_LOG_(FATAL) << "Unable to open file \"" << GTEST_FLAG(flagfile) - << "\""; - } - std::string contents(ReadEntireFile(flagfile)); - posix::FClose(flagfile); - std::vector lines; - SplitString(contents, '\n', &lines); - for (size_t i = 0; i < lines.size(); ++i) { - if (lines[i].empty()) - continue; - if (!ParseGoogleTestFlag(lines[i].c_str())) - g_help_flag = true; - } -} -#endif // GTEST_USE_OWN_FLAGFILE_FLAG_ - -// Parses the command line for Google Test flags, without initializing -// other parts of Google Test. The type parameter CharType can be -// instantiated to either char or wchar_t. -template -void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { - for (int i = 1; i < *argc; i++) { - const std::string arg_string = StreamableToString(argv[i]); - const char* const arg = arg_string.c_str(); - - using internal::ParseBoolFlag; - using internal::ParseInt32Flag; - using internal::ParseStringFlag; - - bool remove_flag = false; - if (ParseGoogleTestFlag(arg)) { - remove_flag = true; -#if GTEST_USE_OWN_FLAGFILE_FLAG_ - } else if (ParseStringFlag(arg, kFlagfileFlag, >EST_FLAG(flagfile))) { - LoadFlagsFromFile(GTEST_FLAG(flagfile)); - remove_flag = true; -#endif // GTEST_USE_OWN_FLAGFILE_FLAG_ - } else if (arg_string == "--help" || arg_string == "-h" || - arg_string == "-?" || arg_string == "/?" || - HasGoogleTestFlagPrefix(arg)) { - // Both help flag and unrecognized Google Test flags (excluding - // internal ones) trigger help display. - g_help_flag = true; - } - - if (remove_flag) { - // Shift the remainder of the argv list left by one. Note - // that argv has (*argc + 1) elements, the last one always being - // NULL. The following loop moves the trailing NULL element as - // well. - for (int j = i; j != *argc; j++) { - argv[j] = argv[j + 1]; - } - - // Decrements the argument count. - (*argc)--; - - // We also need to decrement the iterator as we just removed - // an element. - i--; - } - } - - if (g_help_flag) { - // We print the help here instead of in RUN_ALL_TESTS(), as the - // latter may not be called at all if the user is using Google - // Test with another testing framework. - PrintColorEncoded(kColorEncodedHelpMessage); - } -} - -// Parses the command line for Google Test flags, without initializing -// other parts of Google Test. -void ParseGoogleTestFlagsOnly(int* argc, char** argv) { - ParseGoogleTestFlagsOnlyImpl(argc, argv); - - // Fix the value of *_NSGetArgc() on macOS, but if and only if - // *_NSGetArgv() == argv - // Only applicable to char** version of argv -#if GTEST_OS_MAC -#ifndef GTEST_OS_IOS - if (*_NSGetArgv() == argv) { - *_NSGetArgc() = *argc; - } -#endif -#endif -} -void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { - ParseGoogleTestFlagsOnlyImpl(argc, argv); -} - -// The internal implementation of InitGoogleTest(). -// -// The type parameter CharType can be instantiated to either char or -// wchar_t. -template -void InitGoogleTestImpl(int* argc, CharType** argv) { - // We don't want to run the initialization code twice. - if (GTestIsInitialized()) return; - - if (*argc <= 0) return; - - g_argvs.clear(); - for (int i = 0; i != *argc; i++) { - g_argvs.push_back(StreamableToString(argv[i])); - } - -#if GTEST_HAS_ABSL - absl::InitializeSymbolizer(g_argvs[0].c_str()); -#endif // GTEST_HAS_ABSL - - ParseGoogleTestFlagsOnly(argc, argv); - GetUnitTestImpl()->PostFlagParsingInit(); -} - -} // namespace internal - -// Initializes Google Test. This must be called before calling -// RUN_ALL_TESTS(). In particular, it parses a command line for the -// flags that Google Test recognizes. Whenever a Google Test flag is -// seen, it is removed from argv, and *argc is decremented. -// -// No value is returned. Instead, the Google Test flag variables are -// updated. -// -// Calling the function for the second time has no user-visible effect. -void InitGoogleTest(int* argc, char** argv) { -#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) - GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv); -#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) - internal::InitGoogleTestImpl(argc, argv); -#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) -} - -// This overloaded version can be used in Windows programs compiled in -// UNICODE mode. -void InitGoogleTest(int* argc, wchar_t** argv) { -#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) - GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv); -#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) - internal::InitGoogleTestImpl(argc, argv); -#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) -} - -// This overloaded version can be used on Arduino/embedded platforms where -// there is no argc/argv. -void InitGoogleTest() { - // Since Arduino doesn't have a command line, fake out the argc/argv arguments - int argc = 1; - const auto arg0 = "dummy"; - char* argv0 = const_cast(arg0); - char** argv = &argv0; - -#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) - GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(&argc, argv); -#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) - internal::InitGoogleTestImpl(&argc, argv); -#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) -} - -std::string TempDir() { -#if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_) - return GTEST_CUSTOM_TEMPDIR_FUNCTION_(); -#endif - -#if GTEST_OS_WINDOWS_MOBILE - return "\\temp\\"; -#elif GTEST_OS_WINDOWS - const char* temp_dir = internal::posix::GetEnv("TEMP"); - if (temp_dir == nullptr || temp_dir[0] == '\0') - return "\\temp\\"; - else if (temp_dir[strlen(temp_dir) - 1] == '\\') - return temp_dir; - else - return std::string(temp_dir) + "\\"; -#elif GTEST_OS_LINUX_ANDROID - return "/sdcard/"; -#else - return "/tmp/"; -#endif // GTEST_OS_WINDOWS_MOBILE -} - -// Class ScopedTrace - -// Pushes the given source file location and message onto a per-thread -// trace stack maintained by Google Test. -void ScopedTrace::PushTrace(const char* file, int line, std::string message) { - internal::TraceInfo trace; - trace.file = file; - trace.line = line; - trace.message.swap(message); - - UnitTest::GetInstance()->PushGTestTrace(trace); -} - -// Pops the info pushed by the c'tor. -ScopedTrace::~ScopedTrace() - GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { - UnitTest::GetInstance()->PopGTestTrace(); -} - -} // namespace testing diff --git a/Sofa/framework/Testing/extlibs/gtest/src/gtest_main.cc b/Sofa/framework/Testing/extlibs/gtest/src/gtest_main.cc deleted file mode 100644 index f6e1dd96fb3..00000000000 --- a/Sofa/framework/Testing/extlibs/gtest/src/gtest_main.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2006, Google Inc. -// 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 Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER 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. - -#include -#include "gtest/gtest.h" - -#ifdef ARDUINO -void setup() { - testing::InitGoogleTest(); -} - -void loop() { RUN_ALL_TESTS(); } - -#else - -GTEST_API_ int main(int argc, char **argv) { - printf("Running main() from %s\n", __FILE__); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} -#endif diff --git a/Sofa/framework/Testing/test/TestMessageHandler_test.cpp b/Sofa/framework/Testing/test/TestMessageHandler_test.cpp index fe0180acc47..f38b507f33f 100644 --- a/Sofa/framework/Testing/test/TestMessageHandler_test.cpp +++ b/Sofa/framework/Testing/test/TestMessageHandler_test.cpp @@ -79,7 +79,9 @@ class GTEST_API_ AnyFailureChecker { const TestPartResult::Type type_; const std::string substr_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(AnyFailureChecker); + AnyFailureChecker(const AnyFailureChecker&) = delete; + AnyFailureChecker& operator=(const AnyFailureChecker&) = + delete; }; diff --git a/applications/collections/deprecated/modules/SofaMiscCollision/SofaMiscCollision_test/DefaultCollisionGroupManager_test.cpp b/applications/collections/deprecated/modules/SofaMiscCollision/SofaMiscCollision_test/DefaultCollisionGroupManager_test.cpp index 8c5514b3658..8df65f4ce69 100644 --- a/applications/collections/deprecated/modules/SofaMiscCollision/SofaMiscCollision_test/DefaultCollisionGroupManager_test.cpp +++ b/applications/collections/deprecated/modules/SofaMiscCollision/SofaMiscCollision_test/DefaultCollisionGroupManager_test.cpp @@ -58,15 +58,15 @@ void DefaultCollisionGroupManager_test::onSetUp() + "/DefaultCollisionGroupManager_singleObject_test.scn"; // Init simulation - sofa::simulation::setSimulation(simulation = new sofa::simulation::graph::DAGSimulation()); - root = sofa::simulation::getSimulation()->load(sceneFilename.c_str()); + simulation = sofa::simulation::getSimulation(); + root = sofa::simulation::node::load(sceneFilename.c_str()); } void DefaultCollisionGroupManager_test::onTearDown() { if (root != nullptr) { - sofa::simulation::getSimulation()->unload(root); + sofa::simulation::node::unload(root); } } @@ -75,7 +75,7 @@ bool DefaultCollisionGroupManager_test::combineSingleObject() EXPECT_TRUE(root != nullptr); EXPECT_TRUE(sofa::simulation::getSimulation() != nullptr); - sofa::simulation::getSimulation()->init(root.get()); + sofa::simulation::node::initRoot(root.get()); // run 200 time steps // objectives: @@ -83,7 +83,7 @@ bool DefaultCollisionGroupManager_test::combineSingleObject() // 2) Collision prevents the cube to fall through the floor for (unsigned int i = 0; i < 200; ++i) { - sofa::simulation::getSimulation()->animate(root.get(), 0.01); + sofa::simulation::node::animate(root.get(), 0.01); } auto* baseObject = root->getTreeNode("Cube1")->getObject("mechanicalObject"); diff --git a/applications/collections/deprecated/modules/SofaValidation/SofaValidation_test/Monitor_test.cpp b/applications/collections/deprecated/modules/SofaValidation/SofaValidation_test/Monitor_test.cpp index 4f71d377d38..5c6024decd5 100644 --- a/applications/collections/deprecated/modules/SofaValidation/SofaValidation_test/Monitor_test.cpp +++ b/applications/collections/deprecated/modules/SofaValidation/SofaValidation_test/Monitor_test.cpp @@ -147,7 +147,7 @@ struct Monitor_test : public BaseSimulationTest // make a few steps before checkinf if values are correctly updated in // Monitor for (int i = 0; i < 10; ++i) - simulation::getSimulation()->animate(root.get(), 1.0); + simulation::node::animate(root.get(), 1.0); monitor->testModif(mo.get()); diff --git a/applications/plugins/BeamAdapter/ExternalProjectConfig.cmake.in b/applications/plugins/BeamAdapter/ExternalProjectConfig.cmake.in index 5aa30f64ba1..88d1964e2a6 100644 --- a/applications/plugins/BeamAdapter/ExternalProjectConfig.cmake.in +++ b/applications/plugins/BeamAdapter/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(BeamAdapter GIT_REPOSITORY https://github.com/sofa-framework/BeamAdapter - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/BeamAdapter" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/CGALPlugin/ExternalProjectConfig.cmake.in b/applications/plugins/CGALPlugin/ExternalProjectConfig.cmake.in index c87a29bb1af..9c2696cbf87 100644 --- a/applications/plugins/CGALPlugin/ExternalProjectConfig.cmake.in +++ b/applications/plugins/CGALPlugin/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(CGALPlugin GIT_REPOSITORY https://github.com/sofa-framework/CGALPlugin - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/CGALPlugin" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/CMakeLists.txt b/applications/plugins/CMakeLists.txt index ba0a49e6d0f..7afdc76e6f1 100644 --- a/applications/plugins/CMakeLists.txt +++ b/applications/plugins/CMakeLists.txt @@ -9,7 +9,7 @@ endif() sofa_add_subdirectory(plugin CollisionOBBCapsule CollisionOBBCapsule) -sofa_add_subdirectory(directory SofaHighOrder SofaHighOrder EXTERNAL) +sofa_add_subdirectory(directory SofaHighOrder SofaHighOrder EXTERNAL GIT_REF v23.12) sofa_add_subdirectory(plugin CImgPlugin CImgPlugin) # ON by default and first as it is used by other plugins. sofa_add_subdirectory(plugin ArticulatedSystemPlugin ArticulatedSystemPlugin ON) @@ -22,15 +22,15 @@ sofa_add_subdirectory(plugin DiffusionSolver DiffusionSolver) # Depends on CImgP sofa_add_subdirectory(plugin image image) # Depends on CImgPlugin, DiffusionSolver, MultiThreading (soft) sofa_add_subdirectory(plugin SofaNewmat SofaNewmat) -sofa_add_subdirectory(directory SofaPython3 SofaPython3 EXTERNAL) -sofa_add_subdirectory(plugin CGALPlugin CGALPlugin EXTERNAL) # Depends on image -sofa_add_subdirectory(plugin Registration Registration EXTERNAL) # Depends on image, SofaPython, SofaGui and SofaDistanceGrid +sofa_add_subdirectory(directory SofaPython3 SofaPython3 EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin CGALPlugin CGALPlugin EXTERNAL GIT_REF v23.12) # Depends on image +sofa_add_subdirectory(plugin Registration Registration EXTERNAL GIT_REF v23.12) # Depends on image, SofaPython, SofaGui and SofaDistanceGrid sofa_add_subdirectory(plugin BulletCollisionDetection BulletCollisionDetection) # Depends on Compliant and LMConstraint sofa_add_subdirectory(plugin ExternalBehaviorModel ExternalBehaviorModel OFF WHEN_TO_SHOW "SOFA_ENABLE_LEGACY_HEADERS" VALUE_IF_HIDDEN OFF) -sofa_add_subdirectory(plugin InvertibleFVM InvertibleFVM EXTERNAL) +sofa_add_subdirectory(plugin InvertibleFVM InvertibleFVM EXTERNAL GIT_REF v23.12) sofa_add_subdirectory(plugin MeshSTEPLoader MeshSTEPLoader) -sofa_add_subdirectory(plugin PluginExample PluginExample EXTERNAL) -sofa_add_subdirectory(plugin ManifoldTopologies ManifoldTopologies EXTERNAL) +sofa_add_subdirectory(plugin PluginExample PluginExample EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin ManifoldTopologies ManifoldTopologies EXTERNAL GIT_REF v23.12) sofa_add_subdirectory(plugin SixenseHydra SixenseHydra) sofa_add_subdirectory(plugin SofaOpenCL SofaOpenCL) sofa_add_subdirectory(plugin Xitact Xitact) @@ -45,16 +45,16 @@ sofa_add_subdirectory(plugin LeapMotion LeapMotion) sofa_add_subdirectory(plugin Geomagic Geomagic) sofa_add_subdirectory(plugin SofaAssimp SofaAssimp) # ColladaSceneLoader Depends on Flexible and image sofa_add_subdirectory(plugin SofaMatrix SofaMatrix ON) # Depends on image, CImgPlugin -sofa_add_subdirectory(plugin BeamAdapter BeamAdapter EXTERNAL) -sofa_add_subdirectory(plugin STLIB STLIB EXTERNAL) -sofa_add_subdirectory(plugin SoftRobots SoftRobots EXTERNAL) -sofa_add_subdirectory(plugin CollisionAlgorithm CollisionAlgorithm EXTERNAL) -sofa_add_subdirectory(plugin ConstraintGeometry ConstraintGeometry EXTERNAL) -sofa_add_subdirectory(plugin ShapeMatchingPlugin ShapeMatchingPlugin EXTERNAL) -sofa_add_subdirectory(plugin CSparseSolvers CSparseSolvers EXTERNAL) +sofa_add_subdirectory(plugin BeamAdapter BeamAdapter EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin STLIB STLIB EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin SoftRobots SoftRobots EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin CollisionAlgorithm CollisionAlgorithm EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin ConstraintGeometry ConstraintGeometry EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin ShapeMatchingPlugin ShapeMatchingPlugin EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(plugin CSparseSolvers CSparseSolvers EXTERNAL GIT_REF v23.12) -sofa_add_subdirectory(plugin PSL PSL EXTERNAL) +sofa_add_subdirectory(plugin PSL PSL EXTERNAL GIT_REF v23.12) if((${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") AND (${CMAKE_SYSTEM_NAME} MATCHES "Linux")) sofa_add_subdirectory(plugin SofaPardisoSolver SofaPardisoSolver) # SofaPardisoSolver is only available under linux with gcc diff --git a/applications/plugins/CSparseSolvers/ExternalProjectConfig.cmake.in b/applications/plugins/CSparseSolvers/ExternalProjectConfig.cmake.in index 989dbe70379..bf0b64b9e25 100644 --- a/applications/plugins/CSparseSolvers/ExternalProjectConfig.cmake.in +++ b/applications/plugins/CSparseSolvers/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(CSparseSolvers GIT_REPOSITORY https://github.com/sofa-framework/CSparseSolvers - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/CSparseSolvers" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/CollisionAlgorithm/ExternalProjectConfig.cmake.in b/applications/plugins/CollisionAlgorithm/ExternalProjectConfig.cmake.in index 372f6dbf768..d3c343a415a 100644 --- a/applications/plugins/CollisionAlgorithm/ExternalProjectConfig.cmake.in +++ b/applications/plugins/CollisionAlgorithm/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(CollisionAlgorithm GIT_REPOSITORY https://github.com/courtecuisse/CollisionAlgorithm.git - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/CollisionAlgorithm" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/CollisionOBBCapsule/examples/benchmark_cubes.scn b/applications/plugins/CollisionOBBCapsule/examples/benchmark_cubes.scn index e3e29fe85d1..bf34abd651d 100644 --- a/applications/plugins/CollisionOBBCapsule/examples/benchmark_cubes.scn +++ b/applications/plugins/CollisionOBBCapsule/examples/benchmark_cubes.scn @@ -43,7 +43,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -59,7 +59,7 @@ - + @@ -67,7 +67,7 @@ - + @@ -75,7 +75,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -91,7 +91,7 @@ - + @@ -99,7 +99,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -115,7 +115,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -139,7 +139,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -171,7 +171,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -195,7 +195,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -227,7 +227,7 @@ - + @@ -235,7 +235,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -251,7 +251,7 @@ - + @@ -259,7 +259,7 @@ - + @@ -267,7 +267,7 @@ - + @@ -275,7 +275,7 @@ - + @@ -283,7 +283,7 @@ - + @@ -291,7 +291,7 @@ - + @@ -299,7 +299,7 @@ - + @@ -307,7 +307,7 @@ - + @@ -315,7 +315,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -331,7 +331,7 @@ - + @@ -339,7 +339,7 @@ - + @@ -347,7 +347,7 @@ - + @@ -355,7 +355,7 @@ - + @@ -363,7 +363,7 @@ - + @@ -371,7 +371,7 @@ - + @@ -379,7 +379,7 @@ - + @@ -387,7 +387,7 @@ - + @@ -395,7 +395,7 @@ - + @@ -403,7 +403,7 @@ - + @@ -411,7 +411,7 @@ - + @@ -419,7 +419,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -435,7 +435,7 @@ - + @@ -443,7 +443,7 @@ - + @@ -451,7 +451,7 @@ - + @@ -459,7 +459,7 @@ - + @@ -467,7 +467,7 @@ - + @@ -475,7 +475,7 @@ - + @@ -483,7 +483,7 @@ - + @@ -491,7 +491,7 @@ - + @@ -499,7 +499,7 @@ - + @@ -507,7 +507,7 @@ - + @@ -515,7 +515,7 @@ - + @@ -523,7 +523,7 @@ - + @@ -531,7 +531,7 @@ - + @@ -539,7 +539,7 @@ - + @@ -547,7 +547,7 @@ - + @@ -555,7 +555,7 @@ - + @@ -563,7 +563,7 @@ - + @@ -571,7 +571,7 @@ - + @@ -579,7 +579,7 @@ - + @@ -587,7 +587,7 @@ - + @@ -595,7 +595,7 @@ - + @@ -603,7 +603,7 @@ - + @@ -611,7 +611,7 @@ - + diff --git a/applications/plugins/ConstraintGeometry/ExternalProjectConfig.cmake.in b/applications/plugins/ConstraintGeometry/ExternalProjectConfig.cmake.in index 4c10f3667bf..b91fe26f047 100644 --- a/applications/plugins/ConstraintGeometry/ExternalProjectConfig.cmake.in +++ b/applications/plugins/ConstraintGeometry/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(ConstraintGeometry GIT_REPOSITORY https://github.com/courtecuisse/ConstraintGeometry.git - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/ConstraintGeometry" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/Haption/CMakeLists.txt b/applications/plugins/Haption/CMakeLists.txt index 21648d5ee44..a568175813b 100644 --- a/applications/plugins/Haption/CMakeLists.txt +++ b/applications/plugins/Haption/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required(VERSION 3.12) project(Haption) -find_package(SofaHaptics REQUIRED) -find_package(SofaOpenglVisual REQUIRED) +find_package(Sofa.Config REQUIRED) +sofa_find_package(Sofa.Component.Haptics REQUIRED) +sofa_find_package(Sofa.GL.Component.Rendering3D REQUIRED) +sofa_find_package(Sofa.Component.Mapping.NonLinear REQUIRED) +sofa_find_package(Sofa.Component.Controller REQUIRED) +sofa_find_package(Sofa.Component.StateContainer REQUIRED) set(HEADER_FILES HaptionDriver.h @@ -15,12 +19,19 @@ set(SOURCE_FILES ) set(README_FILES + README.md PluginHaption.txt ) -add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) +add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${README_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-DSOFA_BUILD_HAPTIONPLUGIN") -target_link_libraries(${PROJECT_NAME} SofaHaptics SofaOpenglVisual) +target_link_libraries(${PROJECT_NAME} + Sofa.Component.Haptics + Sofa.GL.Component.Rendering3D + Sofa.Component.Mapping.NonLinear + Sofa.Component.Controller + Sofa.Component.StateContainer +) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..") install(TARGETS ${PROJECT_NAME} diff --git a/applications/plugins/Haption/HaptionDriver.cpp b/applications/plugins/Haption/HaptionDriver.cpp index fba135a7e31..adfbf1be9f9 100644 --- a/applications/plugins/Haption/HaptionDriver.cpp +++ b/applications/plugins/Haption/HaptionDriver.cpp @@ -43,11 +43,11 @@ void HaptionDriver::haptic_callback(VirtContext, void *param) virtGetAvatarPosition(data->m_virtContext, position); SolidTypes::Transform sofaWorld_H_Tool( - Vec3d(data->scale*position[0],data->scale*position[1],data->scale*position[2]), - Quat(position[3],position[4],position[5],position[6])); + type::Vec3d(data->scale*position[0],data->scale*position[1],data->scale*position[2]), + type::Quat(position[3],position[4],position[5],position[6])); - SolidTypes::SpatialVector Twist_tool_inWorld(Vec3d(0.0,0.0,0.0), Vec3d(0.0,0.0,0.0)); - SolidTypes::SpatialVector Wrench_tool_inWorld(Vec3d(0.0,0.0,0.0), Vec3d(0.0,0.0,0.0)); + SolidTypes::SpatialVector Twist_tool_inWorld(type::Vec3d(0.0,0.0,0.0), type::Vec3d(0.0,0.0,0.0)); + SolidTypes::SpatialVector Wrench_tool_inWorld(type::Vec3d(0.0,0.0,0.0), type::Vec3d(0.0,0.0,0.0)); if(data->forceFeedback != NULL) { @@ -169,7 +169,7 @@ void HaptionDriver::init() visuActif=true; } - visualHaptionDOF = new sofa::component::container::MechanicalObject(); + visualHaptionDOF = new sofa::component::statecontainer::MechanicalObject(); nodeHaptionVisual->addObject(visualHaptionDOF); visualHaptionDOF->name.setValue("rigidDOF"); @@ -186,7 +186,7 @@ void HaptionDriver::init() //context->addChild(nodeAxesVisual); //nodeAxesVisual->updateContext(); - visualAxesDOF = new sofa::component::container::MechanicalObject(); + visualAxesDOF = new sofa::component::statecontainer::MechanicalObject(); nodeAxesVisual->addObject(visualAxesDOF); visualAxesDOF->name.setValue("rigidDOF"); @@ -212,7 +212,7 @@ void HaptionDriver::init() visualNode[i].mapping = NULL; if(visualNode[i].visu == NULL && visualNode[i].mapping == NULL) { - visualNode[i].visu = new sofa::component::visualmodel::OglModel(); + visualNode[i].visu = new sofa::gl::component::rendering3d::OglModel(); visualNode[i].node->addObject(visualNode[i].visu); visualNode[i].visu->name.setValue("VisualParticles"); if(i==0) @@ -238,9 +238,9 @@ void HaptionDriver::init() visualNode[i].visu->initVisual(); visualNode[i].visu->updateVisual(); if(i<2) - visualNode[i].mapping = new sofa::component::mapping::RigidMapping< Rigid3dTypes, Vec3fTypes >(visualHaptionDOF,visualNode[i].visu); + visualNode[i].mapping = new sofa::component::mapping::nonlinear::RigidMapping< Rigid3dTypes, Vec3fTypes >(visualHaptionDOF,visualNode[i].visu); else - visualNode[i].mapping = new sofa::component::mapping::RigidMapping< Rigid3dTypes, Vec3fTypes >(visualAxesDOF,visualNode[i].visu); + visualNode[i].mapping = new sofa::component::mapping::nonlinear::RigidMapping< Rigid3dTypes, Vec3fTypes >(visualAxesDOF,visualNode[i].visu); visualNode[i].node->addObject(visualNode[i].mapping); visualNode[i].mapping->name.setValue("RigidMapping"); visualNode[i].mapping->f_mapConstraints.setValue(false); @@ -294,7 +294,7 @@ void HaptionDriver::bwdInit() simulation::Node *context = dynamic_cast(this->getContext()); - rigidDOF = context->get > (); + rigidDOF = context->get > (); if (rigidDOF==NULL) @@ -303,7 +303,7 @@ void HaptionDriver::bwdInit() } //search force feedback - MechanicalStateForceFeedback* ff = context->getTreeObject>(); + haptics::MechanicalStateForceFeedback* ff = context->getTreeObject>(); if(ff) { @@ -312,7 +312,7 @@ void HaptionDriver::bwdInit() } } -void HaptionDriver::setForceFeedback(MechanicalStateForceFeedback* ff) +void HaptionDriver::setForceFeedback(haptics::MechanicalStateForceFeedback* ff) { if(myData.forceFeedback == ff) { @@ -451,7 +451,7 @@ void HaptionDriver::onKeyPressedEvent(core::objectmodel::KeypressedEvent *kpe) if(modX || modY || modZ) { VecCoord& posB =(*posBase.beginEdit()); - posB[0].getCenter()+=posB[0].getOrientation().rotate(Vec3d(-(int)modX,-(int)modY,-(int)modZ)); + posB[0].getCenter()+=posB[0].getOrientation().rotate(type::Vec3d(-(int)modX,-(int)modY,-(int)modZ)); posBase.endEdit(); } else @@ -466,7 +466,7 @@ void HaptionDriver::onKeyPressedEvent(core::objectmodel::KeypressedEvent *kpe) if(modX || modY || modZ) { VecCoord& posB =(*posBase.beginEdit()); - posB[0].getCenter()+=posB[0].getOrientation().rotate(Vec3d((int)modX,(int)modY,(int)modZ)); + posB[0].getCenter()+=posB[0].getOrientation().rotate(type::Vec3d((int)modX,(int)modY,(int)modZ)); posBase.endEdit(); } else @@ -478,14 +478,14 @@ void HaptionDriver::onKeyPressedEvent(core::objectmodel::KeypressedEvent *kpe) else if ((kpe->getKey()==21) && (modX || modY || modZ)) //down { VecCoord& posB =(*posBase.beginEdit()); - sofa::type::Quat quarter_transform(Vec3d((int)modX,(int)modY,(int)modZ),-M_PI/50); + sofa::type::Quat quarter_transform(type::Vec3d((int)modX,(int)modY,(int)modZ),-M_PI/50); posB[0].getOrientation()*=quarter_transform; posBase.endEdit(); } else if ((kpe->getKey()==19) && (modX || modY || modZ)) //up { VecCoord& posB =(*posBase.beginEdit()); - sofa::type::Quat quarter_transform(Vec3d((int)modX,(int)modY,(int)modZ),+M_PI/50); + sofa::type::Quat quarter_transform(type::Vec3d((int)modX,(int)modY,(int)modZ),+M_PI/50); posB[0].getOrientation()*=quarter_transform; posBase.endEdit(); } @@ -558,8 +558,8 @@ void HaptionDriver::onAnimateBeginEvent() virtGetAvatarPosition(myData.m_virtContext, position); VecCoord& posR = (*rigidDOF->x0.beginEdit()); - posR[0].getCenter() = Vec3d(scale.getValue()*position[0],scale.getValue()*position[1],scale.getValue()*position[2]); - posR[0].getOrientation() = Quat(position[3],position[4],position[5],position[6]); + posR[0].getCenter() = type::Vec3d(scale.getValue()*position[0],scale.getValue()*position[1],scale.getValue()*position[2]); + posR[0].getOrientation() = type::Quat(position[3],position[4],position[5],position[6]); rigidDOF->x0.endEdit(); //button_state @@ -571,8 +571,8 @@ void HaptionDriver::onAnimateBeginEvent() if(visuActif) { VecCoord& posH = (*visualHaptionDOF->x.beginEdit()); - posH[1].getCenter() = Vec3d(scale.getValue()*position[0],scale.getValue()*position[1],scale.getValue()*position[2]); - posH[1].getOrientation() = Quat(position[3],position[4],position[5],position[6]); + posH[1].getCenter() = type::Vec3d(scale.getValue()*position[0],scale.getValue()*position[1],scale.getValue()*position[2]); + posH[1].getOrientation() = type::Quat(position[3],position[4],position[5],position[6]); visualHaptionDOF->x.endEdit(); } diff --git a/applications/plugins/Haption/HaptionDriver.h b/applications/plugins/Haption/HaptionDriver.h index 484a7d78b11..16586a777bf 100644 --- a/applications/plugins/Haption/HaptionDriver.h +++ b/applications/plugins/Haption/HaptionDriver.h @@ -29,15 +29,15 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include -#include +#include #include -#include -#include +#include +#include #include #include #include @@ -66,14 +66,14 @@ using core::objectmodel::Data; typedef struct { simulation::Node *node; - sofa::component::visualmodel::OglModel *visu; - sofa::component::mapping::RigidMapping< Rigid3dTypes , Vec3fTypes > *mapping; + sofa::gl::component::rendering3d::OglModel *visu; + sofa::component::mapping::nonlinear::RigidMapping< Rigid3dTypes , Vec3fTypes > *mapping; } VisualComponent; typedef struct { VirtContext m_virtContext; - MechanicalStateForceFeedback* forceFeedback; + haptics::MechanicalStateForceFeedback* forceFeedback; float scale; float torqueScale; float forceScale; @@ -98,19 +98,19 @@ class HaptionDriver : public Controller HaptionDriver(); virtual ~HaptionDriver(); - virtual void init(); - virtual void reinit(); - virtual void bwdInit(); - virtual void reset(); - virtual void handleEvent(core::objectmodel::Event *); - void onKeyPressedEvent(core::objectmodel::KeypressedEvent *); - void onKeyReleasedEvent(core::objectmodel::KeyreleasedEvent *); + void init() override; + void reinit() override; + void bwdInit() override; + void reset() override; + void handleEvent(core::objectmodel::Event *) override; + void onKeyPressedEvent(core::objectmodel::KeypressedEvent *) override; + void onKeyReleasedEvent(core::objectmodel::KeyreleasedEvent *) override; void onAnimateBeginEvent(); int initDevice(char* ip); void closeDevice(); static void haptic_callback(VirtContext, void *); - void setForceFeedback(MechanicalStateForceFeedback* ff); + void setForceFeedback(haptics::MechanicalStateForceFeedback* ff); private: @@ -121,12 +121,12 @@ class HaptionDriver : public Controller float m_forceFactor; float haptic_time_step; int connection_device; - sofa::component::container::MechanicalObject *rigidDOF; + sofa::component::statecontainer::MechanicalObject *rigidDOF; bool initCallback; simulation::Node *nodeHaptionVisual; - sofa::component::container::MechanicalObject *visualHaptionDOF; + sofa::component::statecontainer::MechanicalObject *visualHaptionDOF; simulation::Node *nodeAxesVisual; - sofa::component::container::MechanicalObject *visualAxesDOF; + sofa::component::statecontainer::MechanicalObject *visualAxesDOF; VisualComponent visualNode[5]; float oldScale; diff --git a/applications/plugins/Haption/README.md b/applications/plugins/Haption/README.md new file mode 100644 index 00000000000..d1184a4e3fd --- /dev/null +++ b/applications/plugins/Haption/README.md @@ -0,0 +1,7 @@ +# Haption + +SOFA plugin allowing the use a Haption's haptic device in a SOFA simulation. + +## Requirements + +The plugin relies on the [Virtuose API](https://www.haption.com/en/software-en/virtuose-en.html), which is not provided with the plugin. diff --git a/applications/plugins/InvertibleFVM/ExternalProjectConfig.cmake.in b/applications/plugins/InvertibleFVM/ExternalProjectConfig.cmake.in index e3a5812dc20..e5e17538b36 100644 --- a/applications/plugins/InvertibleFVM/ExternalProjectConfig.cmake.in +++ b/applications/plugins/InvertibleFVM/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.2) include(ExternalProject) ExternalProject_Add(InvertibleFVM GIT_REPOSITORY https://github.com/sofa-framework/InvertibleFVM - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/InvertibleFVM" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/ManifoldTopologies/ExternalProjectConfig.cmake.in b/applications/plugins/ManifoldTopologies/ExternalProjectConfig.cmake.in index 94d5f942f6f..8146ab01c2c 100644 --- a/applications/plugins/ManifoldTopologies/ExternalProjectConfig.cmake.in +++ b/applications/plugins/ManifoldTopologies/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(ManifoldTopologies GIT_REPOSITORY https://github.com/sofa-framework/ManifoldTopologies - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/ManifoldTopologies" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/MultiThreading/src/MultiThreading/TaskSchedulerUser.cpp b/applications/plugins/MultiThreading/src/MultiThreading/TaskSchedulerUser.cpp index c005b5ee945..a60da64108f 100644 --- a/applications/plugins/MultiThreading/src/MultiThreading/TaskSchedulerUser.cpp +++ b/applications/plugins/MultiThreading/src/MultiThreading/TaskSchedulerUser.cpp @@ -65,7 +65,7 @@ void TaskSchedulerUser::reinitTaskScheduler() if (m_taskScheduler) { const auto nbThreads = d_nbThreads.getValue(); - if ( nbThreads != m_taskScheduler->getThreadCount() ) + if ( nbThreads != static_cast(m_taskScheduler->getThreadCount()) ) { m_taskScheduler->init(nbThreads); sofa::simulation::initThreadLocalData(); diff --git a/applications/plugins/MultiThreading/src/MultiThreading/component/linearsolver/iterative/ParallelCompressedRowSparseMatrixMechanical.h b/applications/plugins/MultiThreading/src/MultiThreading/component/linearsolver/iterative/ParallelCompressedRowSparseMatrixMechanical.h index 2f12e06811d..c246aae0a7c 100644 --- a/applications/plugins/MultiThreading/src/MultiThreading/component/linearsolver/iterative/ParallelCompressedRowSparseMatrixMechanical.h +++ b/applications/plugins/MultiThreading/src/MultiThreading/component/linearsolver/iterative/ParallelCompressedRowSparseMatrixMechanical.h @@ -125,7 +125,7 @@ class ParallelCompressedRowSparseMatrixMechanical : public sofa::linearalgebra:: // transfer a chunk of large vector to a local block-sized vector sofa::type::Vec v; //Index jN = colsIndex[xj] * NC; // scalar column index - for (Index bj = 0; bj < NC; ++bj) + for (sofa::Index bj = 0; bj < NC; ++bj) { v[bj] = vget(vec, m_crs.colsIndex[xj], NC, bj); } @@ -133,9 +133,9 @@ class ParallelCompressedRowSparseMatrixMechanical : public sofa::linearalgebra:: // multiply the block with the local vector const typename Base::Block& b = m_crs.colsValue[xj]; // non-null block has block-indices (rowIndex[xi],colsIndex[xj]) and value colsValue[xj] - for (Index bi = 0; bi < NL; ++bi) + for (sofa::Index bi = 0; bi < NL; ++bi) { - for (Index bj = 0; bj < NC; ++bj) + for (sofa::Index bj = 0; bj < NC; ++bj) { r[bi] += Base::traits::v(b, bi, bj) * v[bj]; } @@ -144,7 +144,7 @@ class ParallelCompressedRowSparseMatrixMechanical : public sofa::linearalgebra:: // transfer the local result to the large result vector //Index iN = rowIndex[xi] * NL; // scalar row index - for (Index bi = 0; bi < NL; ++bi) + for (sofa::Index bi = 0; bi < NL; ++bi) { vset(res, m_crs.rowIndex[xi], NL, bi, r[bi]); } diff --git a/applications/plugins/PSL/ExternalProjectConfig.cmake.in b/applications/plugins/PSL/ExternalProjectConfig.cmake.in index f63a0e8a7a2..1ec08590cee 100644 --- a/applications/plugins/PSL/ExternalProjectConfig.cmake.in +++ b/applications/plugins/PSL/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(PSL GIT_REPOSITORY https://github.com/sofa-framework/PSL - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/PSL" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/PluginExample/ExternalProjectConfig.cmake.in b/applications/plugins/PluginExample/ExternalProjectConfig.cmake.in index d0a67e5b63c..21e5d458439 100644 --- a/applications/plugins/PluginExample/ExternalProjectConfig.cmake.in +++ b/applications/plugins/PluginExample/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(PluginExample GIT_REPOSITORY https://github.com/sofa-framework/PluginExample - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/PluginExample" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/Registration/ExternalProjectConfig.cmake.in b/applications/plugins/Registration/ExternalProjectConfig.cmake.in index 549b35faee0..768f1708ae2 100644 --- a/applications/plugins/Registration/ExternalProjectConfig.cmake.in +++ b/applications/plugins/Registration/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(Registration GIT_REPOSITORY https://github.com/sofa-framework/Registration - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/Registration" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/RegressionStateScenes.regression-tests b/applications/plugins/RegressionStateScenes.regression-tests index f89599f5330..fe2d67684b1 100644 --- a/applications/plugins/RegressionStateScenes.regression-tests +++ b/applications/plugins/RegressionStateScenes.regression-tests @@ -2,6 +2,9 @@ # REGRESSION_TEST DOES NOT SUPPORT DASHES ("-") IN SCENE NAMES. # USE UNDERSCORES ("_") INSTEAD. +### References relative path ### +../projects/Regression/references/applications/plugins + ### Sph Plugin ### SofaSphFluid/examples/SPHFluidForceField.scn 100 1e-4 1 1 SofaSphFluid/examples/SPHFluidForceField_benchmarks.scn 100 1e-4 1 1 diff --git a/applications/plugins/STLIB/ExternalProjectConfig.cmake.in b/applications/plugins/STLIB/ExternalProjectConfig.cmake.in index 4a31917ad70..dbf37a68576 100644 --- a/applications/plugins/STLIB/ExternalProjectConfig.cmake.in +++ b/applications/plugins/STLIB/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(STLIB GIT_REPOSITORY https://github.com/SofaDefrost/STLIB - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/STLIB" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/SensableEmulation/examples/SimpleBox-Method2.scn b/applications/plugins/SensableEmulation/examples/SimpleBox-Method2.scn index f1ad8c485b3..becbb2480b0 100644 --- a/applications/plugins/SensableEmulation/examples/SimpleBox-Method2.scn +++ b/applications/plugins/SensableEmulation/examples/SimpleBox-Method2.scn @@ -53,7 +53,7 @@ - + diff --git a/applications/plugins/ShapeMatchingPlugin/ExternalProjectConfig.cmake.in b/applications/plugins/ShapeMatchingPlugin/ExternalProjectConfig.cmake.in index 3fbe8291ebd..8a6b093ddf8 100644 --- a/applications/plugins/ShapeMatchingPlugin/ExternalProjectConfig.cmake.in +++ b/applications/plugins/ShapeMatchingPlugin/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(ShapeMatchingPlugin GIT_REPOSITORY https://github.com/sofa-framework/ShapeMatchingPlugin - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/ShapeMatchingPlugin" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/SofaAssimp/CMakeLists.txt b/applications/plugins/SofaAssimp/CMakeLists.txt index 9e83964d3a5..cb7165cd993 100644 --- a/applications/plugins/SofaAssimp/CMakeLists.txt +++ b/applications/plugins/SofaAssimp/CMakeLists.txt @@ -22,7 +22,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") ### Dependencies find_package(Sofa.Core REQUIRED) -sofa_find_package(Assimp REQUIRED) +sofa_find_package(assimp REQUIRED) sofa_find_package(Sofa.Component.Constraint.Projective REQUIRED) sofa_find_package(Sofa.Component.Mass REQUIRED) sofa_find_package(Sofa.Component.Mapping REQUIRED) @@ -35,7 +35,7 @@ sofa_find_package(Flexible QUIET) # Create the plugin library. add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${README_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-DSOFA_BUILD_SOFAASSIMP") -target_link_libraries(${PROJECT_NAME} PUBLIC ${ASSIMP_LIBRARY} Sofa.Core Sofa.Component.Constraint.Projective Sofa.Component.Mass Sofa.Component.Mapping Sofa.GL.Component.Rendering3D Sofa.Component.StateContainer Sofa.Component.Collision.Geometry) +target_link_libraries(${PROJECT_NAME} PUBLIC ${ASSIMP_LIBRARIES} Sofa.Core Sofa.Component.Constraint.Projective Sofa.Component.Mass Sofa.Component.Mapping Sofa.GL.Component.Rendering3D Sofa.Component.StateContainer Sofa.Component.Collision.Geometry) if(image_FOUND) target_link_libraries(${PROJECT_NAME} PUBLIC image) diff --git a/applications/plugins/SofaAssimp/cmake/FindAssimp.cmake b/applications/plugins/SofaAssimp/cmake/Findassimp.cmake similarity index 85% rename from applications/plugins/SofaAssimp/cmake/FindAssimp.cmake rename to applications/plugins/SofaAssimp/cmake/Findassimp.cmake index 93f1fdd0115..cc9075e745a 100644 --- a/applications/plugins/SofaAssimp/cmake/FindAssimp.cmake +++ b/applications/plugins/SofaAssimp/cmake/Findassimp.cmake @@ -1,136 +1,137 @@ -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ASSIMP_ARCHITECTURE "64") -elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(ASSIMP_ARCHITECTURE "32") -endif(CMAKE_SIZEOF_VOID_P EQUAL 8) - -# First try to find assimp in CONFIG mode on the system -find_package(Assimp NO_MODULE QUIET - PATHS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/cmake - ) - -# If not found, try to manually find it -if(NOT ASSIMP_INCLUDE_DIR OR NOT Assimp_FOUND) - if(CMAKE_SYSTEM_NAME STREQUAL Windows) - # Use ASSIMP_ROOT_DIR as user input for Assimp location - set(ASSIMP_ROOT_DIR CACHE PATH "Assimp root directory") - - find_path(ASSIMP_INCLUDE_DIR - NAMES assimp/postprocess.h - PATHS ${ASSIMP_ROOT_DIR}/include - DOC "The directory where assimp headers reside" - ) - - if(MSVC12) - set(ASSIMP_MSVC_VERSION "vc120") - elseif(MSVC14) - # First look for vc140 build and if not found try vc141 - find_path(ASSIMP_LIBRARY_DIR - NAMES assimp-vc140-mt.lib - HINTS - ${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE} - ${ASSIMP_ROOT_DIR}/lib - ${ASSIMP_ROOT_DIR}/lib/x64 - ) - - if(ASSIMP_LIBRARY_DIR) - set(ASSIMP_MSVC_VERSION "vc140") - else() - set(ASSIMP_MSVC_VERSION "vc141") - endif() - else() - set(ASSIMP_MSVC_VERSION "") - endif() - - if(NOT ASSIMP_LIBRARY_DIR) - find_path(ASSIMP_LIBRARY_DIR - NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib - HINTS - ${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE} - ${ASSIMP_ROOT_DIR}/lib - ${ASSIMP_ROOT_DIR}/lib/x64 - ) - endif() - - find_library(ASSIMP_LIBRARY_DEBUG - NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.lib - PATHS - ${ASSIMP_LIBRARY_DIR} - ${ASSIMP_ROOT_DIR}/lib - DOC "The assimp debug library" - ) - - find_library(ASSIMP_LIBRARY_RELEASE - NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib - PATHS - ${ASSIMP_LIBRARY_DIR} - ${ASSIMP_ROOT_DIR}/lib - DOC "The assimp release library" - ) - - find_path(ASSIMP_BIN_DIR - NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.dll - HINTS - ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE} - ${ASSIMP_ROOT_DIR}/bin - ${ASSIMP_ROOT_DIR}/bin/x64 - ) - - if(ASSIMP_LIBRARY_RELEASE AND ASSIMP_BIN_DIR) - if(ASSIMP_LIBRARY_DEBUG) - set(ASSIMP_LIBRARY - optimized ${ASSIMP_LIBRARY_RELEASE} - debug ${ASSIMP_LIBRARY_DEBUG} - ) - else() - set(ASSIMP_LIBRARY ${ASSIMP_LIBRARY_RELEASE}) - endif() - - set(ASSIMP_DLL ${ASSIMP_BIN_DIR}/assimp-${ASSIMP_MSVC_VERSION}-mt.dll) - set(Assimp_FOUND TRUE) - else() - set(Assimp_FOUND FALSE) - endif() - else() - find_path(ASSIMP_INCLUDE_DIR - NAMES assimp/postprocess.h assimp/scene.h assimp/version.h assimp/config.h assimp/cimport.h - PATHS - /usr/include - /usr/local/include - /sw/include - /opt/local/include - DOC "The directory where assimp headers reside" - ) - - find_library(ASSIMP_LIBRARY - NAMES assimp - PATHS - /usr/local/lib/ - /usr/lib64 - /usr/lib - /usr/local/lib64 - /usr/local/lib - /sw/lib - /opt/local/lib - DOC "The assimp library" - ) - - if(ASSIMP_INCLUDE_DIR AND ASSIMP_LIBRARY) - set(Assimp_FOUND TRUE) - endif() - endif() -endif() - -if(${CMAKE_FIND_PACKAGE_NAME}_FOUND) - if(NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) - message(STATUS "Assimp found. Library is ${ASSIMP_LIBRARY} and include dir is ${ASSIMP_INCLUDE_DIR}") - endif() -else() - if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) - set(error_message "Assimp not found.") - if(CMAKE_SYSTEM_NAME STREQUAL Windows AND NOT ASSIMP_ROOT_DIR) - set(error_message "${error_message} Please set ASSIMP_ROOT_DIR to locate Assimp.") - endif() - message(FATAL_ERROR "${error_message}") - endif() -endif() +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(ASSIMP_ARCHITECTURE "64") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(ASSIMP_ARCHITECTURE "32") +endif(CMAKE_SIZEOF_VOID_P EQUAL 8) + +# First try to find assimp in CONFIG mode on the system +find_package(assimp NO_MODULE QUIET) + + +# If not found, try to manually find it +if(NOT ASSIMP_INCLUDE_DIRS OR NOT assimp_FOUND) + if(CMAKE_SYSTEM_NAME STREQUAL Windows) + # Use ASSIMP_ROOT_DIR as user input for Assimp location + set(ASSIMP_ROOT_DIR CACHE PATH "Assimp root directory") + + find_path(ASSIMP_INCLUDE_DIRS + NAMES assimp/postprocess.h + PATHS ${ASSIMP_ROOT_DIR}/include + DOC "The directory where assimp headers reside" + ) + + if(MSVC12) + set(ASSIMP_MSVC_VERSION "vc120") + elseif(MSVC14) + # First look for vc140 build and if not found try vc141 + find_path(ASSIMP_LIBRARY_DIR + NAMES assimp-vc140-mt.lib + HINTS + ${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE} + ${ASSIMP_ROOT_DIR}/lib + ${ASSIMP_ROOT_DIR}/lib/x64 + ) + + if(ASSIMP_LIBRARY_DIR) + set(ASSIMP_MSVC_VERSION "vc140") + else() + set(ASSIMP_MSVC_VERSION "vc141") + endif() + elseif (MSVC17) + set(ASSIMP_MSVC_VERSION "vc143") + else() + set(ASSIMP_MSVC_VERSION "") + endif() + + if(NOT ASSIMP_LIBRARY_DIR) + find_path(ASSIMP_LIBRARY_DIR + NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib + HINTS + ${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE} + ${ASSIMP_ROOT_DIR}/lib + ${ASSIMP_ROOT_DIR}/lib/x64 + ) + endif() + + find_library(ASSIMP_LIBRARY_DEBUG + NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.lib + PATHS + ${ASSIMP_LIBRARY_DIR} + ${ASSIMP_ROOT_DIR}/lib + DOC "The assimp debug library" + ) + + find_library(ASSIMP_LIBRARY_RELEASE + NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib + PATHS + ${ASSIMP_LIBRARY_DIR} + ${ASSIMP_ROOT_DIR}/lib + DOC "The assimp release library" + ) + + find_path(ASSIMP_BIN_DIR + NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.dll + HINTS + ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE} + ${ASSIMP_ROOT_DIR}/bin + ${ASSIMP_ROOT_DIR}/bin/x64 + ) + + if(ASSIMP_LIBRARY_RELEASE AND ASSIMP_BIN_DIR) + if(ASSIMP_LIBRARY_DEBUG) + set(ASSIMP_LIBRARY + optimized ${ASSIMP_LIBRARY_RELEASE} + debug ${ASSIMP_LIBRARY_DEBUG} + ) + else() + set(ASSIMP_LIBRARY ${ASSIMP_LIBRARY_RELEASE}) + endif() + + set(ASSIMP_DLL ${ASSIMP_BIN_DIR}/assimp-${ASSIMP_MSVC_VERSION}-mt.dll) + set(assimp_FOUND TRUE) + else() + set(assimp_FOUND FALSE) + endif() + else() + find_path(ASSIMP_INCLUDE_DIRS + NAMES assimp/postprocess.h assimp/scene.h assimp/version.h assimp/config.h assimp/cimport.h + PATHS + /usr/include + /usr/local/include + /sw/include + /opt/local/include + DOC "The directory where assimp headers reside" + ) + + find_library(ASSIMP_LIBRARY + NAMES assimp + PATHS + /usr/local/lib/ + /usr/lib64 + /usr/lib + /usr/local/lib64 + /usr/local/lib + /sw/lib + /opt/local/lib + DOC "The assimp library" + ) + + if(ASSIMP_INCLUDE_DIRS AND ASSIMP_LIBRARY) + set(assimp_FOUND TRUE) + endif() + endif() +endif() + +if(assimp_FOUND) + if(NOT assimp_FIND_QUIETLY) + message(STATUS "Assimp found. Library is ${ASSIMP_LIBRARIES} and include dir is ${ASSIMP_INCLUDE_DIRS}") + endif() +else() + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + set(error_message "Assimp not found.") + if(CMAKE_SYSTEM_NAME STREQUAL Windows AND NOT ASSIMP_ROOT_DIR) + set(error_message "${error_message} Please set ASSIMP_ROOT_DIR to locate Assimp.") + endif() + message(FATAL_ERROR "${error_message}") + endif() +endif() diff --git a/applications/plugins/SofaCUDA/sofa/gpu/cuda/CudaTetrahedralVisualModel.inl b/applications/plugins/SofaCUDA/sofa/gpu/cuda/CudaTetrahedralVisualModel.inl index e5e866f3b1e..db7a13e0020 100644 --- a/applications/plugins/SofaCUDA/sofa/gpu/cuda/CudaTetrahedralVisualModel.inl +++ b/applications/plugins/SofaCUDA/sofa/gpu/cuda/CudaTetrahedralVisualModel.inl @@ -59,13 +59,13 @@ void OglTetrahedralModel< gpu::cuda::CudaVectorTypes >::ini if (!nodes) { - serr << "No mecha." << sendl; + msg_error() << "No mecha."; return; } if (!topo) { - serr << "No topo." << sendl; + msg_error() << "No topo."; return; } diff --git a/applications/plugins/SofaHighOrder/ExternalProjectConfig.cmake.in b/applications/plugins/SofaHighOrder/ExternalProjectConfig.cmake.in index 7824bce591b..b21792528d9 100644 --- a/applications/plugins/SofaHighOrder/ExternalProjectConfig.cmake.in +++ b/applications/plugins/SofaHighOrder/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.2) include(ExternalProject) ExternalProject_Add(SofaHighOrder GIT_REPOSITORY https://github.com/sofa-framework/SofaHighOrder - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/SofaHighOrder" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/SofaMatrix/CMakeLists.txt b/applications/plugins/SofaMatrix/CMakeLists.txt index 988aadbefc2..e716ed68c70 100644 --- a/applications/plugins/SofaMatrix/CMakeLists.txt +++ b/applications/plugins/SofaMatrix/CMakeLists.txt @@ -8,6 +8,20 @@ sofa_find_package(Sofa.Component.LinearSolver.Direct REQUIRED) sofa_find_package(Eigen3 REQUIRED) sofa_find_package(Sofa.GUI.Qt QUIET) +find_package(metis 5.1.0 EXACT QUIET) +if(NOT metis_FOUND AND SOFA_ALLOW_FETCH_DEPENDENCIES) + message("SofaMatrix: DEPENDENCY metis NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is ON, fetching metis...") + include(FetchContent) + FetchContent_Declare(metis + GIT_REPOSITORY https://github.com/sofa-framework/METIS + GIT_TAG v5.1.0-ModernInstall + ) + FetchContent_MakeAvailable(metis) +elseif (NOT metis_FOUND) + message(FATAL_ERROR "SofaMatrix: DEPENDENCY metis NOT FOUND. SOFA_ALLOW_FETCH_DEPENDENCIES is OFF and thus cannot be fetched. Install metis (version=5.1.0), or enable SOFA_ALLOW_FETCH_DEPENDENCIES to fix this issue.") +endif() + + set(SOFA_MODULES Sofa.Component.Constraint.Lagrangian.Solver Sofa.Component.LinearSolver.Direct @@ -77,7 +91,8 @@ endif() add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${README_FILES} ${MOC_HEADER_FILES} ${MOC_FILES}) # Link the plugin library to its dependency(ies). -target_link_libraries(${PROJECT_NAME} ${SOFA_MODULES}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${SOFA_MODULES}) +target_link_libraries(${PROJECT_NAME} PRIVATE metis) sofa_create_package_with_targets( PACKAGE_NAME ${PROJECT_NAME} diff --git a/applications/plugins/SofaPython3/ExternalProjectConfig.cmake.in b/applications/plugins/SofaPython3/ExternalProjectConfig.cmake.in index 1eebd415fc3..965cff02750 100644 --- a/applications/plugins/SofaPython3/ExternalProjectConfig.cmake.in +++ b/applications/plugins/SofaPython3/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(SofaPython3 GIT_REPOSITORY https://github.com/sofa-framework/SofaPython3 - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/SofaPython3" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/SoftRobots/ExternalProjectConfig.cmake.in b/applications/plugins/SoftRobots/ExternalProjectConfig.cmake.in index 566d848f869..88e6563933c 100644 --- a/applications/plugins/SoftRobots/ExternalProjectConfig.cmake.in +++ b/applications/plugins/SoftRobots/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(SoftRobots GIT_REPOSITORY https://github.com/SofaDefrost/SoftRobots - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/plugins/SoftRobots" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/plugins/VolumetricRendering/CMakeLists.txt b/applications/plugins/VolumetricRendering/CMakeLists.txt index 0f13f8e0ee6..b02f7146d1f 100644 --- a/applications/plugins/VolumetricRendering/CMakeLists.txt +++ b/applications/plugins/VolumetricRendering/CMakeLists.txt @@ -1,11 +1,12 @@ cmake_minimum_required(VERSION 3.12) -project(VolumetricRendering VERSION 0.1) +project(VolumetricRendering) -find_package(Sofa.Helper REQUIRED) +find_package(Sofa.Config REQUIRED) sofa_find_package(Sofa.GL.Component REQUIRED) set(HEADER_FILES src/VolumetricRendering/config.h.in + src/VolumetricRendering/initVolumetricRendering.cpp src/VolumetricRendering/OglTetrahedralModel.h src/VolumetricRendering/OglTetrahedralModel.inl src/VolumetricRendering/OglVolumetricModel.h @@ -19,17 +20,13 @@ set(SOURCE_FILES add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} Sofa.Helper Sofa.GL.Component) - -# Add the include DIR from OpenHaptics to target -target_include_directories(${PROJECT_NAME} PUBLIC "$") +target_link_libraries(${PROJECT_NAME} Sofa.GL.Component) # Install rules for the library and the headers; CMake package configurations files sofa_create_package_with_targets( PACKAGE_NAME ${PROJECT_NAME} + PACKAGE_VERSION ${Sofa_VERSION} TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES - PACKAGE_VERSION ${PROJECT_VERSION} INCLUDE_SOURCE_DIR "src" - INCLUDE_INSTALL_DIR "VolumetricRendering" - RELOCATABLE "plugins" - ) + INCLUDE_INSTALL_DIR "${PROJECT_NAME}" +) diff --git a/applications/plugins/VolumetricRendering/examples/OglTetrahedralModel.scn b/applications/plugins/VolumetricRendering/examples/OglTetrahedralModel.scn index d0e0e6dbe73..2584b9a2401 100644 --- a/applications/plugins/VolumetricRendering/examples/OglTetrahedralModel.scn +++ b/applications/plugins/VolumetricRendering/examples/OglTetrahedralModel.scn @@ -1,16 +1,24 @@ - - - - - - - - - - - + + + + + + - \ No newline at end of file + + + + + + + + + + + + + + diff --git a/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa.scn b/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa.scn index 6947acd4725..7ddea1884d8 100644 --- a/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa.scn +++ b/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa.scn @@ -1,18 +1,23 @@ + + + + - + + - - + + - - - - - - + + + + + + - \ No newline at end of file + diff --git a/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa_link.scn b/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa_link.scn index e6a93625208..34048c30a8b 100644 --- a/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa_link.scn +++ b/applications/plugins/VolumetricRendering/examples/OglVolumetricModel_hexa_link.scn @@ -3,18 +3,18 @@ - + - - - + + + - - - - - - + + + + + + - \ No newline at end of file + diff --git a/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.frag b/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.frag index 8ac26097cb3..c4a64b8d353 100644 --- a/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.frag +++ b/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.frag @@ -1,3 +1,5 @@ +#version 140 + uniform float u_enableLight; //GLSL >= 130 diff --git a/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.vert b/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.vert index f853623ad1d..823e83e4def 100644 --- a/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.vert +++ b/applications/plugins/VolumetricRendering/examples/share/shaders/tetra.vert @@ -1,4 +1,4 @@ -#version 130 +#version 140 // uniform vec4 vertexColor; in vec4 a_vertexColor; diff --git a/applications/plugins/VolumetricRendering/examples/share/shaders/tetra_triangles.geo b/applications/plugins/VolumetricRendering/examples/share/shaders/tetra_triangles.geo index 2d9940dfb09..472c534595a 100644 --- a/applications/plugins/VolumetricRendering/examples/share/shaders/tetra_triangles.geo +++ b/applications/plugins/VolumetricRendering/examples/share/shaders/tetra_triangles.geo @@ -1,4 +1,4 @@ -#version 130 +#version 140 #extension GL_EXT_geometry_shader4: enable //GLSL >= 130 diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.h b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.h index 43b29a359af..0fd1ca8244a 100644 --- a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.h +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include namespace sofa { @@ -76,8 +76,8 @@ class OglTetrahedralModel : public core::visual::VisualModel void updateVertexBuffer(); //Tables - sofa::component::visual::OglFloatVector4Variable::SPtr m_mappingTableValues; - sofa::component::visual::OglFloatVector4Variable::SPtr m_runSelectTableValues; + sofa::gl::component::shader::OglFloatVector4Variable::SPtr m_mappingTableValues; + sofa::gl::component::shader::OglFloatVector4Variable::SPtr m_runSelectTableValues; protected: OglTetrahedralModel(); @@ -90,16 +90,6 @@ class OglTetrahedralModel : public core::visual::VisualModel void updateVisual() override; virtual void computeMesh(); - - virtual std::string getTemplateName() const - { - return templateName(this); - } - - static std::string templateName(const OglTetrahedralModel* = NULL) - { - return DataTypes::Name(); - } }; #if !defined(SOFA_COMPONENT_VISUALMODEL_OGLTETRAHEDRALMODEL_CPP) diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.inl b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.inl index 6d8f5216bb1..9bf08a8ffc4 100644 --- a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.inl +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglTetrahedralModel.inl @@ -28,7 +28,6 @@ #include #include #include -#include #include namespace sofa @@ -63,8 +62,8 @@ void OglTetrahedralModel::init() //instanciate the mapping tables //Useful for the PT algorithm only - sofa::type::vector listVec4Variables; - this->getContext()->core::objectmodel::BaseContext::template get > + sofa::type::vector listVec4Variables; + this->getContext()->core::objectmodel::BaseContext::template get > (&listVec4Variables, core::objectmodel::BaseContext::Local); for (unsigned int i = 0; i::init() if (!m_mappingTableValues) { msg_info() << "No MappingTable found, instanciating one"; - m_mappingTableValues = sofa::core::objectmodel::New(); + m_mappingTableValues = sofa::core::objectmodel::New(); m_mappingTableValues->setName("MappingTable"); m_mappingTableValues->setID("MappingTable"); @@ -109,7 +108,7 @@ void OglTetrahedralModel::init() { msg_info() << "No RunSelectTable found, instanciating one"; - m_runSelectTableValues = sofa::core::objectmodel::New(); + m_runSelectTableValues = sofa::core::objectmodel::New(); m_runSelectTableValues->setName("RunSelectTable"); m_runSelectTableValues->setID("RunSelectTable"); @@ -179,6 +178,13 @@ void OglTetrahedralModel::initVisual() template void OglTetrahedralModel::updateVisual() { + // Workaround if updateVisual() is called without an opengl context + const auto* vparams = core::visual::VisualParams::defaultInstance(); + if (!vparams->isSupported(core::visual::API_OpenGL)) + { + return; + } + if ((modified && !m_positions.getValue().empty()) || useTopology) { @@ -255,7 +261,6 @@ void OglTetrahedralModel::computeMesh() template void OglTetrahedralModel::drawTransparent(const core::visual::VisualParams* vparams) { - using sofa::component::topology::TetrahedronSetTopologyContainer; if (!vparams->displayFlags().getShowVisualModels()) return; if (m_topology == NULL) return; if (m_topology->getNbTetrahedra() < 1) return; @@ -288,7 +293,15 @@ void OglTetrahedralModel::drawTransparent(const core::visual::VisualP glBindBufferARB(GL_ARRAY_BUFFER, m_vbo); - glVertexPointer(3, GL_FLOAT, 0, (char*)NULL + 0); + int gltype = GL_FLOAT; + + if constexpr (std::is_same_v) + { + gltype = GL_DOUBLE; + } + + glVertexPointer(3, gltype, 0, nullptr); + glBindBufferARB(GL_ARRAY_BUFFER, 0); glEnableClientState(GL_VERTEX_ARRAY); @@ -314,24 +327,21 @@ void OglTetrahedralModel::drawTransparent(const core::visual::VisualP template void OglTetrahedralModel::computeBBox(const core::ExecParams * params, bool /* onlyVisible */) { - if (m_topology) + const type::vector& position = m_positions.getValue(); + + if (m_topology && position.size() > 0) { - const core::topology::BaseMeshTopology::SeqTetrahedra& vec = m_topology->getTetrahedra(); - core::topology::BaseMeshTopology::SeqTetrahedra::const_iterator it; - Coord v; - const type::vector& position = m_positions.getValue(); const SReal max_real = std::numeric_limits::max(); - const SReal min_real = std::numeric_limits::min(); + const SReal min_real = std::numeric_limits::lowest(); SReal maxBBox[3] = { min_real,min_real,min_real }; SReal minBBox[3] = { max_real,max_real,max_real }; - for (it = vec.begin(); it != vec.end(); it++) + for(const auto& tetra : m_topology->getTetrahedra()) { for (unsigned int i = 0; i< 4; i++) { - v = position[(*it)[i]]; - //v = x[(*it)[i]]; + const auto& v = position[tetra[i]]; if (minBBox[0] > v[0]) minBBox[0] = v[0]; if (minBBox[1] > v[1]) minBBox[1] = v[1]; diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.cpp b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.cpp index a966e904856..07716e96c4e 100644 --- a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.cpp +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.cpp @@ -28,9 +28,8 @@ #include #include -#include #include -#include +#include namespace sofa::component::visualmodel { @@ -74,8 +73,8 @@ void OglVolumetricModel::init() //instanciate the mapping tables //Useful for the PT algorithm only - sofa::type::vector listVec4Variables; - this->getContext()->core::objectmodel::BaseContext::template get > + sofa::type::vector listVec4Variables; + this->getContext()->core::objectmodel::BaseContext::template get > (&listVec4Variables, core::objectmodel::BaseContext::Local); for (unsigned int i = 0; i(); + m_mappingTableValues = sofa::core::objectmodel::New(); m_mappingTableValues->setName("MappingTable"); m_mappingTableValues->setID("MappingTable"); @@ -118,7 +117,7 @@ void OglVolumetricModel::init() { msg_info() << "No RunSelectTable found, instanciating one"; - m_runSelectTableValues = sofa::core::objectmodel::New(); + m_runSelectTableValues = sofa::core::objectmodel::New(); m_runSelectTableValues->setName("RunSelectTable"); m_runSelectTableValues->setID("RunSelectTable"); @@ -156,7 +155,6 @@ void OglVolumetricModel::init() if (b_useTopology) computeMeshFromTopology(); - updateVisual(); } @@ -185,8 +183,8 @@ void OglVolumetricModel::initVisual() glBindBufferARB(GL_ARRAY_BUFFER, 0); //Check attributes - sofa::type::vector listVec4Attributes; - this->getContext()->core::objectmodel::BaseContext::template get > + sofa::type::vector listVec4Attributes; + this->getContext()->core::objectmodel::BaseContext::template get > (&listVec4Attributes, core::objectmodel::BaseContext::Local); for (unsigned int i = 0; i < listVec4Attributes.size(); i++) { @@ -201,7 +199,7 @@ void OglVolumetricModel::initVisual() if (!m_vertexColors) { msg_error() << "No attributes called a_vertexColor found, instanciating one with a default color"; - m_vertexColors = sofa::core::objectmodel::New(); + m_vertexColors = sofa::core::objectmodel::New(); m_vertexColors->setName("a_vertexColor"); m_vertexColors->setID("a_vertexColor"); m_vertexColors->setIndexShader(0); @@ -222,11 +220,17 @@ void OglVolumetricModel::initVisual() m_vertexColors->init(); m_vertexColors->initVisual(); - } void OglVolumetricModel::updateVisual() { + // Workaround if updateVisual() is called without an opengl context + const auto* vparams = core::visual::VisualParams::defaultInstance(); + if (!vparams->isSupported(core::visual::API_OpenGL)) + { + return; + } + if (b_modified || d_tetrahedra.isDirty() || d_hexahedra.isDirty() || m_positions.isDirty()) { //if(b_useTopology) @@ -358,27 +362,38 @@ void OglVolumetricModel::computeBarycenters() if (!b_tboCreated) { //Texture buffer objects + if (m_tetraBarycenters.size() > 0) + { + glGenBuffers(1, &m_tetraBarycentersTbo); + glBindBuffer(GL_TEXTURE_BUFFER, m_tetraBarycentersTbo); + glBufferData(GL_TEXTURE_BUFFER, tetraBarycentersBufferSize, &(m_tetraBarycenters[0]), GL_DYNAMIC_COPY); + glGenTextures(1, &m_tetraBarycentersTboTexture); + glBindBuffer(GL_TEXTURE_BUFFER, 0); + b_tboCreated = true; + } + if (m_hexaBarycenters.size() > 0) + { + glGenBuffers(1, &m_hexaBarycentersTbo); + glBindBuffer(GL_TEXTURE_BUFFER, m_hexaBarycentersTbo); + glBufferData(GL_TEXTURE_BUFFER, hexaBarycentersBufferSize, &(m_hexaBarycenters[0]), GL_DYNAMIC_COPY); + glGenTextures(1, &m_hexaBarycentersTboTexture); + glBindBuffer(GL_TEXTURE_BUFFER, 0); + b_tboCreated = true; + } + } - glGenBuffers(1, &m_tetraBarycentersTbo); + if (m_tetraBarycenters.size() > 0) + { glBindBuffer(GL_TEXTURE_BUFFER, m_tetraBarycentersTbo); - glBufferData(GL_TEXTURE_BUFFER, tetraBarycentersBufferSize, &(m_tetraBarycenters[0]), GL_DYNAMIC_COPY); - glGenTextures(1, &m_tetraBarycentersTboTexture); + glBufferSubData(GL_TEXTURE_BUFFER, 0, tetraBarycentersBufferSize, &(m_tetraBarycenters[0])); glBindBuffer(GL_TEXTURE_BUFFER, 0); - - glGenBuffers(1, &m_hexaBarycentersTbo); + } + if (m_hexaBarycenters.size() > 0) + { glBindBuffer(GL_TEXTURE_BUFFER, m_hexaBarycentersTbo); - glBufferData(GL_TEXTURE_BUFFER, hexaBarycentersBufferSize, &(m_hexaBarycenters[0]), GL_DYNAMIC_COPY); - glGenTextures(1, &m_hexaBarycentersTboTexture); + glBufferSubData(GL_TEXTURE_BUFFER, 0, hexaBarycentersBufferSize, &(m_hexaBarycenters[0])); glBindBuffer(GL_TEXTURE_BUFFER, 0); - - b_tboCreated = true; } - - glBindBuffer(GL_TEXTURE_BUFFER, m_tetraBarycentersTbo); - glBufferSubData(GL_TEXTURE_BUFFER, 0, tetraBarycentersBufferSize, &(m_tetraBarycenters[0])); - glBindBuffer(GL_TEXTURE_BUFFER, m_hexaBarycentersTbo); - glBufferSubData(GL_TEXTURE_BUFFER, 0, hexaBarycentersBufferSize, &(m_hexaBarycenters[0])); - glBindBuffer(GL_TEXTURE_BUFFER, 0); } void OglVolumetricModel::handleTopologyChange() @@ -399,7 +414,6 @@ void OglVolumetricModel::handleTopologyChange() void OglVolumetricModel::drawTransparent(const core::visual::VisualParams* vparams) { - using sofa::component::topology::TetrahedronSetTopologyContainer; if (!vparams->displayFlags().getShowVisualModels()) return; glPushAttrib(GL_ALL_ATTRIB_BITS); @@ -426,7 +440,14 @@ void OglVolumetricModel::drawTransparent(const core::visual::VisualParams* vpara #ifdef GL_LINES_ADJACENCY_EXT glBindBufferARB(GL_ARRAY_BUFFER, m_vbo); - glVertexPointer(3, GL_FLOAT, 0, (char*)NULL + 0); + int gltype = GL_FLOAT; + + if constexpr (std::is_same_v) + { + gltype = GL_DOUBLE; + } + + glVertexPointer(3, gltype, 0, nullptr); glBindBufferARB(GL_ARRAY_BUFFER, 0); glEnableClientState(GL_VERTEX_ARRAY); @@ -435,6 +456,7 @@ void OglVolumetricModel::drawTransparent(const core::visual::VisualParams* vpara const type::vector& hexahedra = d_hexahedra.getValue(); //glEnable(GL_CLIP_DISTANCE0); + if (tetrahedra.size() > 0) { glBindTexture(GL_TEXTURE_BUFFER, m_tetraBarycentersTboTexture); diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.h b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.h index 84f9b2ae64f..7fc4034afad 100644 --- a/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.h +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/OglVolumetricModel.h @@ -49,7 +49,7 @@ namespace visualmodel class SOFA_VOLUMETRICRENDERING_API OglVolumetricModel : public core::visual::VisualModel, public component::visual::Vec3State { public: - SOFA_CLASS2(OglVolumetricModel, core::visual::VisualModel, Vec3State); + SOFA_CLASS2(OglVolumetricModel, core::visual::VisualModel, component::visual::Vec3State); typedef sofa::core::topology::Tetrahedron Tetrahedron; typedef sofa::core::topology::Hexahedron Hexahedron; @@ -94,8 +94,8 @@ class SOFA_VOLUMETRICRENDERING_API OglVolumetricModel : public core::visual::Vis sofa::type::vector m_hexaToTetrahedra; - sofa::type::vector m_tetraBarycenters; - sofa::type::vector m_hexaBarycenters; + sofa::type::vector m_tetraBarycenters; + sofa::type::vector m_hexaBarycenters; public: void init() override; diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/config.h.in b/applications/plugins/VolumetricRendering/src/VolumetricRendering/config.h.in index 40f6cac6c86..bb9fb08d30a 100644 --- a/applications/plugins/VolumetricRendering/src/VolumetricRendering/config.h.in +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/config.h.in @@ -33,4 +33,10 @@ # define SOFA_VOLUMETRICRENDERING_API SOFA_IMPORT_DYNAMIC_LIBRARY #endif +namespace volumetricrendering +{ + constexpr const char* MODULE_NAME = "@PROJECT_NAME@"; + constexpr const char* MODULE_VERSION = "@PROJECT_VERSION@"; +} + #endif diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.cpp b/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.cpp index 3008b366634..de1556a8deb 100644 --- a/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.cpp +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.cpp @@ -19,10 +19,10 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ +#include +#include -#include - -namespace sofa::component +namespace volumetricrendering { //Here are just several convenient functions to help user to know what contains the plugin @@ -36,6 +36,11 @@ extern "C" { SOFA_VOLUMETRICRENDERING_API const char* getModuleComponentList(); } +void init() +{ + initExternalModule(); +} + void initExternalModule() { static bool first = true; @@ -47,12 +52,12 @@ void initExternalModule() const char* getModuleName() { - return "VolumetricRendering"; + return volumetricrendering::MODULE_NAME; } const char* getModuleVersion() { - return "0.1"; + return volumetricrendering::MODULE_VERSION; } const char* getModuleLicense() @@ -68,9 +73,9 @@ const char* getModuleDescription() const char* getModuleComponentList() { - return "OglTetrahedralModel"; + static std::string classes = sofa::core::ObjectFactory::getInstance()->listClassesFromTarget(volumetricrendering::MODULE_NAME); + return classes.c_str(); } -} // namespace sofa::component - +} // namespace volumetricrendering diff --git a/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.h b/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.h new file mode 100644 index 00000000000..fb505e5a842 --- /dev/null +++ b/applications/plugins/VolumetricRendering/src/VolumetricRendering/initVolumetricRendering.h @@ -0,0 +1,29 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 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 . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#pragma once + +#include + +namespace volumetricrendering +{ +SOFA_VOLUMETRICRENDERING_API void init(); +} diff --git a/applications/plugins/image/image_test/ImageEngine_test.cpp b/applications/plugins/image/image_test/ImageEngine_test.cpp index 9549af5a122..50ad94855fa 100644 --- a/applications/plugins/image/image_test/ImageEngine_test.cpp +++ b/applications/plugins/image/image_test/ImageEngine_test.cpp @@ -54,7 +54,7 @@ struct ImageEngine_test : public sofa::testing::BaseTest void TearDown() { if (root!=NULL) - sofa::simulation::getSimulation()->unload(root); + sofa::simulation::node::unload(root); } // Test link @@ -130,7 +130,7 @@ struct ImageEngine_test : public sofa::testing::BaseTest TestImageEngine::SPtr imageEngine; // Create a scene - sofa::simulation::setSimulation(simulation = new sofa::simulation::graph::DAGSimulation()); + simulation = sofa::simulation::getSimulation(); // Root node root = simulation->createNewGraph("root"); @@ -156,12 +156,12 @@ struct ImageEngine_test : public sofa::testing::BaseTest sofa::modeling::setDataLink(&imageEngine->outputImage,&imageEngine2->inputImage); // Init simulation - sofa::simulation::getSimulation()->init(root.get()); + sofa::simulation::node::initRoot(root.get()); // do several steps of animation for(int l=0;l<2;++l) { - sofa::simulation::getSimulation()->animate(root.get(),0.5); + sofa::simulation::node::animate(root.get(),0.5); } // Check if pointers of images that should be shared are equal @@ -190,7 +190,7 @@ struct ImageEngine_test : public sofa::testing::BaseTest ImageViewer::SPtr imageViewer; // Create a scene - sofa::simulation::setSimulation(simulation = new sofa::simulation::graph::DAGSimulation()); + simulation = sofa::simulation::getSimulation(); // Root node root = simulation->createNewGraph("root"); @@ -221,12 +221,12 @@ struct ImageEngine_test : public sofa::testing::BaseTest //sofa::modeling::setDataLink(&imageContainer->image,&imageViewer->image); // Init simulation - sofa::simulation::getSimulation()->init(root.get()); + sofa::simulation::node::initRoot(root.get()); // do several steps of animation for(int l=0;l<2;++l) { - sofa::simulation::getSimulation()->animate(root.get(),0.5); + sofa::simulation::node::animate(root.get(),0.5); } diff --git a/applications/projects/CMakeLists.txt b/applications/projects/CMakeLists.txt index 48eebc64ff8..13301bb2e52 100644 --- a/applications/projects/CMakeLists.txt +++ b/applications/projects/CMakeLists.txt @@ -13,6 +13,6 @@ sofa_add_subdirectory(application SofaGuiGlut SofaGuiGlut OFF) sofa_add_subdirectory(application runSofa runSofa ON) sofa_add_subdirectory(application sofaOPENCL sofaOPENCL OFF) -sofa_add_subdirectory(directory Regression Regression EXTERNAL) -sofa_add_subdirectory(directory SofaGLFW SofaGLFW EXTERNAL) +sofa_add_subdirectory(directory Regression Regression EXTERNAL GIT_REF v23.12) +sofa_add_subdirectory(directory SofaGLFW SofaGLFW EXTERNAL GIT_REF v23.12) sofa_add_subdirectory(application sofaProjectExample sofaProjectExample) diff --git a/applications/projects/Modeler/lib/CMakeLists.txt b/applications/projects/Modeler/lib/CMakeLists.txt index 176f8bda686..642174019ec 100644 --- a/applications/projects/Modeler/lib/CMakeLists.txt +++ b/applications/projects/Modeler/lib/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12) project(SofaModeler VERSION 0.1) -find_package(TinyXML REQUIRED) +find_package(TinyXML2 REQUIRED) set(HEADER_FILES AddPreset.h @@ -43,7 +43,7 @@ set(MOC_FILES_GROUP "Generated") add_library(${PROJECT_NAME} STATIC ${HEADER_FILES} ${MOC_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC SofaGui SofaBase SofaCommon SofaGeneral SofaMisc) target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) -target_link_libraries(${PROJECT_NAME} PUBLIC tinyxml) # Public because needed by Modeler (exec) +target_link_libraries(${PROJECT_NAME} PUBLIC tinyxml2::tinyxml2) # Public because needed by Modeler (exec) sofa_create_package_with_targets( PACKAGE_NAME ${PROJECT_NAME} diff --git a/applications/projects/Modeler/lib/SofaModelerConfig.cmake.in b/applications/projects/Modeler/lib/SofaModelerConfig.cmake.in index 8870ee91ca7..90a138d6963 100644 --- a/applications/projects/Modeler/lib/SofaModelerConfig.cmake.in +++ b/applications/projects/Modeler/lib/SofaModelerConfig.cmake.in @@ -3,7 +3,7 @@ @PACKAGE_INIT@ find_package(SofaGeneral QUIET REQUIRED) -find_package(TinyXML REQUIRED) +find_package(TinyXML2 REQUIRED) if(NOT TARGET @PROJECT_NAME@) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/applications/projects/Modeler/lib/TutorialSelector.cpp b/applications/projects/Modeler/lib/TutorialSelector.cpp index 139ed9706cf..86730f73e1c 100644 --- a/applications/projects/Modeler/lib/TutorialSelector.cpp +++ b/applications/projects/Modeler/lib/TutorialSelector.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include namespace sofa { @@ -86,16 +86,20 @@ void TutorialSelector::loadTutorials(const std::string &fileTutorial) this->clear(); itemToTutorial.clear(); - //Open it using TinyXML - TiXmlDocument doc(fileTutorial.c_str()); - doc.LoadFile(); + //Open it using TinyXML2 + tinyxml2::XMLDocument doc; + if (doc.LoadFile(fileTutorial.c_str()) != tinyxml2::XML_SUCCESS) + { + msg_error("TutorialSelector") << "Unable to load file '" << fileTutorial << "'"; + return; + } - TiXmlHandle hDoc(&doc); + tinyxml2::XMLHandle hDoc(&doc); //Getting the root of the file - TiXmlNode* node=hDoc.FirstChildElement().ToElement(); + tinyxml2::XMLNode* node=hDoc.FirstChildElement().ToElement(); if (!node) { - msg_error("TutorialSelector") << "Unable to load file '" << fileTutorial << "'"; + msg_error("TutorialSelector") << "Unable to get root XML node from file '" << fileTutorial << "'"; return; } openNode(node, nullptr, true); @@ -103,7 +107,7 @@ void TutorialSelector::loadTutorials(const std::string &fileTutorial) this->setMaximumWidth((int)(this->columnWidth(0)*1.1)); } -void TutorialSelector::openNode(TiXmlNode *node, QTreeWidgetItem *parent, bool isRoot) +void TutorialSelector::openNode(tinyxml2::XMLNode *node, QTreeWidgetItem *parent, bool isRoot) { std::string nameOfNode=node->Value(); // TinyXml API changed in 2.6.0, ELEMENT was replaced with TINYXML_ELEMENT @@ -112,7 +116,7 @@ void TutorialSelector::openNode(TiXmlNode *node, QTreeWidgetItem *parent, bool i // -- Jeremie A. 02/07/2011 //int typeOfNode=node->Type(); QTreeWidgetItem* item=nullptr; - if (node->ToElement()) // case TiXmlNode::ELEMENT: + if (node->ToElement()) // case tinyxml2::XMLNode::ELEMENT: { if (!isRoot) { @@ -135,16 +139,16 @@ void TutorialSelector::openNode(TiXmlNode *node, QTreeWidgetItem *parent, bool i else // default: { } - for ( TiXmlNode* child = node->FirstChild(); child != nullptr; child = child->NextSibling()) + for ( tinyxml2::XMLNode* child = node->FirstChild(); child != nullptr; child = child->NextSibling()) { openNode(child, item); } } -void TutorialSelector::openAttribute(TiXmlElement* element, QTreeWidgetItem *item) +void TutorialSelector::openAttribute(tinyxml2::XMLElement* element, QTreeWidgetItem *item) { if (!element || !item) return; - TiXmlAttribute* attribute=element->FirstAttribute(); + const tinyxml2::XMLAttribute* attribute=element->FirstAttribute(); std::string typeElement=element->Value() ; std::map attributes; diff --git a/applications/projects/Modeler/lib/TutorialSelector.h b/applications/projects/Modeler/lib/TutorialSelector.h index b42266274c1..bb41e8e7c03 100644 --- a/applications/projects/Modeler/lib/TutorialSelector.h +++ b/applications/projects/Modeler/lib/TutorialSelector.h @@ -30,8 +30,8 @@ #include // Forward declarations -class TiXmlNode; -class TiXmlElement; +class tinyxml2::XMLNode; +class tinyxml2::XMLElement; #include @@ -106,8 +106,8 @@ public slots: void openTutorial(const Tutorial&); void loadTutorials(const std::string &fileTutorials); - void openNode(TiXmlNode* node, QTreeWidgetItem *parent=nullptr, bool isRoot=false); - void openAttribute(TiXmlElement* element, QTreeWidgetItem *item); + void openNode(tinyxml2::XMLNode* node, QTreeWidgetItem *parent=nullptr, bool isRoot=false); + void openAttribute(tinyxml2::XMLElement* element, QTreeWidgetItem *item); std::map< QTreeWidgetItem *, Category> itemToCategory; std::map< QTreeWidgetItem *, Tutorial> itemToTutorial; diff --git a/applications/projects/Regression/ExternalProjectConfig.cmake.in b/applications/projects/Regression/ExternalProjectConfig.cmake.in index 6653d4075ff..9d1b66e6dd3 100644 --- a/applications/projects/Regression/ExternalProjectConfig.cmake.in +++ b/applications/projects/Regression/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.2) include(ExternalProject) ExternalProject_Add(Regression GIT_REPOSITORY https://github.com/sofa-framework/regression - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/projects/Regression" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/projects/SofaGLFW/ExternalProjectConfig.cmake.in b/applications/projects/SofaGLFW/ExternalProjectConfig.cmake.in index fd3922006de..22d1eaf4f1c 100644 --- a/applications/projects/SofaGLFW/ExternalProjectConfig.cmake.in +++ b/applications/projects/SofaGLFW/ExternalProjectConfig.cmake.in @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11) include(ExternalProject) ExternalProject_Add(SofaGLFW GIT_REPOSITORY https://github.com/sofa-framework/SofaGLFW - GIT_TAG origin/master + GIT_TAG origin/@ARG_GIT_REF@ SOURCE_DIR "${CMAKE_SOURCE_DIR}/applications/projects/SofaGLFW" BINARY_DIR "" CONFIGURE_COMMAND "" diff --git a/applications/projects/SofaPhysicsAPI/src/SofaPhysicsAPI/SofaPhysicsBindings.cpp b/applications/projects/SofaPhysicsAPI/src/SofaPhysicsAPI/SofaPhysicsBindings.cpp index 0e2ae2a3573..c3e83065873 100644 --- a/applications/projects/SofaPhysicsAPI/src/SofaPhysicsAPI/SofaPhysicsBindings.cpp +++ b/applications/projects/SofaPhysicsAPI/src/SofaPhysicsAPI/SofaPhysicsBindings.cpp @@ -354,7 +354,7 @@ int sofaVisualModel_getNbEdges(void* api_ptr, const char* name) } -int sofaVisualModel_getEdges(void* api_ptr, const char* name, int* buffer) +int sofaVisualModel_getEdges(void* /*api_ptr*/, const char* /*name*/, int* /*buffer*/) { //TODO diff --git a/applications/projects/xmlconvert-displayflags/CMakeLists.txt b/applications/projects/xmlconvert-displayflags/CMakeLists.txt index 0321017514b..8092948ce1c 100644 --- a/applications/projects/xmlconvert-displayflags/CMakeLists.txt +++ b/applications/projects/xmlconvert-displayflags/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12) project(xmlconvert-displayflags) -find_package(TinyXML REQUIRED) +find_package(TinyXML2 REQUIRED) add_executable(${PROJECT_NAME} xmlvisitor.h xmlvisitor.cpp main.cpp) -target_link_libraries(${PROJECT_NAME} TinyXML Sofa.Core) +target_link_libraries(${PROJECT_NAME} tinyxml2::tinyxml2 Sofa.Core) diff --git a/applications/projects/xmlconvert-displayflags/main.cpp b/applications/projects/xmlconvert-displayflags/main.cpp index ecbf4eaeafb..a1dc857398a 100644 --- a/applications/projects/xmlconvert-displayflags/main.cpp +++ b/applications/projects/xmlconvert-displayflags/main.cpp @@ -19,25 +19,25 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include "xmlvisitor.h" #include #include -TiXmlDocument* loadFromFile(const char *filename) +tinyxml2::XMLDocument* loadFromFile(const char *filename) { // this initialize the library and check potential ABI mismatches // between the version it was compiled for and the actual shared // library used. // - TiXmlDocument* doc = new TiXmlDocument; // the resulting document tree + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument; // the resulting document tree // xmlSubstituteEntitiesDefault(1); - if (!(doc->LoadFile(filename))) + if (doc->LoadFile(filename) != tinyxml2::XML_SUCCESS) { - std::cerr << "Failed to open " << filename << "\n" << doc->ErrorDesc() << " at line " << doc->ErrorRow() << " row " << doc->ErrorCol() << std::endl; + std::cerr << "Failed to open " << filename << "\n" << doc->ErrorStr() << " at line " << doc->ErrorLineNum() << std::endl; delete doc; return NULL; } @@ -50,7 +50,7 @@ using namespace sofa::xml; int main(int argc, char** argv) { if( argc < 2 ) return -1; - TiXmlDocument* doc = loadFromFile(argv[1]); + tinyxml2::XMLDocument* doc = loadFromFile(argv[1]); sofa::core::init(); int retValue = 0; @@ -74,22 +74,22 @@ int main(int argc, char** argv) if( v_nodes.rootNode() ) { - std::map::iterator it_root; + std::map::iterator it_root; it_root = v_displayFlags.map_displayFlags.find(v_nodes.rootNode()); if( it_root != v_displayFlags.map_displayFlags.end() ) { DisplayFlags* root_flags = it_root->second; convert_false_to_neutral(*root_flags); - TiXmlElement* visualStyle; + tinyxml2::XMLElement* visualStyle; if( ! root_flags->isNeutral() ) { if( (visualStyle = v_nodes.rootNode()->FirstChildElement("VisualStyle") ) == NULL ) { - TiXmlElement* visualstyle = new TiXmlElement("VisualStyle"); + tinyxml2::XMLElement* visualstyle = new tinyxml2::XMLElement("VisualStyle"); std::ostringstream oss; oss << *root_flags; visualstyle->SetAttribute("displayFlags",oss.str()); - TiXmlElement* first_child = v_nodes.rootNode()->FirstChildElement(); + tinyxml2::XMLElement* first_child = v_nodes.rootNode()->FirstChildElement(); if(first_child) v_nodes.rootNode()->InsertBeforeChild(first_child,*visualstyle); else v_nodes.rootNode()->LinkEndChild(visualstyle); } diff --git a/applications/projects/xmlconvert-displayflags/xmlvisitor.cpp b/applications/projects/xmlconvert-displayflags/xmlvisitor.cpp index e5d0e0ab9e4..66a25f36968 100644 --- a/applications/projects/xmlconvert-displayflags/xmlvisitor.cpp +++ b/applications/projects/xmlconvert-displayflags/xmlvisitor.cpp @@ -31,10 +31,10 @@ namespace xml { -bool DiscoverNodes::VisitEnter(const TiXmlElement& element, const TiXmlAttribute* ) +bool DiscoverNodes::VisitEnter(const tinyxml2::XMLElement& element, const tinyxml2::XMLAttribute* ) { if( element.ValueStr() != std::string("Node") ) return true; - const TiXmlElement* child; + const tinyxml2::XMLElement* child; bool is_leafnode = true; for( child = element.FirstChildElement() ; child != 0; child = child->NextSiblingElement()) { @@ -47,13 +47,13 @@ bool DiscoverNodes::VisitEnter(const TiXmlElement& element, const TiXmlAttribute if( is_leafnode) { //std::cout << element << std::endl; - leaves.push_back(const_cast(&element)); + leaves.push_back(const_cast(&element)); } - nodes.push_back(const_cast(&element)); + nodes.push_back(const_cast(&element)); return true; } -bool DiscoverDisplayFlagsVisitor::VisitEnter(const TiXmlElement & element, const TiXmlAttribute * attribute) +bool DiscoverDisplayFlagsVisitor::VisitEnter(const tinyxml2::XMLElement & element, const tinyxml2::XMLAttribute * attribute) { // skip elements other than Nodes @@ -69,7 +69,7 @@ bool DiscoverDisplayFlagsVisitor::VisitEnter(const TiXmlElement & element, const sofa::core::visual::DisplayFlags* flags = map_displayFlags[&element]; - const TiXmlAttribute* current; + const tinyxml2::XMLAttribute* current; for( current = attribute; current != NULL; current = current->Next() ) { std::string attribute_name( current->Name() ); @@ -161,7 +161,7 @@ bool DiscoverDisplayFlagsVisitor::VisitEnter(const TiXmlElement & element, const DiscoverDisplayFlagsVisitor::~DiscoverDisplayFlagsVisitor() { - std::map::iterator it_map; + std::map::iterator it_map; for(it_map = map_displayFlags.begin(); it_map != map_displayFlags.end(); ++it_map) { delete it_map->second; @@ -170,13 +170,13 @@ DiscoverDisplayFlagsVisitor::~DiscoverDisplayFlagsVisitor() } -void createVisualStyleVisitor(TiXmlElement* origin, const std::map& map_displayFlags) +void createVisualStyleVisitor(tinyxml2::XMLElement* origin, const std::map& map_displayFlags) { - TiXmlNode* parent = origin->Parent(); - TiXmlElement* parent_element = parent->ToElement(); + tinyxml2::XMLNode* parent = origin->Parent(); + tinyxml2::XMLElement* parent_element = parent->ToElement(); if( ! parent_element ) { - std::map::const_iterator it_current; + std::map::const_iterator it_current; it_current = map_displayFlags.find(origin); if(it_current == map_displayFlags.end() ) { @@ -189,11 +189,11 @@ void createVisualStyleVisitor(TiXmlElement* origin, const std::mapFirstChildElement("VisualStyle") == NULL ) { //convert_false_to_neutral(current_flags); - TiXmlElement* visualstyle = new TiXmlElement("VisualStyle"); + tinyxml2::XMLElement* visualstyle = new tinyxml2::XMLElement("VisualStyle"); std::ostringstream oss; oss << current_flags; visualstyle->SetAttribute("displayFlags",oss.str()); - TiXmlElement* first_child = origin->FirstChildElement(); + tinyxml2::XMLElement* first_child = origin->FirstChildElement(); if(first_child) origin->InsertBeforeChild(first_child,*visualstyle); else origin->LinkEndChild(visualstyle); } @@ -201,8 +201,8 @@ void createVisualStyleVisitor(TiXmlElement* origin, const std::map::const_iterator it_current; - std::map::const_iterator it_parent; + std::map::const_iterator it_current; + std::map::const_iterator it_parent; it_current = map_displayFlags.find(origin); it_parent = map_displayFlags.find(parent_element); @@ -225,11 +225,11 @@ void createVisualStyleVisitor(TiXmlElement* origin, const std::mapFirstChildElement("VisualStyle") == NULL ) { - TiXmlElement* visualstyle = new TiXmlElement("VisualStyle"); + tinyxml2::XMLElement* visualstyle = new tinyxml2::XMLElement("VisualStyle"); std::ostringstream oss; oss << difference; visualstyle->SetAttribute("displayFlags",oss.str()); - TiXmlElement* first_child = origin->FirstChildElement(); + tinyxml2::XMLElement* first_child = origin->FirstChildElement(); if(first_child) origin->InsertBeforeChild(first_child,*visualstyle); else origin->LinkEndChild(visualstyle); @@ -239,24 +239,24 @@ void createVisualStyleVisitor(TiXmlElement* origin, const std::mapRemoveAttribute("showAll"); - node->RemoveAttribute("showVisual"); - node->RemoveAttribute("showVisualModels"); - node->RemoveAttribute("showBehavior"); - node->RemoveAttribute("showForceFields"); - node->RemoveAttribute("showInteractionForceFields"); - node->RemoveAttribute("showBehaviorModels"); - node->RemoveAttribute("showCollision"); - node->RemoveAttribute("showCollisionModels"); - node->RemoveAttribute("showBoundingCollisionModels"); - node->RemoveAttribute("showMapping"); - node->RemoveAttribute("showMappings"); - node->RemoveAttribute("showMechanicalMappings"); - node->RemoveAttribute("showWireFrame"); - node->RemoveAttribute("showNormals"); - node->RemoveAttribute("showProcessorColor"); + node->DeleteAttribute("showAll"); + node->DeleteAttribute("showVisual"); + node->DeleteAttribute("showVisualModels"); + node->DeleteAttribute("showBehavior"); + node->DeleteAttribute("showForceFields"); + node->DeleteAttribute("showInteractionForceFields"); + node->DeleteAttribute("showBehaviorModels"); + node->DeleteAttribute("showCollision"); + node->DeleteAttribute("showCollisionModels"); + node->DeleteAttribute("showBoundingCollisionModels"); + node->DeleteAttribute("showMapping"); + node->DeleteAttribute("showMappings"); + node->DeleteAttribute("showMechanicalMappings"); + node->DeleteAttribute("showWireFrame"); + node->DeleteAttribute("showNormals"); + node->DeleteAttribute("showProcessorColor"); } diff --git a/applications/projects/xmlconvert-displayflags/xmlvisitor.h b/applications/projects/xmlconvert-displayflags/xmlvisitor.h index 1cf94924ba2..f47b84140c6 100644 --- a/applications/projects/xmlconvert-displayflags/xmlvisitor.h +++ b/applications/projects/xmlconvert-displayflags/xmlvisitor.h @@ -22,7 +22,7 @@ #ifndef SOFA_XMLCONVERT_XMLVISITOR #define SOFA_XMLCONVERT_XMLVISITOR -#include +#include #include #include #include @@ -32,36 +32,36 @@ namespace sofa namespace xml { -class DiscoverNodes : public TiXmlVisitor +class DiscoverNodes : public tinyxml2::XMLVisitor { public: - virtual bool VisitEnter( const TiXmlElement&, const TiXmlAttribute* ); + virtual bool VisitEnter( const tinyxml2::XMLElement&, const tinyxml2::XMLAttribute* ); - TiXmlElement* rootNode() + tinyxml2::XMLElement* rootNode() { if( nodes.empty() ) return NULL; else return nodes[0]; } - std::vector leaves; - std::vector nodes; + std::vector leaves; + std::vector nodes; }; -class DiscoverDisplayFlagsVisitor : public TiXmlVisitor +class DiscoverDisplayFlagsVisitor : public tinyxml2::XMLVisitor { public: - virtual bool VisitEnter( const TiXmlElement&, const TiXmlAttribute* ); + virtual bool VisitEnter( const tinyxml2::XMLElement&, const tinyxml2::XMLAttribute* ); ~DiscoverDisplayFlagsVisitor(); - std::map map_displayFlags; + std::map map_displayFlags; }; -void createVisualStyleVisitor(TiXmlElement* leaf, const std::map& map_displayFlags); +void createVisualStyleVisitor(tinyxml2::XMLElement* leaf, const std::map& map_displayFlags); -void removeShowAttributes(TiXmlElement* node); +void removeShowAttributes(tinyxml2::XMLElement* node); void convert_false_to_neutral(sofa::core::visual::DisplayFlags& flags); diff --git a/applications/tutorials/chainHybrid/chainHybrid.cpp b/applications/tutorials/chainHybrid/chainHybrid.cpp index fd5245e43ab..54351897099 100644 --- a/applications/tutorials/chainHybrid/chainHybrid.cpp +++ b/applications/tutorials/chainHybrid/chainHybrid.cpp @@ -244,7 +244,6 @@ int main(int argc, char** argv) sofa::gui::common::GUIManager::Init(argv[0]); auto simulation = sofa::simpleapi::createSimulation(); - sofa::simulation::setSimulation( simulation.get() ); // The graph root node Node::SPtr root = sofa::modeling::createRootWithCollisionPipeline(); @@ -255,7 +254,7 @@ int main(int argc, char** argv) root->setAnimate(false); - sofa::simulation::getSimulation()->init(root.get()); + sofa::simulation::node::initRoot(root.get()); //======================================= diff --git a/applications/tutorials/compositeObject/compositeObject.cpp b/applications/tutorials/compositeObject/compositeObject.cpp index ede322d8a9a..cd9a2cefe61 100644 --- a/applications/tutorials/compositeObject/compositeObject.cpp +++ b/applications/tutorials/compositeObject/compositeObject.cpp @@ -256,13 +256,11 @@ int main(int argc, char** argv) if (int err=sofa::gui::common::GUIManager::createGUI(NULL)) return err; sofa::gui::common::GUIManager::SetDimension(800,600); - sofa::simulation::setSimulation(new sofa::simulation::graph::DAGSimulation()); - //================================================= sofa::simulation::Node::SPtr groot = createGridScene(Vec3(0,0,0), Vec3(5,1,1), 6,2,2, 1.0 ); //================================================= - sofa::simulation::getSimulation()->init(groot.get()); + sofa::simulation::node::initRoot(groot.get()); sofa::gui::common::GUIManager::SetScene(groot); groot->setAnimate(true); @@ -271,7 +269,7 @@ int main(int argc, char** argv) if (int err = sofa::gui::common::GUIManager::MainLoop(groot)) return err; - sofa::simulation::getSimulation()->unload(groot); + sofa::simulation::node::unload(groot); sofa::gui::common::GUIManager::closeGUI(); sofa::simulation::graph::cleanup(); diff --git a/applications/tutorials/mixedPendulum/mixedPendulum.cpp b/applications/tutorials/mixedPendulum/mixedPendulum.cpp index f7084a5ed35..41e2a186ac0 100644 --- a/applications/tutorials/mixedPendulum/mixedPendulum.cpp +++ b/applications/tutorials/mixedPendulum/mixedPendulum.cpp @@ -66,7 +66,6 @@ int main(int argc, char** argv) double splength = 1.; //-------------------- The graph root node - sofa::simulation::setSimulation(new sofa::simulation::graph::DAGSimulation()); auto groot = sofa::simulation::getSimulation()->createNewGraph("root"); groot->setGravity({ 0,-10,0 }); @@ -199,7 +198,7 @@ int main(int argc, char** argv) sofa::gui::common::GUIManager::SetDimension(800, 600); //=========================== Init the scene - sofa::simulation::getSimulation()->init(groot.get()); + sofa::simulation::node::initRoot(groot.get()); sofa::gui::common::GUIManager::SetScene(groot); groot->setAnimate(true); @@ -208,9 +207,8 @@ int main(int argc, char** argv) sofa::gui::common::GUIManager::MainLoop(groot); if (groot != NULL) - sofa::simulation::getSimulation()->unload(groot); + sofa::simulation::node::unload(groot); sofa::simulation::graph::cleanup(); return 0; } - diff --git a/applications/tutorials/oneParticle/oneParticle.cpp b/applications/tutorials/oneParticle/oneParticle.cpp index b8f405609b4..f0697745daa 100644 --- a/applications/tutorials/oneParticle/oneParticle.cpp +++ b/applications/tutorials/oneParticle/oneParticle.cpp @@ -64,7 +64,6 @@ int main(int argc, char** argv) sofa::gui::common::GUIManager::Init(argv[0]); // The graph root node - sofa::simulation::setSimulation(new sofa::simulation::graph::DAGSimulation()); sofa::simulation::Node::SPtr groot = sofa::simulation::getSimulation()->createNewGraph("root"); groot->setGravity({ 0,-10,0 }); @@ -113,7 +112,7 @@ int main(int argc, char** argv) flags.setShowCollisionModels(true); style->displayFlags.endEdit(); - sofa::simulation::graph::getSimulation()->init(groot.get()); + sofa::simulation::node::initRoot(groot.get()); groot->setAnimate(false); //====================================== diff --git a/cmake/Modules/FindQGLViewer.cmake b/cmake/Modules/FindQGLViewer.cmake index cbf284d949a..e6dbab5ef6b 100644 --- a/cmake/Modules/FindQGLViewer.cmake +++ b/cmake/Modules/FindQGLViewer.cmake @@ -21,7 +21,7 @@ if(NOT TARGET QGLViewer) if(NOT QGLViewer_LIBRARY) find_library(QGLViewer_LIBRARY - NAMES QGLViewer QGLViewer-qt5 + NAMES QGLViewer QGLViewer2 QGLViewer-qt5 PATH_SUFFIXES lib ) endif() diff --git a/cmake/Modules/FindTinyXML2.cmake b/cmake/Modules/FindTinyXML2.cmake new file mode 100644 index 00000000000..6dda44b060d --- /dev/null +++ b/cmake/Modules/FindTinyXML2.cmake @@ -0,0 +1,53 @@ +# Find the tinyxml2 headers and libraries +# Behavior is to first look for config files, such as the one installed by some package +# managers who provides their own cmake files. If no config files +# were found, this tries to find the library by looking at headers / lib file. +# +# Defines: +# TinyXML2_FOUND : True if tinyxml2 is found +# +# Provides target tinyxml2::tinyxml2. +find_package(tinyxml2 NO_MODULE QUIET) + +if(TARGET tinyxml2::tinyxml2) + set(TinyXML2_FOUND TRUE) # only tinyxml2_FOUND has been set +else() + + if(NOT TinyXML2_INCLUDE_DIR) + find_path(TinyXML2_INCLUDE_DIR + NAMES tinyxml2.h + PATH_SUFFIXES include + ) + endif() + + if(NOT TinyXML2_LIBRARY) + find_library(TinyXML2_LIBRARY + NAMES tinyxml2 + PATH_SUFFIXES lib + ) + endif() + + if(TinyXML2_INCLUDE_DIR AND TinyXML2_LIBRARY) + set(TinyXML2_FOUND TRUE) + else() + if(TinyXML2_FIND_REQUIRED) + message(FATAL_ERROR "Cannot find TinyXML2") + endif() + endif() + + if(TinyXML2_FOUND) + set(TinyXML2_LIBRARIES ${TinyXML2_LIBRARY}) + set(TinyXML2_INCLUDE_DIRS ${TinyXML2_INCLUDE_DIR}) + + if(NOT TARGET tinyxml2::tinyxml2) + add_library(tinyxml2::tinyxml2 SHARED IMPORTED) + set_property(TARGET tinyxml2::tinyxml2 PROPERTY IMPORTED_LOCATION "${TinyXML2_LIBRARIES}") + if(WIN32) + set_property(TARGET tinyxml2::tinyxml2 PROPERTY IMPORTED_IMPLIB "${TinyXML2_LIBRARIES}") + endif() + set_property(TARGET tinyxml2::tinyxml2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${TinyXML2_INCLUDE_DIR}") + endif() + else() + endif() + mark_as_advanced(TinyXML2_INCLUDE_DIR TinyXML2_LIBRARY) +endif() diff --git a/examples/Component/Constraint/Lagrangian/BilateralInteractionConstraint_Rigid.scn b/examples/Component/Constraint/Lagrangian/BilateralInteractionConstraint_Rigid.scn index 0a387c66ad4..6ed48f210ff 100644 --- a/examples/Component/Constraint/Lagrangian/BilateralInteractionConstraint_Rigid.scn +++ b/examples/Component/Constraint/Lagrangian/BilateralInteractionConstraint_Rigid.scn @@ -28,7 +28,7 @@ - + @@ -42,7 +42,7 @@ - + diff --git a/examples/Component/IO/Mesh/GIDMeshLoader.scn b/examples/Component/IO/Mesh/GIDMeshLoader.scn index 67d832f36aa..d11c399f26e 100644 --- a/examples/Component/IO/Mesh/GIDMeshLoader.scn +++ b/examples/Component/IO/Mesh/GIDMeshLoader.scn @@ -19,7 +19,7 @@ - + diff --git a/examples/RegressionStateScenes.regression-tests b/examples/RegressionStateScenes.regression-tests index 7ac5834edf8..de108be75b9 100644 --- a/examples/RegressionStateScenes.regression-tests +++ b/examples/RegressionStateScenes.regression-tests @@ -8,6 +8,9 @@ # REGRESSION_TEST DOES NOT SUPPORT DASHES ("-") IN SCENE NAMES. # USE UNDERSCORES ("_") INSTEAD. +### References relative path ### +../applications/projects/Regression/references/examples + ### Demo scenes ### Demos/TriangleSurfaceCutting.scn 100 1e-4 1 1 Demos/chainAll.scn 100 1e-2 1 1 diff --git a/examples/RegressionTopologyScenes.regression-tests b/examples/RegressionTopologyScenes.regression-tests index 379dd0b5c59..a789f64974a 100644 --- a/examples/RegressionTopologyScenes.regression-tests +++ b/examples/RegressionTopologyScenes.regression-tests @@ -2,6 +2,9 @@ # REGRESSION_TEST DOES NOT SUPPORT DASHES ("-") IN SCENE NAMES. # USE UNDERSCORES ("_") INSTEAD. +### References relative path ### +../applications/projects/Regression/references/examples + ### Topology scenes ### Component/Topology/Mapping/Tetra2TriangleTopologicalMapping.scn 30 1e-4 1 diff --git a/extlibs/CMakeLists.txt b/extlibs/CMakeLists.txt index 2b7e0658fb5..db919cd6b87 100644 --- a/extlibs/CMakeLists.txt +++ b/extlibs/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required(VERSION 3.12) -set(EXTLIBS_TARGETS - tinyxml -) ############# extlibs ############## @@ -13,15 +10,4 @@ set(STB_ROOT "${CMAKE_CURRENT_LIST_DIR}/stb" CACHE PATH "STB directory") # DiffLib set(DIFFLIB_ROOT "${CMAKE_CURRENT_LIST_DIR}/difflib" CACHE PATH "DiffLib directory") -# TinyXML -find_package(TinyXML QUIET) -if(NOT TinyXML_FOUND) - add_subdirectory(tinyxml tinyxml) -endif() - #################################### - -foreach(target ${EXTLIBS_TARGETS}) - set_target_properties(${target} PROPERTIES DEBUG_POSTFIX "_d") - set_target_properties(${target} PROPERTIES FOLDER "SofaExtlibs") -endforeach() diff --git a/extlibs/tinyxml/CMakeLists.txt b/extlibs/tinyxml/CMakeLists.txt deleted file mode 100644 index 5597e5f75e1..00000000000 --- a/extlibs/tinyxml/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.12) -project(tinyxml VERSION 2.6.2) - -set(SOURCE_FILES - tinystr.cpp - tinyxml.cpp - tinyxmlerror.cpp - tinyxmlparser.cpp -) - -set(HEADER_FILES - tinystr.h - tinyxml.h -) - - -add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${HEADER_FILES}) - -include(SofaMacros) -sofa_create_package_with_targets( - PACKAGE_NAME TinyXML - PACKAGE_VERSION ${PROJECT_VERSION} - TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES - INCLUDE_SOURCE_DIR "." - INCLUDE_INSTALL_DIR "extlibs/TinyXML" - ) diff --git a/extlibs/tinyxml/TinyXMLConfig.cmake.in b/extlibs/tinyxml/TinyXMLConfig.cmake.in deleted file mode 100644 index 9b3e6240b24..00000000000 --- a/extlibs/tinyxml/TinyXMLConfig.cmake.in +++ /dev/null @@ -1,10 +0,0 @@ -# CMake package configuration file for the TinyXML library - -@PACKAGE_GUARD@ -@PACKAGE_INIT@ - -if(NOT TARGET tinyxml) - include("${CMAKE_CURRENT_LIST_DIR}/TinyXMLTargets.cmake") -endif() - -check_required_components(tinyxml) diff --git a/extlibs/tinyxml/changes.txt b/extlibs/tinyxml/changes.txt deleted file mode 100644 index 15b51bd91f5..00000000000 --- a/extlibs/tinyxml/changes.txt +++ /dev/null @@ -1,299 +0,0 @@ -Changes in version 1.0.1: -- Fixed comment tags which were outputing as ' include. Thanks - to Steve Lhomme for that. - -Changes in version 2.0.0 BETA -- Made the ToXXX() casts safe if 'this' is null. - When "LoadFile" is called with a filename, the value will correctly get set. - Thanks to Brian Yoder. -- Fixed bug where isalpha() and isalnum() would get called with a negative value for - high ascii numbers. Thanks to Alesky Aksenov. -- Fixed some errors codes that were not getting set. -- Made methods "const" that were not. -- Added a switch to enable or disable the ignoring of white space. ( TiXmlDocument::SetIgnoreWhiteSpace() ) -- Greater standardization and code re-use in the parser. -- Added a stream out operator. -- Added a stream in operator. -- Entity support, of predefined entites. &#x entities are untouched by input or output. -- Improved text out formatting. -- Fixed ReplaceChild bug, thanks to Tao Chen. - -Changes in version 2.0.1 -- Fixed hanging on loading a 0 length file. Thanks to Jeff Scozzafava. -- Fixed crashing on InsertBeforeChild and InsertAfterChild. Also possibility of bad links being - created by same function. Thanks to Frank De prins. -- Added missing licence text. Thanks to Lars Willemsens. -- Added include, at the suggestion of Steve Walters. - -Changes in version 2.1.0 -- Yves Berquin brings us the STL switch. The forum on SourceForge, and various emails to - me, have long debated all out STL vs. no STL at all. And now you can have it both ways. - TinyXml will compile either way. - -Changes in version 2.1.1 -- Compilation warnings. - -Changes in version 2.1.2 -- Uneeded code is not compiled in the STL case. -- Changed headers so that STL can be turned on or off in tinyxml.h - -Changes in version 2.1.3 -- Fixed non-const reference in API; now uses a pointer. -- Copy constructor of TiXmlString not checking for assignment to self. -- Nimrod Cohen found a truly evil bug in the STL implementation that occurs - when a string is converted to a c_str and then assigned to self. Search for - STL_STRING_BUG for a full description. I'm asserting this is a Microsoft STL - bug, since &string and string.c_str() should never be the same. Nevertheless, - the code works around it. -- Urivan Saaib pointed out a compiler conflict, where the C headers define - the isblank macro, which was wiping out the TiXmlString::isblank() method. - The method was unused and has been removed. - -Changes in version 2.1.4 -- Reworked the entity code. Entities were not correctly surving round trip input and output. - Will now automatically create entities for high ascii in output. - -Changes in version 2.1.5 -- Bug fix by kylotan : infinite loop on some input (tinyxmlparser.cpp rev 1.27) -- Contributed by Ivica Aracic (bytelord) : 1 new VC++ project to compile versions as static libraries (tinyxml_lib.dsp), - and an example usage in xmltest.dsp - (Patch request ID 678605) -- A suggestion by Ronald Fenner Jr (dormlock) to add #include and for Apple's Project Builder - (Patch request ID 697642) -- A patch from ohommes that allows to parse correctly dots in element names and attribute names - (Patch request 602600 and kylotan 701728) -- A patch from hermitgeek ( James ) and wasteland for improper error reporting -- Reviewed by Lee, with the following changes: - - Got sick of fighting the STL/non-STL thing in the windows build. Broke - them out as seperate projects. - - I have too long not included the dsw. Added. - - TinyXmlText had a protected Print. Odd. - - Made LinkEndChild public, with docs and appropriate warnings. - - Updated the docs. - -2.2.0 -- Fixed an uninitialized pointer in the TiXmlAttributes -- Fixed STL compilation problem in MinGW (and gcc 3?) - thanks Brian Yoder for finding this one -- Fixed a syntax error in TiXmlDeclaration - thanks Brian Yoder -- Fletcher Dunn proposed and submitted new error handling that tracked the row and column. Lee - modified it to not have performance impact. -- General cleanup suggestions from Fletcher Dunn. -- In error handling, general errors will no longer clear the error state of specific ones. -- Fix error in documentation : comments starting with ">) has now - been fixed. - -2.5.2 -- Lieven, and others, pointed out a missing const-cast that upset the Open Watcom compiler. - Should now be fixed. -- ErrorRow and ErrorCol should have been const, and weren't. Fixed thanks to Dmitry Polutov. - -2.5.3 -- zloe_zlo identified a missing string specialization for QueryValueAttribute() [ 1695429 ]. Worked - on this bug, but not sure how to fix it in a safe, cross-compiler way. -- increased warning level to 4 and turned on detect 64 bit portability issues for VC2005. - May address [ 1677737 ] VS2005: /Wp64 warnings -- grosheck identified several problems with the Document copy. Many thanks for [ 1660367 ] -- Nice catch, and suggested fix, be Gilad Novik on the Printer dropping entities. - "[ 1600650 ] Bug when printing xml text" is now fixed. -- A subtle fix from Nicos Gollan in the tinystring initializer: - [ 1581449 ] Fix initialiser of TiXmlString::nullrep_ -- Great catch, although there isn't a submitter for the bug. [ 1475201 ] TinyXML parses entities in comments. - Comments should not, in fact, parse entities. Fixed the code path and added tests. -- We were not catching all the returns from ftell. Thanks to Bernard for catching that. - -2.5.4 -- A TiXMLDocument can't be a sub-node. Block this from happening in the 'replace'. Thanks Noam. -- [ 1714831 ] TiXmlBase::location is not copied by copy-ctors, fix reported and suggested by Nicola Civran. -- Fixed possible memory overrun in the comment reading code - thanks gcarlton77 - -2.5.5 -- Alex van der Wal spotted incorrect types (lf) being used in print and scan. robertnestor pointed out some problems with the simple solution. Types updated. -- Johannes Hillert pointed out some bug typos. -- Christian Mueller identified inconsistent error handling with Attributes. -- olivier barthelemy also reported a problem with double truncation, also related to the %lf issue. -- zaelsius came up with a great (and simple) suggestion to fix QueryValueAttribute truncating strings. -- added some null pointer checks suggested by hansenk -- Sami Visnen found a (rare) buffer overrun that could occur in parsing. -- vi tri filed a bug that led to a refactoring of the attribute setting mess (as well as adding a missing SetDoubleAttribute() ) -- removed TIXML_ERROR_OUT_OF_MEMORY. TinyXML does not systematically address OOO, and the notion it does is misleading. -- vanneto, keithmarshall, others all reported the warning from IsWhiteSpace() usage. Cleaned this up - many thanks to everyone who reported this one. -- tibur found a bug in end tag parsing - - -2.6.2 -- Switched over to VC 2010 -- Fixed up all the build issues arising from that. (Lots of latent build problems.) -- Removed the old, now unmaintained and likely not working, build files. -- Fixed some static analysis issues reported by orbitcowboy from cppcheck. -- Bayard 95 sent in analysis from a different analyzer - fixes applied from that as well. -- Tim Kosse sent a patch fixing an infinite loop. -- Ma Anguo identified a doc issue. -- Eddie Cohen identified a missing qualifier resulting in a compilation error on some systems. -- Fixed a line ending bug. (What year is this? Can we all agree on a format for text files? Please? ...oh well.) - diff --git a/extlibs/tinyxml/readme.txt b/extlibs/tinyxml/readme.txt deleted file mode 100644 index 89d9e8d38bf..00000000000 --- a/extlibs/tinyxml/readme.txt +++ /dev/null @@ -1,530 +0,0 @@ -/** @mainpage - -

TinyXML

- -TinyXML is a simple, small, C++ XML parser that can be easily -integrated into other programs. - -

What it does.

- -In brief, TinyXML parses an XML document, and builds from that a -Document Object Model (DOM) that can be read, modified, and saved. - -XML stands for "eXtensible Markup Language." It allows you to create -your own document markups. Where HTML does a very good job of marking -documents for browsers, XML allows you to define any kind of document -markup, for example a document that describes a "to do" list for an -organizer application. XML is a very structured and convenient format. -All those random file formats created to store application data can -all be replaced with XML. One parser for everything. - -The best place for the complete, correct, and quite frankly hard to -read spec is at -http://www.w3.org/TR/2004/REC-xml-20040204/. An intro to XML -(that I really like) can be found at -http://skew.org/xml/tutorial. - -There are different ways to access and interact with XML data. -TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed -into a C++ objects that can be browsed and manipulated, and then -written to disk or another output stream. You can also construct an XML document -from scratch with C++ objects and write this to disk or another output -stream. - -TinyXML is designed to be easy and fast to learn. It is two headers -and four cpp files. Simply add these to your project and off you go. -There is an example file - xmltest.cpp - to get you started. - -TinyXML is released under the ZLib license, -so you can use it in open source or commercial code. The details -of the license are at the top of every source file. - -TinyXML attempts to be a flexible parser, but with truly correct and -compliant XML output. TinyXML should compile on any reasonably C++ -compliant system. It does not rely on exceptions or RTTI. It can be -compiled with or without STL support. TinyXML fully supports -the UTF-8 encoding, and the first 64k character entities. - - -

What it doesn't do.

- -TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs -(eXtensible Stylesheet Language.) There are other parsers out there -(check out www.sourceforge.org, search for XML) that are much more fully -featured. But they are also much bigger, take longer to set up in -your project, have a higher learning curve, and often have a more -restrictive license. If you are working with browsers or have more -complete XML needs, TinyXML is not the parser for you. - -The following DTD syntax will not parse at this time in TinyXML: - -@verbatim - - ]> -@endverbatim - -because TinyXML sees this as a !DOCTYPE node with an illegally -embedded !ELEMENT node. This may be addressed in the future. - -

Tutorials.

- -For the impatient, here is a tutorial to get you going. A great way to get started, -but it is worth your time to read this (very short) manual completely. - -- @subpage tutorial0 - -

Code Status.

- -TinyXML is mature, tested code. It is very stable. If you find -bugs, please file a bug report on the sourceforge web site -(www.sourceforge.net/projects/tinyxml). We'll get them straightened -out as soon as possible. - -There are some areas of improvement; please check sourceforge if you are -interested in working on TinyXML. - -

Related Projects

- -TinyXML projects you may find useful! (Descriptions provided by the projects.) - -
    -
  • TinyXPath (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint - XPath syntax decoder, written in C++.
  • -
  • TinyXML++ (http://code.google.com/p/ticpp/). TinyXML++ is a completely new - interface to TinyXML that uses MANY of the C++ strengths. Templates, - exceptions, and much better error handling.
  • -
- -

Features

- -

Using STL

- -TinyXML can be compiled to use or not use STL. When using STL, TinyXML -uses the std::string class, and fully supports std::istream, std::ostream, -operator<<, and operator>>. Many API methods have both 'const char*' and -'const std::string&' forms. - -When STL support is compiled out, no STL files are included whatsoever. All -the string classes are implemented by TinyXML itself. API methods -all use the 'const char*' form for input. - -Use the compile time #define: - - TIXML_USE_STL - -to compile one version or the other. This can be passed by the compiler, -or set as the first line of "tinyxml.h". - -Note: If compiling the test code in Linux, setting the environment -variable TINYXML_USE_STL=YES/NO will control STL compilation. In the -Windows project file, STL and non STL targets are provided. In your project, -It's probably easiest to add the line "#define TIXML_USE_STL" as the first -line of tinyxml.h. - -

UTF-8

- -TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML -also supports "legacy mode" - the encoding used before UTF-8 support and -probably best described as "extended ascii". - -Normally, TinyXML will try to detect the correct encoding and use it. However, -by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML -can be forced to always use one encoding. - -TinyXML will assume Legacy Mode until one of the following occurs: -
    -
  1. If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf) - begin the file or data stream, TinyXML will read it as UTF-8.
  2. -
  3. If the declaration tag is read, and it has an encoding="UTF-8", then - TinyXML will read it as UTF-8.
  4. -
  5. If the declaration tag is read, and it has no encoding specified, then TinyXML will - read it as UTF-8.
  6. -
  7. If the declaration tag is read, and it has an encoding="something else", then TinyXML - will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's - not clear what that mode does exactly, but old content should keep working.
  8. -
  9. Until one of the above criteria is met, TinyXML runs in Legacy Mode.
  10. -
- -What happens if the encoding is incorrectly set or detected? TinyXML will try -to read and pass through text seen as improperly encoded. You may get some strange results or -mangled characters. You may want to force TinyXML to the correct mode. - -You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or -LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all -the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may -force it to TIXML_ENCODING_UTF8 with the same technique. - -For English users, using English XML, UTF-8 is the same as low-ASCII. You -don't need to be aware of UTF-8 or change your code in any way. You can think -of UTF-8 as a "superset" of ASCII. - -UTF-8 is not a double byte format - but it is a standard encoding of Unicode! -TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time. -It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding -of unicode. This is a source of confusion. - -For "high-ascii" languages - everything not English, pretty much - TinyXML can -handle all languages, at the same time, as long as the XML is encoded -in UTF-8. That can be a little tricky, older programs and operating systems -tend to use the "default" or "traditional" code page. Many apps (and almost all -modern ones) can output UTF-8, but older or stubborn (or just broken) ones -still output text in the default code page. - -For example, Japanese systems traditionally use SHIFT-JIS encoding. -Text encoded as SHIFT-JIS can not be read by TinyXML. -A good text editor can import SHIFT-JIS and then save as UTF-8. - -The Skew.org link does a great -job covering the encoding issue. - -The test file "utf8test.xml" is an XML containing English, Spanish, Russian, -and Simplified Chinese. (Hopefully they are translated correctly). The file -"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that -if you don't have the correct fonts (Simplified Chinese or Russian) on your -system, you won't see output that matches the GIF file even if you can parse -it correctly. Also note that (at least on my Windows machine) console output -is in a Western code page, so that Print() or printf() cannot correctly display -the file. This is not a bug in TinyXML - just an OS issue. No data is lost or -destroyed by TinyXML. The console just doesn't render UTF-8. - - -

Entities

-TinyXML recognizes the pre-defined "character entities", meaning special -characters. Namely: - -@verbatim - & & - < < - > > - " " - ' ' -@endverbatim - -These are recognized when the XML document is read, and translated to there -UTF-8 equivalents. For instance, text with the XML of: - -@verbatim - Far & Away -@endverbatim - -will have the Value() of "Far & Away" when queried from the TiXmlText object, -and will be written back to the XML stream/file as an ampersand. Older versions -of TinyXML "preserved" character entities, but the newer versions will translate -them into characters. - -Additionally, any character can be specified by its Unicode code point: -The syntax " " or " " are both to the non-breaking space characher. - -

Printing

-TinyXML can print output in several different ways that all have strengths and limitations. - -- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout. - - "Pretty prints", but you don't have control over printing options. - - The output is streamed directly to the FILE object, so there is no memory overhead - in the TinyXML code. - - used by Print() and SaveFile() - -- operator<<. Output to a c++ stream. - - Integrates with standart C++ iostreams. - - Outputs in "network printing" mode without line breaks. Good for network transmission - and moving XML between C++ objects, but hard for a human to read. - -- TiXmlPrinter. Output to a std::string or memory buffer. - - API is less concise - - Future printing options will be put here. - - Printing may change slightly in future versions as it is refined and expanded. - -

Streams

-With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well -as C (FILE*) streams. There are some differences that you may need to be aware of. - -C style output: - - based on FILE* - - the Print() and SaveFile() methods - - Generates formatted output, with plenty of white space, intended to be as - human-readable as possible. They are very fast, and tolerant of ill formed - XML documents. For example, an XML document that contains 2 root elements - and 2 declarations, will still print. - -C style input: - - based on FILE* - - the Parse() and LoadFile() methods - - A fast, tolerant read. Use whenever you don't need the C++ streams. - -C++ style output: - - based on std::ostream - - operator<< - - Generates condensed output, intended for network transmission rather than - readability. Depending on your system's implementation of the ostream class, - these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML: - a document should contain the correct one root element. Additional root level - elements will not be streamed out. - -C++ style input: - - based on std::istream - - operator>> - - Reads XML from a stream, making it useful for network transmission. The tricky - part is knowing when the XML document is complete, since there will almost - certainly be other data in the stream. TinyXML will assume the XML data is - complete after it reads the root element. Put another way, documents that - are ill-constructed with more than one root element will not read correctly. - Also note that operator>> is somewhat slower than Parse, due to both - implementation of the STL and limitations of TinyXML. - -

White space

-The world simply does not agree on whether white space should be kept, or condensed. -For example, pretend the '_' is a space, and look at "Hello____world". HTML, and -at least some XML parsers, will interpret this as "Hello_world". They condense white -space. Some XML parsers do not, and will leave it as "Hello____world". (Remember -to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become -Hello___world. - -It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the -first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior. -The default is to condense white space. - -If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool ) -before making any calls to Parse XML data, and I don't recommend changing it after -it has been set. - - -

Handles

- -Where browsing an XML document in a robust way, it is important to check -for null returns from method calls. An error safe implementation can -generate a lot of code like: - -@verbatim -TiXmlElement* root = document.FirstChildElement( "Document" ); -if ( root ) -{ - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. -@endverbatim - -Handles have been introduced to clean this up. Using the TiXmlHandle class, -the previous code reduces to: - -@verbatim -TiXmlHandle docHandle( &document ); -TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); -if ( child2 ) -{ - // do something useful -@endverbatim - -Which is much easier to deal with. See TiXmlHandle for more information. - - -

Row and Column tracking

-Being able to track nodes and attributes back to their origin location -in source files can be very important for some applications. Additionally, -knowing where parsing errors occured in the original source can be very -time saving. - -TinyXML can tracks the row and column origin of all nodes and attributes -in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return -the origin of the node in the source text. The correct tabs can be -configured in TiXmlDocument::SetTabSize(). - - -

Using and Installing

- -To Compile and Run xmltest: - -A Linux Makefile and a Windows Visual C++ .dsw file is provided. -Simply compile and run. It will write the file demotest.xml to your -disk and generate output on the screen. It also tests walking the -DOM by printing out the number of nodes found using different -techniques. - -The Linux makefile is very generic and runs on many systems - it -is currently tested on mingw and -MacOSX. You do not need to run 'make depend'. The dependecies have been -hard coded. - -

Windows project file for VC6

-
    -
  • tinyxml: tinyxml library, non-STL
  • -
  • tinyxmlSTL: tinyxml library, STL
  • -
  • tinyXmlTest: test app, non-STL
  • -
  • tinyXmlTestSTL: test app, STL
  • -
- -

Makefile

-At the top of the makefile you can set: - -PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in -the makefile. - -In the tinyxml directory, type "make clean" then "make". The executable -file 'xmltest' will be created. - - - -

To Use in an Application:

- -Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your -project or make file. That's it! It should compile on any reasonably -compliant C++ system. You do not need to enable exceptions or -RTTI for TinyXML. - - -

How TinyXML works.

- -An example is probably the best way to go. Take: -@verbatim - - - - Go to the Toy store! - Do bills - -@endverbatim - -Its not much of a To Do list, but it will do. To read this file -(say "demo.xml") you would create a document, and parse it in: -@verbatim - TiXmlDocument doc( "demo.xml" ); - doc.LoadFile(); -@endverbatim - -And its ready to go. Now lets look at some lines and how they -relate to the DOM. - -@verbatim - -@endverbatim - - The first line is a declaration, and gets turned into the - TiXmlDeclaration class. It will be the first child of the - document node. - - This is the only directive/special tag parsed by TinyXML. - Generally directive tags are stored in TiXmlUnknown so the - commands wont be lost when it is saved back to disk. - -@verbatim - -@endverbatim - - A comment. Will become a TiXmlComment object. - -@verbatim - -@endverbatim - - The "ToDo" tag defines a TiXmlElement object. This one does not have - any attributes, but does contain 2 other elements. - -@verbatim - -@endverbatim - - Creates another TiXmlElement which is a child of the "ToDo" element. - This element has 1 attribute, with the name "priority" and the value - "1". - -@verbatim -Go to the -@endverbatim - - A TiXmlText. This is a leaf node and cannot contain other nodes. - It is a child of the "Item" TiXmlElement. - -@verbatim - -@endverbatim - - - Another TiXmlElement, this one a child of the "Item" element. - -Etc. - -Looking at the entire object tree, you end up with: -@verbatim -TiXmlDocument "demo.xml" - TiXmlDeclaration "version='1.0'" "standalone=no" - TiXmlComment " Our to do list data" - TiXmlElement "ToDo" - TiXmlElement "Item" Attribtutes: priority = 1 - TiXmlText "Go to the " - TiXmlElement "bold" - TiXmlText "Toy store!" - TiXmlElement "Item" Attributes: priority=2 - TiXmlText "Do bills" -@endverbatim - -

Documentation

- -The documentation is build with Doxygen, using the 'dox' -configuration file. - -

License

- -TinyXML is released under the zlib license: - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. - -

References

- -The World Wide Web Consortium is the definitive standard body for -XML, and their web pages contain huge amounts of information. - -The definitive spec: -http://www.w3.org/TR/2004/REC-xml-20040204/ - -I also recommend "XML Pocket Reference" by Robert Eckstein and published by -OReilly...the book that got the whole thing started. - -

Contributors, Contacts, and a Brief History

- -Thanks very much to everyone who sends suggestions, bugs, ideas, and -encouragement. It all helps, and makes this project fun. A special thanks -to the contributors on the web pages that keep it lively. - -So many people have sent in bugs and ideas, that rather than list here -we try to give credit due in the "changes.txt" file. - -TinyXML was originally written by Lee Thomason. (Often the "I" still -in the documentation.) Lee reviews changes and releases new versions, -with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community. - -We appreciate your suggestions, and would love to know if you -use TinyXML. Hopefully you will enjoy it and find it useful. -Please post questions, comments, file bugs, or contact us at: - -www.sourceforge.net/projects/tinyxml - -Lee Thomason, Yves Berquin, Andrew Ellerton -*/ diff --git a/extlibs/tinyxml/tinystr.cpp b/extlibs/tinyxml/tinystr.cpp deleted file mode 100644 index 06657682051..00000000000 --- a/extlibs/tinyxml/tinystr.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/extlibs/tinyxml/tinystr.h b/extlibs/tinyxml/tinystr.h deleted file mode 100644 index 89cca334156..00000000000 --- a/extlibs/tinyxml/tinystr.h +++ /dev/null @@ -1,305 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/extlibs/tinyxml/tinyxml.cpp b/extlibs/tinyxml/tinyxml.cpp deleted file mode 100644 index f90860631ab..00000000000 --- a/extlibs/tinyxml/tinyxml.cpp +++ /dev/null @@ -1,1885 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - -FILE* TiXmlFOpen( const char* filename, const char* mode ); - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; - target->location = location; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - delete node; - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( !replaceThis ) - return 0; - - if ( replaceThis->parent != this ) - return 0; - - if ( withThis.ToDocument() ) { - // A document can never be a child. Thanks to Noam. - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( !removeThis ) { - return false; - } - - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); - return *this; -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( attrib ) - return &attrib->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} - - -int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int ival = 0; - int result = node->QueryIntValue( &ival ); - *value = (unsigned)ival; - return result; -} - - -int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int result = TIXML_WRONG_TYPE; - if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = true; - result = TIXML_SUCCESS; - } - else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = false; - result = TIXML_SUCCESS; - } - return result; -} - - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} -#endif - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); - if ( attrib ) { - attrib->SetValue( cvalue ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); - if ( attrib ) { - attrib->SetValue( _value ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Process the buffer in place to normalize new lines. (See comment above.) - // Copies from the 'p' to 'q' pointer, where p can advance faster if - // a newline-carriage return is hit. - // - // Wikipedia: - // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or - // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... - // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others - // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS - // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 - - const char* p = buf; // the read head - char* q = buf; // the write head - const char CR = 0x0d; - const char LF = 0x0a; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - assert( q <= (buf+length) ); - assert( q <= p ); - - if ( *p == CR ) { - *q++ = LF; - p++; - if ( *p == LF ) { // check for CR+LF (and skip LF) - p++; - } - } - else { - *q++ = *p++; - } - } - assert( q <= (buf+length) ); - *q = 0; - - Parse( buf, 0, encoding ); - - delete [] buf; - return !Error(); -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); - #else - sprintf (buf, "%g", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); - return *this; -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - copy.CopyTo( this ); -} - - -TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} -#endif - - -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} - - -#ifdef TIXML_USE_STL -EXPORT std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -EXPORT std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -EXPORT std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} diff --git a/extlibs/tinyxml/tinyxml.h b/extlibs/tinyxml/tinyxml.h deleted file mode 100644 index 555d8aca6b4..00000000000 --- a/extlibs/tinyxml/tinyxml.h +++ /dev/null @@ -1,1808 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#ifndef TIXML_USE_STL - #define TIXML_USE_STL -#endif - -#if defined (_WIN32) - #if defined(tinyxml_EXPORTS) - #define EXPORT __declspec(dllexport) - #else - #define EXPORT __declspec(dllimport) - #endif -#else - #define EXPORT -#endif - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1900 ) - // Microsoft visual studio, version 2015 and higher. - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif - - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 6; -const int TIXML_PATCH_VERSION = 2; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class EXPORT TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknown node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class EXPORT TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class EXPORT TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend EXPORT std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend EXPORT std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend EXPORT std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, - TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class EXPORT TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class EXPORT TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); - -# ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); -# endif - - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class EXPORT TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - TiXmlElement& operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). - int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; - /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). - Note that '1', 'true', or 'yes' are considered true, while '0', 'false' - and 'no' are considered false. - */ - int QueryBoolAttribute( const char* name, bool* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class EXPORT TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - TiXmlComment& operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class EXPORT TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class EXPORT TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class EXPORT TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class EXPORT TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - TiXmlDocument& operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class EXPORT TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class EXPORT TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i -#include - -#include "tinyxml.h" - - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() const { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p && *p ) - p += strlen( endTag ); - return ( p && *p ) ? p : 0; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p && *p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p && *p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i