#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
//-------------------------------------------------------------------------
// Example (1) boost::split
//
// in this exmaple , demonstrate use of
//
// - std::stringstream
// - boost::split
// - boost::lexical_cast
// - for_each
// - boost::trim
//-------------------------------------------------------------------------
// This struct is used in the for_each call of the split example below
struct Trim { void operator()( std::string &s) { boost::trim(s); } };
// create std::string from std::string, dobule, int and bool
std::stringstream strm;
strm << " ABCDE" << ", " << 100.0 << ", " << 75 << "," << false ;
std::string line = strm.str(); // line = " ABCDE , 100.0, 75,false"
// split the line a into sections using "," as the delimiter, store result into a string vector
std::vector<std::string> sv;
boost::split( sv , line , boost::is_any_of( "," ) );
// trim any leading and trailing blanks from each element parsed, note the struct Trim passed to for_each()
for_each( sv.begin() , sv.end() , Trim() );
// convert the individual components into specific type variables using lexical_cast
std::string sval;
double dval;
int ival;
bool bval;
// note this is not exception safe as if the wrong type is converted it will throw a bad_lexical_cast exception
size_t i = 0;
if ( i < sv.size() ) sval = sv[i++];
if ( i < sv.size() ) dval = boost::lexical_cast<double>(sv[i++].c_str());
if ( i < sv.size() ) ival = boost::lexical_cast<int>(sv[i++].c_str());
if ( i < sv.size() ) bval = boost::lexical_cast<bool>(sv[i++].c_str());
//-------------------------------------------------------------------------
// Example (2) case conversion
//-------------------------------------------------------------------------
// a mixed case string
std::string case_str = "XyzzZZ";
std::cout << "mixed case = " << case_str << std::endl;
// convert to lower case
boost::to_lower(case_str);
std::cout << "lower case = " << case_str << std::endl;
// convert to upper case
boost::to_upper(case_str);
std::cout << "upper case = " << case_str << std::endl;
// Resulting output
mixed case = XyzzZZ
lower case = xyzzzz
upper case = XYZZZZ
//-------------------------------------------------------------------------
// Exmaple(3) boost::trim
// usee boost trim and its variants to trim leading/trailing blanks and specified substrings
//-------------------------------------------------------------------------
// a string with leading and traling blanks
std::string str = " abcde ";
std::cout << "untrimmed :" << str << std::endl;
// trim leading blanks put output in a copy string
std::string trim_left_str = boost::trim_left_copy(str);
std::cout << "trim left :" << trim_left_str << std::endl;
// trim trailing blanks put output in a copy string
std::string trim_right_str = boost::trim_right_copy(str);
std::cout << "trim right :" << trim_right_str << std::endl;
// trim a string based on criteria
std::string line = "0123456789";
std::cout << "number line :" << line << std::endl;
// trim a left leading "0"
boost::trim_left_if( line , boost::is_any_of( "0" ));
std::cout << "trim 0 :" << line << std::endl;
// trim a right traling "9"
boost::trim_right_if( line , boost::is_any_of( "9" ));
std::cout << "trim 9 :" << line << std::endl;
// resulting output
untrimmed : abcde
trim left :abcde
trim right : abcde
number line :0123456789
trim 0 :123456789
trim 9 :12345678
//-------------------------------------------------------------------------
// Example (4) boost:erase , boost::replace
// use boost to replace and replace substrings
//-------------------------------------------------------------------------
// example string
std::string str = "XXX4567This is aXTestXXX123456";
std::cout << "before replace : " << str << std::endl;
// remove all "X"'s in string and replace with " " (space)
boost::replace_all( str , "X" , " " );
std::cout << "after replace : " << str << std::endl;
// erase the word "Test"
boost::erase_all( str , "Test" );
std::cout << "after erase Test : " << str << std::endl;
// erase the first 6 characters of the string " 456"
boost::erase_head( str , 6 );
std::cout << "after erase head 6 : " << str << std::endl;
// erase the last 5 characters of the string "23456"
boost::erase_tail( str , 5 );
std::cout << "after erase tail 5 : " << str << std::endl;
// resulting output
before replace : XXX4567This is aXTestXXX123456
after replace : 4567This is a Test 123456
after erase Test : 4567This is a 123456
after erase head 6 : 7This is a 123456
after erase tail 5 : 7This is a 1
//-------------------------------------------------------------------------
// Example (5) : String Comparision
//-------------------------------------------------------------------------
std::string x1 = "abcde";
std::string x2 = "Abcde.exe";
std::string x3 = "AbcDe";
bool result ;
// (a) lexicographical_compare chekcs for ordering: does "a" come before "b" ?
result = boost::lexicographical_compare( "a" , "b" );
std::cout << "comparing " << "a" << " to " << "b" << " result = " << ( result ? "true" : "false" ) << std::endl;
comparing a to b result = true
// (b) lexicographical_compare does "b" come before "a" ?
result = boost::lexicographical_compare( "b" , "a" );
std::cout << "comparing " << "b" << " to " << "a" << " result = " << ( result ? "true" : "false" ) << std::endl;
comparing b to a result = false
// (c) compare "abcde" to "AbcDe"
result = boost::lexicographical_compare( x1 , x3 );
std::cout << "comparing " << x1 << " to " << x3 << " result = " << ( result ? "true" : "false" ) << std::endl;
comparing abcde to Abcde result = false // "A" comes before "a"
// (d) check for an excact match
result = boost::equals( x1 , x3 );
std::cout << "equals " << x1 << " to " << x3 << " result = " << ( result ? "true" : "false" ) << std::endl;
equals abcde to AbcDe result = false
// (e) boost::iequals (ignore the case )
result = boost::iequals( x1 , x3 );
std::cout << "iequals " << x1 << " to " << x3 << " result = " << ( result ? "true" : "false" ) << std::endl;
iequals abcde to AbcDe result = true
// (f) see if string x1 starts with the substring "abc"
result = boost::starts_with( x1 , "abc" );
std::cout << "starts_with " << x1 << " " << "abc" << " result = " << ( result ? "true" : "false" ) << std::endl;
starts_with abcde abc result = true
// (g) see if string x2 ends with substring ".exe"
result = boost::ends_with( x2 , ".exe" );
std::cout << "ends_with " << x2 << " " << ".exe" << " result = " << ( result ? "true" : "false" ) << std::endl;
ends_with Abcde.exe .exe result = true
// (h) same as (g) but ignore the case
result = boost::iends_with( x2 , ".ExE" );
std::cout << "iends_with " << x2 << " " << ".ExE" << " result = " << ( result ? "true" : "false" ) << std::endl;
iends_with Abcde.exe .ExE result = true
// (i) look for as subtring within a string
result = boost::contains( x2 , "cde" );
std::cout << "contains " << x2 << " " << "cde" << " result = " << ( result ? "true" : "false" ) << std::endl;
contains Abcde.exe cde result = true