libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2010 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 #include <string> 00018 #include "STLUtilities.h" 00019 00020 // 00021 #define _STLUTILITIES_BENCHMARK_ 00022 // This can turn on the benchmark of STLUtilities class and String class 00023 // 00024 #ifdef _STLUTILITIES_BENCHMARK_ 00025 #include "Performance.h" 00026 #include "Random.h" 00027 #include "StringBasics.h" 00028 #endif /* _STLUTILITIES_BENCHMARK_ */ 00029 00030 00031 #include <gtest/gtest.h> 00032 00033 TEST(STLUtilitiesTest, tSTLUtilitiesTest) 00034 { 00035 #if 0 00036 std::string test; 00037 std::string::iterator result; 00038 00039 test = "445566"; 00040 result = trimSequence(test, '5', true); 00041 EXPECT_EQ(result - test.begin() , 2); 00042 00043 test = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 00044 result = trimSequence(test, 'A', true); 00045 EXPECT_TRUE(result == test.begin()); 00046 #endif 00047 00048 00049 using namespace STLUtilities; // for overloaded std::string << operator 00050 00051 std::string toot; 00052 00053 toot << "double: " << 0.123456 << " LL: " << -5LL << " UL: " << 999UL << " char: " << '!'; 00054 00055 EXPECT_TRUE(toot == "double: 0.123456 LL: -5 UL: 999 char: !"); 00056 00057 00058 // same result as above using different methods 00059 toot.clear(); 00060 00061 append(toot, "double: "); 00062 00063 append(toot, 0.123456); 00064 00065 append(toot, " LL: "); 00066 00067 append(toot, -5LL); 00068 00069 append(toot, " UL: "); 00070 00071 append(toot, 999UL); 00072 00073 append(toot, " char: "); 00074 00075 append(toot, (char) (' ' + 1)); 00076 00077 EXPECT_TRUE(toot == "double: 0.123456 LL: -5 UL: 999 char: !"); 00078 00079 00080 toot.clear(); 00081 00082 std::vector<int> v; 00083 v.push_back(1); 00084 v.push_back(2); 00085 v.push_back(3); 00086 v.push_back(4); 00087 v.push_back(5); 00088 00089 toot = "array: "; 00090 append(toot, v, "\t", true); 00091 00092 EXPECT_TRUE(toot == "array: 0: 1\t1: 2\t2: 3\t3: 4\t4: 5"); 00093 00094 std::vector<std::string> tokens; 00095 00096 Tokenize(tokens, "ab\tcd\tefg\thi\tjk", '\t'); 00097 EXPECT_EQ(tokens.size(), 5U); 00098 EXPECT_TRUE(tokens[0] == "ab"); 00099 EXPECT_TRUE(tokens[1] == "cd"); 00100 EXPECT_TRUE(tokens[2] == "efg"); 00101 EXPECT_TRUE(tokens[3] == "hi"); 00102 EXPECT_TRUE(tokens[4] == "jk"); 00103 00104 00105 Tokenize(tokens, "ab\tcd\tefg\thi\tjk\t", '\t'); 00106 EXPECT_EQ(tokens.size(), 6U); 00107 EXPECT_TRUE(tokens[5] == ""); 00108 00109 // a single tab splits two empty fields, so should see two tokens here: 00110 Tokenize(tokens, "\t", '\t'); 00111 EXPECT_EQ(tokens.size(), 2U); 00112 EXPECT_TRUE(tokens[0] == ""); 00113 EXPECT_TRUE(tokens[1] == ""); 00114 00115 00116 Tokenize(tokens, "bahbah", '\t'); 00117 EXPECT_EQ(tokens.size(), 1U); 00118 EXPECT_TRUE(tokens[0] == "bahbah"); 00119 00120 // 00121 // no data on the line is the same as a single empty field. 00122 // the reason is we don't want to have a file with a single 00123 // column of data, but two separate values for .size(). Better 00124 // to let the caller simply say 'if tokens[0]==""' 00125 // 00126 Tokenize(tokens, "", '\t'); 00127 EXPECT_EQ(tokens.size(), 1U); 00128 EXPECT_TRUE(tokens[0] == ""); 00129 00130 #if 0 00131 toot = ""; 00132 append(toot, tokens, '\t'); 00133 std::cout << toot << std::endl; 00134 00135 exit(0); 00136 #endif 00137 } 00138 00139 // 00140 // Variadic templates necessary for reasonable printf implementation 00141 // are only supported as an experimental feature that in theory is 00142 // subject to changes in the future draft standard for C++. 00143 // 00144 // Only defined when the g++ option -std=c++0x is used. 00145 // 00146 #if defined(__GXX_EXPERIMENTAL_CXX0X__) 00147 TEST(STLUtilitiesTestPrintf, tSTLUtilitiesTestPrintf) 00148 { 00149 using namespace STLUtilities; // for overloaded std::string << operator 00150 00151 std::string result; 00152 00153 sprintf(result, "Hello, world!"); 00154 EXPECT_TRUE(result=="Hello, world!"); 00155 00156 sprintf(result, "n = %20.5lXXX", 123ULL); 00157 EXPECT_TRUE(result=="n = 7bXX"); 00158 00159 sprintf(result, "hello, world! %20sand boo", "well then"); 00160 EXPECT_TRUE(result=="hello, world! well thenand boo"); 00161 00162 sprintf(result, "addr = %08xXXX", 1234); 00163 EXPECT_TRUE(result=="addr = 000004d2XXX"); 00164 00165 sprintf(result, "Hello, world!! Imagine: %d!", 2345.1234); 00166 EXPECT_TRUE(result=="Hello, world!! Imagine: 2345.12!"); 00167 00168 } 00169 #endif 00170 00171 #ifdef _STLUTILITIES_BENCHMARK_ 00172 00173 // 00174 // Compare StringBasics.h String with std::string and STLUtilities append methods 00175 // 00176 // NB: these are mostly inline with the exception of String::operator +(char c), which 00177 // is a function call, so as currently implemented, String is at a disadvantage. 00178 // 00179 // However, all of these potentially suffer from limitations in g++, as I've noticed 00180 // that it at times is unable to inline more than a few levels of nested functions 00181 // deep even if all are trivially short and inlined. 00182 // 00183 00184 TEST(STLUtilitiesTestPrintf, Benchmark1) { 00185 using namespace STLUtilities; // for overloaded std::string << operator 00186 00187 std::string result; 00188 Random random; 00189 int range = 'z' - 'A'; 00190 unsigned int round = 1e6; 00191 Timing timing; 00192 random.Reset(0); 00193 timing.start(); 00194 for (unsigned int i = 0; i < round; i++) 00195 { 00196 result << (char)('A' + ( random.NextInt() % range)); 00197 } 00198 timing.end(); 00199 std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl; 00200 00201 String s; 00202 random.Reset(0); 00203 timing.start(); 00204 for (unsigned int i = 0; i < round; i++) 00205 { 00206 s += (char)('A' + ( random.NextInt() % range)); 00207 } 00208 timing.end(); 00209 std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl; 00210 EXPECT_EQ(result, s.c_str()); 00211 00212 std::string st; 00213 random.Reset(0); 00214 timing.start(); 00215 for (unsigned int i = 0; i < round; i++) 00216 { 00217 st += (char)('A' + ( random.NextInt() % range)); 00218 } 00219 timing.end(); 00220 std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl; 00221 EXPECT_EQ(result, st); 00222 00223 } 00224 00225 TEST(STLUtilitiesTestPrintf, Benchmark2) { 00226 using namespace STLUtilities; // for overloaded std::string << operator 00227 00228 std::string result; 00229 Random random; 00230 unsigned int round = 1e6; 00231 Timing timing; 00232 timing.start(); 00233 for (unsigned int i = 0; i < round; i++) 00234 { 00235 result = ""; 00236 for(int j=0; j<15; j++) result << (char) 'A'; 00237 } 00238 timing.end(); 00239 std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl; 00240 00241 String s; 00242 timing.start(); 00243 for (unsigned int i = 0; i < round; i++) 00244 { 00245 s = ""; 00246 for(int j=0; j<15; j++) s += 'A'; 00247 } 00248 timing.end(); 00249 std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl; 00250 EXPECT_EQ(result, s.c_str()); 00251 00252 std::string st; 00253 timing.start(); 00254 for (unsigned int i = 0; i < round; i++) 00255 { 00256 st = ""; 00257 for(int j=0; j<15; j++) st += 'A'; 00258 } 00259 timing.end(); 00260 std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl; 00261 EXPECT_EQ(result, st); 00262 } 00263 00264 #endif /* _STLUTILITIES_BENCHMARK_ */