Commit 58ad9e76 authored by ledig's avatar ledig
Browse files

[FIX] fixtures, tests and biosig target work in win now

parent 3f7f2afc
......@@ -221,7 +221,7 @@ ADD_CUSTOM_TARGET( tags DEPENDS ctags DEPENDS cscope )
FILE( GLOB_RECURSE STYLE_CPP ${PROJECT_SOURCE_DIR}/*.cpp )
FILE( GLOB_RECURSE STYLE_H ${PROJECT_SOURCE_DIR}/*.h )
# Set dirs to exclude from stylecheck
SET( EXCLUDE_DIRS "/dataHandler/io/nifti/;/dataHandler/io/biosig/;/dataHandler/io/biosig/XMLParser/;/dataHandler/io/libeep/avr/;/dataHandler/io/libeep/cnt/;/dataHandler/io/libeep/eep/;/common/platformDependent/visualStudio/" )
SET( EXCLUDE_DIRS "/dataHandler/io/nifti/;/dataHandler/io/biosig/;/dataHandler/io/biosigWin/;/dataHandler/io/biosig/XMLParser/;/dataHandler/io/biosigWin/XMLParser/;/dataHandler/io/libeep/avr/;/dataHandler/io/libeep/cnt/;/dataHandler/io/libeep/eep/;/common/platformDependent/visualStudio/" )
FOREACH( dirname ${EXCLUDE_DIRS} )
FILE( GLOB EXCLUDE_H ${PROJECT_SOURCE_DIR}${dirname}*.h )
FILE( GLOB EXCLUDE_CPP ${PROJECT_SOURCE_DIR}${dirname}*.cpp )
......@@ -283,6 +283,14 @@ IF( NOT CMAKE_GENERATOR MATCHES "Visual Studio" )
COMMAND cp -rf ${PROJECT_SOURCE_DIR}/modules/marchingCubes/test/fixtures ${PROJECT_BINARY_DIR}/modules/marchingCubes
COMMENT "Copy fixtures to the right place."
)
ELSE()
ADD_CUSTOM_TARGET( fixtures
ALL
COMMAND ${CMAKE_COMMAND} -D OW_SOURCE_DIR:STRING=${PROJECT_SOURCE_DIR} -P ${PROJECT_SOURCE_DIR}/../tools/CMakeModules/FixturesWin.cmake
COMMENT "Copy fixtures to the right place."
)
ENDIF()
#-------------------------------------------------------------------------------------------------------------
......
......@@ -228,8 +228,13 @@ public:
wmath::WLine expected;
for( size_t i = 0; i < 3; ++i )
{
#ifndef _MSC_VER
line.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
expected.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
#else
line.push_back( WPosition( i, std::pow( static_cast< double >( -1 ), static_cast< int >( i % 2 ) ), 0 ) );
expected.push_back( WPosition( i, std::pow( static_cast< double >( -1 ), static_cast< int >( i % 2 ) ), 0 ) );
#endif
expected.push_back( WPosition( i + 0.5, 0, 0 ) );
}
expected.pop_back();
......@@ -248,17 +253,29 @@ public:
wmath::WLine expected;
for( size_t i = 0; i < 100; ++i )
{
#ifndef _MSC_VER
line.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
expected.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
expected.push_back( WPosition( i + 0.25, std::pow( -1, i % 2 ) * 0.5, 0 ) );
expected.push_back( WPosition( i + 0.5, 0, 0 ) );
expected.push_back( WPosition( i + 0.75, std::pow( -1, ( i + 1 ) % 2 ) * 0.5, 0 ) );
#else
line.push_back( WPosition( i, std::pow( static_cast< double >( -1 ), static_cast< int >( i % 2 ) ), 0 ) );
expected.push_back( WPosition( i, std::pow( static_cast< double >( -1 ), static_cast< int >( i % 2 ) ), 0 ) );
expected.push_back( WPosition( i + 0.25, std::pow( static_cast< double >( -1 ), static_cast< int >( i % 2 ) ) * 0.5, 0 ) );
expected.push_back( WPosition( i + 0.5, 0, 0 ) );
expected.push_back( WPosition( i + 0.75, std::pow( static_cast< double >( -1 ), static_cast< int >( ( i + 1 ) % 2 ) ) * 0.5, 0 ) );
#endif
}
expected.pop_back();
expected.pop_back();
expected.pop_back();
line.resample( 4 * 99 + 1 );
#ifndef _MSC_VER
assert_equals_delta( expected, line, 1.0e-10 * std::sqrt( 5 ) / 4 );
#else
assert_equals_delta( expected, line, 1.0e-10 * std::sqrt( static_cast< double >( 5 ) ) / 4 );
#endif
}
/**
......
......@@ -44,7 +44,7 @@ public:
void testInstantiation( void )
{
TS_ASSERT_THROWS_NOTHING( WException e() );
TS_ASSERT_THROWS_NOTHING( WException e( "Some message" ) );
TS_ASSERT_THROWS_NOTHING( WException e( std::string( "Some message" ) ) );
}
/**
......@@ -52,7 +52,7 @@ public:
*/
void testGetMessage( void )
{
WException e( "Dummy exception" );
WException e( std::string( "Dummy exception" ) );
e.m_trace.push_back( "first" );
e.m_trace.push_back( "second" );
std::string expected = "Dummy exception\n\ntrace: first\ntrace: second";
......
......@@ -33,7 +33,9 @@
#ifdef CXXTEST_RUNNING
namespace CxxTest
{
#ifndef _MSC_VER
CXXTEST_TEMPLATE_INSTANTIATION
#endif
/**
* Enables better UnitTest OutPut if something fails with a mixin vector, so
* you see immedeatly what is failing.
......
......@@ -9,15 +9,15 @@ FILE( GLOB DATAHANDLER_DATASTRUCTURES_SRC "datastructures/*.cpp" "datastructures
FILE( GLOB DATAHANDLER_EXCEPTIONS_SRC "exceptions/*.cpp" "exceptions/*.h" )
FILE( GLOB DATAHANDLER_IO_SRC "io/*.cpp" "io/*.h" ) # former WLoader
IF( CMAKE_GENERATOR MATCHES "Visual Studio" )
FILE( GLOB EXCLUDE_biosig "io/*Biosig.cpp" "io/*Biosig.h" )
LIST( REMOVE_ITEM DATAHANDLER_IO_SRC ${EXCLUDE_biosig} )
ADD_LIBRARY( dataHandler ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} ${DATAHANDLER_DATASTRUCTURES_SRC} )
TARGET_LINK_LIBRARIES( dataHandler common ${Boost_LIBRARIES} niftiio libeep ${OPENSCENEGRAPH_LIBRARIES})
ELSE()
#IF( CMAKE_GENERATOR MATCHES "Visual Studio" )
# FILE( GLOB EXCLUDE_biosig "io/*Biosig.cpp" "io/*Biosig.h" )
# LIST( REMOVE_ITEM DATAHANDLER_IO_SRC ${EXCLUDE_biosig} )
# ADD_LIBRARY( dataHandler ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} ${DATAHANDLER_DATASTRUCTURES_SRC} )
# TARGET_LINK_LIBRARIES( dataHandler common ${Boost_LIBRARIES} niftiio libeep ${OPENSCENEGRAPH_LIBRARIES})
#ELSE()
ADD_LIBRARY( dataHandler ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} ${DATAHANDLER_DATASTRUCTURES_SRC} )
TARGET_LINK_LIBRARIES( dataHandler common ${Boost_LIBRARIES} niftiio biosig libeep ${OPENSCENEGRAPH_LIBRARIES})
ENDIF()
#ENDIF()
# Unit tests
IF( OW_COMPILE_TESTS )
CXXTEST_ADD_TESTS_FROM_LIST( "${DATAHANDLER_SRC}" "dataHandler" "WDataTexture3D.cpp" "WDataHandlerEnums.cpp" )
......
......@@ -89,11 +89,20 @@ public:
{
wmath::WFiber expected;
expected.push_back( wmath::WPosition( 0, 1, 0 ) );
#ifndef _MSC_VER
expected.push_back( wmath::WPosition( ( ( 9.0 - 3 * std::sqrt( 2 ) ) / 4.0 - 1.0 ) / 2.0 + 1, 1.5, 0 ) );
expected.push_back( wmath::WPosition( ( ( 9.0 - 3 * std::sqrt( 2 ) ) / 4.0 + ( 5 + std::sqrt( 2 ) ) / 4.0 - 2.0 ) / 2.0 + 2, 1.5, 0 ) );
expected.push_back( wmath::WPosition( ( ( 9.0 - 3 * std::sqrt( 2 ) ) / 4.0 + 2 * ( 5 + std::sqrt( 2 ) ) / 4.0 - 3.0 ) / 2.0 + 3, 1.5, 0 ) );
expected.push_back( wmath::WPosition( 5, 1.5, 0 ) );
#else
expected.push_back( wmath::WPosition( ( ( 9.0 - 3 * std::sqrt( static_cast< double >( 2 ) ) ) / 4.0 - 1.0 ) / 2.0 + 1,
1.5, 0 ) );
expected.push_back( wmath::WPosition( ( ( 9.0 - 3 * std::sqrt( static_cast< double >( 2 ) ) ) / 4.0
+ ( 5 + std::sqrt( static_cast< double >( 2 ) ) ) / 4.0 - 2.0 ) / 2.0 + 2, 1.5, 0 ) );
expected.push_back( wmath::WPosition( ( ( 9.0 - 3 * std::sqrt( static_cast< double >( 2 ) ) ) / 4.0
+ 2 * ( 5 + std::sqrt( static_cast< double >( 2 ) ) ) / 4.0 - 3.0 ) / 2.0 + 3, 1.5, 0 ) );
expected.push_back( wmath::WPosition( 5, 1.5, 0 ) );
#endif
m_cluster->generateCenterLine();
assert_equals_delta( *m_cluster->getCenterLine(), expected, wlimits::FLT_EPS ); // decrese precision since it fails occasionally
std::cout << *m_cluster->getDataSetReference() << std::endl;
......
ADD_SUBDIRECTORY( nifti )
IF( NOT CMAKE_GENERATOR MATCHES "Visual Studio" )
ADD_SUBDIRECTORY( biosig )
ELSE ()
ADD_SUBDIRECTORY( biosigWin )
ENDIF()
ADD_SUBDIRECTORY( libeep )
......
......@@ -73,28 +73,32 @@ boost::shared_ptr< WDataSet > WLoaderBiosig::load()
{
assert( m_fileName.substr( m_fileName.size() - 4 ) == ".edf" && "We expect only EDF so far." );
#ifdef _MSC_VER
hd = biosig_sopen( m_fileName.c_str(), "r", 0 );
#else
hd = sopen( m_fileName.c_str(), "r", 0 );
#endif
switch( B4C_ERRNUM )
{
case B4C_NO_ERROR:
break;
case B4C_FORMAT_UNKNOWN:
throw WException( "BIOSIG: Unknown format!" );
throw WException( std::string( "BIOSIG: Unknown format!" ) );
break;
case B4C_FORMAT_UNSUPPORTED:
throw WException( "BIOSIG: Unsupported format!" );
throw WException( std::string( "BIOSIG: Unsupported format!" ) );
break;
case B4C_UNSPECIFIC_ERROR:
throw WException( "BIOSIG: Unspecific error occured!" );
throw WException( std::string( "BIOSIG: Unspecific error occured!" ) );
break;
default:
throw WException( "BIOSIG: An error occured! The type is not known to OpenWalnut biosig loader." );
throw WException( std::string( "BIOSIG: An error occured! The type is not known to OpenWalnut biosig loader." ) );
}
if( hd->NRec == -1 )
{
throw WException( "Unknown number of blocks in file loaded by biosig!" );
throw WException( std::string( "Unknown number of blocks in file loaded by biosig!" ) );
}
......@@ -110,7 +114,11 @@ boost::shared_ptr< WDataSet > WLoaderBiosig::load()
biosig_data_type* DATA = 0;
size_t LEN = 1;
#ifdef _MSC_VER
size_t dummy = biosig_sread( DATA, 0, LEN, hd );
#else
size_t dummy = sread( DATA, 0, LEN, hd );
#endif
wlog::info( "BIOSIG" ) << " DataSize " << dummy;
size_t nbSamples = LEN*hd->SPR*hd->NS;
m_rows = hd->data.size[0];
......@@ -136,7 +144,7 @@ boost::shared_ptr< WDataSet > WLoaderBiosig::load()
WEEGElectrodeLibrary lib = extractElectrodePositions();
if( hd->NS != lib.size() )
throw WDHException( "Contents of edf and elc files are not compatible: Different number of channels." );
throw WDHException( std::string( "Contents of edf and elc files are not compatible: Different number of channels." ) );
WEEGChannelLabels labels( hd->NS );
for( unsigned int i = 0; i < hd->NS; ++i )
......
......@@ -31,7 +31,11 @@
#include <boost/shared_ptr.hpp>
#include "WLoaderEEG.h"
#ifdef _MSC_VER
#include "biosigWin/biosig.h"
#else
#include "biosig/biosig.h"
#endif
/**
......
# Adapted flags for this directory to inhibit all warnings.
# There is a good reason for this: We do not want to debug
# third party software!
IF( CMAKE_GENERATOR MATCHES "Visual Studio" )
SET( CMAKE_CXX_FLAGS "/EHsc /DWIN32")
SET( CMAKE_C_FLAGS "/TC /DWIN32")
ELSE()
SET( CMAKE_CXX_FLAGS "-pedantic -Wno-write-strings -Wno-deprecated -Wformat=0")
SET( CMAKE_C_FLAGS "-w")
ENDIF()
FILE( GLOB BIOSIG_SRC "*.c" "*.cpp" "*.h" "XMLParser/*.cpp" "XMLParser/*.h" )
ADD_LIBRARY( biosig ${BIOSIG_SRC} )
IF( CMAKE_HOST_SYSTEM MATCHES Windows )
TARGET_LINK_LIBRARIES( biosig ws2_32 )
ENDIF()
This diff is collapsed.
This file contains the original README file as distributed with "BioSig for C/C++". The contents of the original file starts at "Introduction". The license for the code in this directory can be found in the file LICENSE. The source code and documentation in this directory are adapted from "BioSig for C/C++" (http://biosig.sf.net/). See the file VERSION for more information. The changes were made by Alexander Wiebel. Parts of the text of the old README file do not apply to the changed code anymore.
Introduction:
---------------
The aim of this repository is providing a C/C++ software library for biomedical signal processing.
This library is called "BioSig for C/C++" and is complementary to "BioSig for Octave and Matlab".
BioSig4C++ provides several tools:
(1) "libbiosig.a" provides a library for accessing different dataformats.
Recommended: zlib (http://zlib.net/) and GNU Scientific Library (GSL)
The supported data formats are listed here:
http://hci.tugraz.at/schloegl/biosig/TESTED
(2) "save2gdf" is a converter between different file formats,
including but not limited to SCP-ECG(EN1064), HL7aECG (FDA-XML), GDF, EDF, BDF, CWFB.
save2gdf can be also used to upload or retrieve data from a bscs server.
(3) "mexSLOAD" is a MEX-interface for Octave and Matlab
Requirement: Matlab OR Octave (v2.9 or higher) with octave-headers
For Matlab, precompiled binaries are available in matlab/mexSLOAD.mex*
(4) "_biosig.so" is an interface to python.
Requirement: python, python-dev, python-scipy, swig (http://www.swig.org/)
(5) SigViewer
Requirement: qmake, Qt4
(6) Precompiled binaries for Win32
win32/save2gdf.exe binary converter
win32/libbiosig.a library for MinGW 4.x (might work with other compilers too)
The internal data structure resemble the header structure similar to
http://biosig.cvs.sourceforge.net/biosig/biosig/doc/header.txt
and is defined in
http://biosig.cvs.sourceforge.net/biosig/biosig4c++/biosig.h
(see HDRTYPE and CHANNEL_TYPE)
Encoding of Event/Markers/Annotations is available here:
http://hci.tugraz.at/schloegl/matlab/eeg/EventCodes.html
The latest list of supported data formats is available here:
http://hci.tugraz.at/schloegl/biosig/TESTED
File(s):
-------------
README this file
biosig.h definition of external biosig interface
biosig-dev.h definition of internal functions
biosig.c SOPEN, SREAD, SWRITE, SEOF, SCLOSE functions
save2gdf.c converter between various file formats.
physicalunit.c en-/decodes physical units according to ISO/DIS 11073-10101:2003
mexSLOAD.cpp is a MEX-File for loading data in Octave and Matab.
t210/* reading SCP,FAMOS file format
t220/* writing SCP file format
t230/* support of HL7aECG file format
test0/* scripts and functions for testing
Makefile script for compiling and testing under GNU/Linux
Makefile.win32 script for compiling and testing on win32 using mingw
win32/* executables for Windows
Compilation:
-------------
# Linux
You need g++(>4.0), make and zlib. (If you do not have zlib, do not define WITH_ZLIB).
Running make compiles the converter.
make # makes the file format converter
make save2gdf # makes the file format converter
make win32 # makes the file format converter for Win32
make physicalunits # makes the en/decoder for physical units
make libbiosig.a # makes a static library
make mex4o # makes mexSLOAD for Octave (requires Octave-headers2.9 or higher)
make mex4m # makes mexSLOAD for Matlab (path_to_mex need to be defined in Makefile)
make sigviewer # recompiles SigViewer (requires qmake and Qt, and the sources of sigviewer must be in ../sigviewer)
make biosig4python # compiles the BioSig interface for Python (requires SWIG and Python)
make all # all of the above
make testscp
make testhl7
make test # tests HL7<->SCP, SCP<->GDF, GDF<->HL7 converters
make test6 # tests bidirectional conversion between 6 differerent data formats
# MinGW Crosscompiler on Linux for Windows
Currently, only the file converter save2gdf is supported.
- install mingw32 mingw32-binutils mingw32-runtime
- run the command
make win32
# Windows + MinGW
Currently, only the file converter save2gdf is supported.
- You need MinGW with g++ and make.
- run the make command
make -f Makefile.win32
# Windows + MinGW + Matlab
do the steps in "Windows+MinGW"
install and configure gnumex (from http://gnumex.sf.net)
make libbiosig.a
start matlab
>> gnumex % configure mingw for mex
>> mex mexSLOAD.cpp libbiosig \mingw\lib\libws2_32.a
# Windows + Cygwin
Currently, only the file converter save2gdf is supported.
- install Cygwin
- within Cygwin install g++, zlib, and make
- run the make command
make save2gdf
# MSVC - Microsoft Visual C++
MSVC is currently not supported. The main incompatibility is
the use of the typeof() operator. Since typeof() is very convinient,
I'm not planning to change this. However, you can easy replace
any typeof()-operator by the appropriate type, and the code
should compile on MSVC as well.
# Other platforms (Windows+MSVC, MacOSX, Solaris, etc. )
Not tested (yet). Let me know about successful compilations,
or tell me what changes are needed.
Installation:
-------------
run as root
make
make install # installs save2gdf, save2scp, save2aecg,
make install_octave # installs mexSLOAD.mex in /usr/local/share/octave/site-m/
make install_sigviewer # installs sigviewer
Execution:
----------
# if test.gdf exists, some header information is displayed
save2gdf test.gdf
# help and usage information
save2gdf -h
# converts a data file into a GDF format (destination
save2gdf PFE103.scp t5.gdf
# converts a data file into a SCP format (destination
save2scp t5.gdf t5.scp
save2gdf -f=SCP t5.gdf t5.scp
# converts a data file into a HL7aECG format (destination
save2aecg t5.gdf t5.hl7
save2gdf -f=HL7aECG t5.gdf t5.hl7
# load matlab into octave or matlab
start octave or matlab
addpath path_to_mexSLOAD.mex
[data,HDR] = mexSLOAD(filename); % loads data and header information
Open Issue(s) of the SCP-ECG <-> HL7aECG converter:
---------------------------------------------------
The following fields of SCP-ECG are not converted to HL7.
= Mandatory fields (prEN1064:2007 p.18, chp 5.4.3.1) not propagated to HL7:
- time zone information, (tag34, section 1)
- "ID of acquiring device" (tag14, section 1)
= "Highly recommended" fields (prEN1064:2007 p.18, chp 5.4.3.1) not propagated to HL7:
- "ID of analysing device", Patient first name,
= Other fields of the SCP-ECG standard,
- section 1: blood pressure, medication, etc
- section 4 (QRS location), 7 (global measurements), 8-11 (interpretative statements)
The following fields of HL7aECG are not converted to SCP-ECG.
- study, treatment group, clinical trial, clinical trial protocol, trial sponsor, investigator etc.
Development & Testing:
----------------------
There are several testing functions included.
The following commands test the converter and should finish without errors.
make test
make testhl7
make testscp
make test6
The Octave/Matlab script
test0/test01.m
tests whether the various data formats give the same results
or whether some conversion error has been included.
More information is available at http://biosig.sf.net/
If you have any questions you can also contact the mailinglist
https://lists.sourceforge.net/lists/listinfo/biosig-general
$Id: README,v 1.26 2009/02/27 09:18:33 schloegl Exp $
Copyright (C) 2005,2006,2007,2008,2009 Alois Schloegl <a.schloegl@ieee.org>
This function is part of the "BioSig for C/C++" repository
(BioSig4C++) at http://biosig.sf.net/
Thanks to the contributors:
Thomas Brunner
Makefile, testing
Eugenio Cervesato
reading of SCP-ECG format
Franco Chiarugi
writing of SCP-ECG format
Elias Apostolopoulos
read/write support of HL7aECG format
Luca Citi
made the interface to python working
Thsi version was adapted for OpenWalnut by Alexander Wiebel. The basis for this version is the one specified below.
# BIOSIG http://biosig.sf.net/
# Version: BioSig4C++ 0.84
# Date: 2009-06-18
#include <string>
template <typename TContainer>
void stringtokenizer(TContainer& container, const std::string& in, const char* const delimiters = " \t\n"){
const std::string::size_type len = in.length();
std::string::size_type i = 0;
while (i < len){
i = in.find_first_not_of(delimiters, i);
if (i == std::string::npos)
return;
std::string::size_type j = in.find_first_of(delimiters, i);
if (j == std::string::npos){
container.push_back(in.substr(i));
return;
}
else
container.push_back(in.substr(i, j-i));
i = j + 1;
}
}
/*
www.sourceforge.net/projects/tinyxml
Original file by Yves Berquin.
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.
*/
/*
* THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
*/
#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<TiXmlString::size_type>( 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<TiXmlString::size_type>( strlen(a) );
tmp.reserve(a_len + b.length());
tmp.append(a, a_len);