blob: 1da95fa6526e979872eefdfb1f5fc13453f88bc3 [file] [log] [blame]
kurtis.heimerl5a872472013-05-31 21:47:25 +00001/*
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
27namespace Utils {
28
29MemStats gMemStats;
30int gMemLeakDebug = 0;
31
32MemStats::MemStats()
33{
34 memset(mMemNow,0,sizeof(mMemNow));
35 memset(mMemTotal,0,sizeof(mMemTotal));
36 memset(mMemName,0,sizeof(mMemName));
37}
38
39void 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
47void 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
55void 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
66std::ostream& operator<<(std::ostream& os, std::ostringstream& ss)
67{
68 return os << ss.str();
69}
70
71std::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
83std::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.
96double timef()
97{
98 struct timeval tv;
99 gettimeofday(&tv,NULL);
100 return tv.tv_usec / 1000000.0 + tv.tv_sec;
101}
102
103const 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.
115void 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
130std::string Text2Str::str() const
131{
132 std::ostringstream ss;
133 text(ss);
134 return ss.str();
135}
136
137std::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.
151int 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"; }
173int 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
188std::ostream& operator<<(std::ostream& os, const Statistic<int> &stat) { stat.text(os); return os; }
189std::ostream& operator<<(std::ostream& os, const Statistic<unsigned> &stat) { stat.text(os); return os; }
190std::ostream& operator<<(std::ostream& os, const Statistic<float> &stat) { stat.text(os); return os; }
191std::ostream& operator<<(std::ostream& os, const Statistic<double> &stat) { stat.text(os); return os; }
192
193std::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};