kurtis.heimerl | 5a87247 | 2013-05-31 21:47:25 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2011 Range Networks, Inc. |
| 3 | * All Rights Reserved. |
| 4 | * |
| 5 | * This software is distributed under multiple licenses; |
| 6 | * see the COPYING file in the main directory for licensing |
| 7 | * information for this specific distribuion. |
| 8 | * |
| 9 | * This use of this software may be subject to additional restrictions. |
| 10 | * See the LEGAL file in the main directory for details. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 15 | */ |
| 16 | |
| 17 | #include <unistd.h> // For usleep |
| 18 | #include <sys/time.h> // For gettimeofday |
| 19 | #include <stdio.h> // For vsnprintf |
| 20 | #include <ostream> // For ostream |
| 21 | #include <sstream> // For ostringstream |
| 22 | #include <string.h> // For strcpy |
| 23 | //#include "GSMCommon.h" |
| 24 | #include "Utils.h" |
| 25 | #include "MemoryLeak.h" |
| 26 | |
| 27 | namespace Utils { |
| 28 | |
| 29 | MemStats gMemStats; |
| 30 | int gMemLeakDebug = 0; |
| 31 | |
| 32 | MemStats::MemStats() |
| 33 | { |
| 34 | memset(mMemNow,0,sizeof(mMemNow)); |
| 35 | memset(mMemTotal,0,sizeof(mMemTotal)); |
| 36 | memset(mMemName,0,sizeof(mMemName)); |
| 37 | } |
| 38 | |
| 39 | void MemStats::text(std::ostream &os) |
| 40 | { |
| 41 | os << "Structs current total:\n"; |
| 42 | for (int i = 0; i < mMax; i++) { |
| 43 | os << "\t" << (mMemName[i] ? mMemName[i] : "unknown") << " " << mMemNow[i] << " " << mMemTotal[i] << "\n"; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | void MemStats::memChkNew(MemoryNames memIndex, const char *id) |
| 48 | { |
| 49 | /*std::cout << "new " #type "\n";*/ |
| 50 | mMemNow[memIndex]++; |
| 51 | mMemTotal[memIndex]++; |
| 52 | mMemName[memIndex] = id; |
| 53 | } |
| 54 | |
| 55 | void MemStats::memChkDel(MemoryNames memIndex, const char *id) |
| 56 | { |
| 57 | /*std::cout << "del " #type "\n";*/ |
| 58 | mMemNow[memIndex]--; |
| 59 | if (mMemNow[memIndex] < 0) { |
| 60 | LOG(ERR) << "Memory underflow on type "<<id; |
| 61 | if (gMemLeakDebug) assert(0); |
| 62 | mMemNow[memIndex] += 100; // Prevent another message for a while. |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | std::ostream& operator<<(std::ostream& os, std::ostringstream& ss) |
| 67 | { |
| 68 | return os << ss.str(); |
| 69 | } |
| 70 | |
| 71 | std::ostream &osprintf(std::ostream &os, const char *fmt, ...) |
| 72 | { |
| 73 | va_list ap; |
| 74 | char buf[300]; |
| 75 | va_start(ap,fmt); |
| 76 | int n = vsnprintf(buf,300,fmt,ap); |
| 77 | va_end(ap); |
| 78 | if (n >= (300-4)) { strcpy(&buf[(300-4)],"..."); } |
| 79 | os << buf; |
| 80 | return os; |
| 81 | } |
| 82 | |
| 83 | std::string format(const char *fmt, ...) |
| 84 | { |
| 85 | va_list ap; |
| 86 | char buf[300]; |
| 87 | va_start(ap,fmt); |
| 88 | int n = vsnprintf(buf,300,fmt,ap); |
| 89 | va_end(ap); |
| 90 | if (n >= (300-4)) { strcpy(&buf[(300-4)],"..."); } |
| 91 | return std::string(buf); |
| 92 | } |
| 93 | |
| 94 | // Return time in seconds with high resolution. |
| 95 | // Note: In the past I found this to be a surprisingly expensive system call in linux. |
| 96 | double timef() |
| 97 | { |
| 98 | struct timeval tv; |
| 99 | gettimeofday(&tv,NULL); |
| 100 | return tv.tv_usec / 1000000.0 + tv.tv_sec; |
| 101 | } |
| 102 | |
| 103 | const std::string timestr() |
| 104 | { |
| 105 | struct timeval tv; |
| 106 | struct tm tm; |
| 107 | gettimeofday(&tv,NULL); |
| 108 | localtime_r(&tv.tv_sec,&tm); |
| 109 | unsigned tenths = tv.tv_usec / 100000; // Rounding down is ok. |
| 110 | return format(" %02d:%02d:%02d.%1d",tm.tm_hour,tm.tm_min,tm.tm_sec,tenths); |
| 111 | } |
| 112 | |
| 113 | // High resolution sleep for the specified time. |
| 114 | // Return FALSE if time is already past. |
| 115 | void sleepf(double howlong) |
| 116 | { |
| 117 | if (howlong <= 0.00001) return; // Less than 10 usecs, forget it. |
| 118 | usleep((useconds_t) (1000000.0 * howlong)); |
| 119 | } |
| 120 | |
| 121 | //bool sleepuntil(double untilwhen) |
| 122 | //{ |
| 123 | //double now = timef(); |
| 124 | //double howlong = untilwhen - now; // Fractional time in seconds. |
| 125 | // We are not worrying about overflow because all times should be in the near future. |
| 126 | //if (howlong <= 0.00001) return false; // Less than 10 usecs, forget it. |
| 127 | //sleepf(sleeptime); |
| 128 | //} |
| 129 | |
| 130 | std::string Text2Str::str() const |
| 131 | { |
| 132 | std::ostringstream ss; |
| 133 | text(ss); |
| 134 | return ss.str(); |
| 135 | } |
| 136 | |
| 137 | std::ostream& operator<<(std::ostream& os, const Text2Str *val) |
| 138 | { |
| 139 | std::ostringstream ss; |
| 140 | if (val) { |
| 141 | val->text(ss); |
| 142 | os << ss.str(); |
| 143 | } else { |
| 144 | os << "(null)"; |
| 145 | } |
| 146 | return os; |
| 147 | } |
| 148 | |
| 149 | // Greatest Common Denominator. |
| 150 | // This is by Doug Brown. |
| 151 | int gcd(int x, int y) |
| 152 | { |
| 153 | if (x > y) { |
| 154 | return x % y == 0 ? y : gcd(y, x % y); |
| 155 | } else { |
| 156 | return y % x == 0 ? x : gcd(x, y % x); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | |
| 161 | // Split a C string into an argc,argv array in place; the input string is modified. |
| 162 | // Returns argc, and places results in argv, up to maxargc elements. |
| 163 | // The final argv receives the rest of the input string from maxargc on, |
| 164 | // even if it contains additional splitchars. |
| 165 | // The correct idiom for use is to make a copy of your string, like this: |
| 166 | // char *copy = strcpy((char*)alloca(the_string.length()+1),the_string.c_str()); |
| 167 | // char *argv[2]; |
| 168 | // int argc = cstrSplit(copy,argv,2,NULL); |
| 169 | // If you want to detect the error of too many arguments, add 1 to argv, like this: |
| 170 | // char *argv[3]; |
| 171 | // int argc = cstrSplit(copy,argv,3,NULL); |
| 172 | // if (argc == 3) { error("too many arguments"; } |
| 173 | int cstrSplit(char *in, char **pargv,int maxargc, const char *splitchars) |
| 174 | { |
| 175 | if (splitchars == NULL) { splitchars = " \t\r\n"; } // Default is any space. |
| 176 | int argc = 0; |
| 177 | while (argc < maxargc) { |
| 178 | while (*in && strchr(splitchars,*in)) {in++;} // scan past any splitchars |
| 179 | if (! *in) return argc; // return if finished. |
| 180 | pargv[argc++] = in; // save ptr to start of arg. |
| 181 | in = strpbrk(in,splitchars); // go to end of arg. |
| 182 | if (!in) return argc; // return if finished. |
| 183 | *in++ = 0; // zero terminate this arg. |
| 184 | } |
| 185 | return argc; |
| 186 | } |
| 187 | |
| 188 | std::ostream& operator<<(std::ostream& os, const Statistic<int> &stat) { stat.text(os); return os; } |
| 189 | std::ostream& operator<<(std::ostream& os, const Statistic<unsigned> &stat) { stat.text(os); return os; } |
| 190 | std::ostream& operator<<(std::ostream& os, const Statistic<float> &stat) { stat.text(os); return os; } |
| 191 | std::ostream& operator<<(std::ostream& os, const Statistic<double> &stat) { stat.text(os); return os; } |
| 192 | |
| 193 | std::string replaceAll(const std::string input, const std::string search, const std::string replace) |
| 194 | { |
| 195 | std::string output = input; |
| 196 | int index = 0; |
| 197 | |
| 198 | while (true) { |
| 199 | index = output.find(search, index); |
| 200 | if (index == std::string::npos) { |
| 201 | break; |
| 202 | } |
| 203 | |
| 204 | output.replace(index, replace.length(), replace); |
| 205 | index += replace.length(); |
| 206 | } |
| 207 | |
| 208 | return output; |
| 209 | } |
| 210 | |
| 211 | }; |