aboutsummaryrefslogtreecommitdiffstats
path: root/CommonLibs/Utils.cpp
blob: 1da95fa6526e979872eefdfb1f5fc13453f88bc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
* Copyright 2011 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <unistd.h>		// For usleep
#include <sys/time.h>	// For gettimeofday
#include <stdio.h>		// For vsnprintf
#include <ostream>		// For ostream
#include <sstream>		// For ostringstream
#include <string.h>		// For strcpy
//#include "GSMCommon.h"
#include "Utils.h"
#include "MemoryLeak.h"

namespace Utils {

MemStats gMemStats;
int gMemLeakDebug = 0;

MemStats::MemStats()
{
	memset(mMemNow,0,sizeof(mMemNow));
	memset(mMemTotal,0,sizeof(mMemTotal));
	memset(mMemName,0,sizeof(mMemName));
}

void MemStats::text(std::ostream &os)
{
	os << "Structs current total:\n";
	for (int i = 0; i < mMax; i++) {
		os << "\t" << (mMemName[i] ? mMemName[i] : "unknown") << " " << mMemNow[i] << " " << mMemTotal[i] << "\n";
	}
}

void MemStats::memChkNew(MemoryNames memIndex, const char *id)
{
	/*std::cout << "new " #type "\n";*/
	mMemNow[memIndex]++;
	mMemTotal[memIndex]++;
	mMemName[memIndex] = id;
}

void MemStats::memChkDel(MemoryNames memIndex, const char *id)
{
	/*std::cout << "del " #type "\n";*/
	mMemNow[memIndex]--;
	if (mMemNow[memIndex] < 0) {
		LOG(ERR) << "Memory underflow on type "<<id;
		if (gMemLeakDebug) assert(0);
		mMemNow[memIndex] += 100;	// Prevent another message for a while.
	}
}

std::ostream& operator<<(std::ostream& os, std::ostringstream& ss)
{
	return os << ss.str();
}

std::ostream &osprintf(std::ostream &os, const char *fmt, ...)
{
	va_list ap;
	char buf[300];
	va_start(ap,fmt);
	int n = vsnprintf(buf,300,fmt,ap);
	va_end(ap);
	if (n >= (300-4)) { strcpy(&buf[(300-4)],"..."); }
	os << buf;
	return os;
}

std::string format(const char *fmt, ...)
{
	va_list ap;
	char buf[300];
	va_start(ap,fmt);
	int n = vsnprintf(buf,300,fmt,ap);
	va_end(ap);
	if (n >= (300-4)) { strcpy(&buf[(300-4)],"..."); }
	return std::string(buf);
}

// Return time in seconds with high resolution.
// Note: In the past I found this to be a surprisingly expensive system call in linux.
double timef()
{
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return tv.tv_usec / 1000000.0 + tv.tv_sec;
}

const std::string timestr()
{
	struct timeval tv;
	struct tm tm;
	gettimeofday(&tv,NULL);
	localtime_r(&tv.tv_sec,&tm);
	unsigned tenths = tv.tv_usec / 100000;	// Rounding down is ok.
	return format(" %02d:%02d:%02d.%1d",tm.tm_hour,tm.tm_min,tm.tm_sec,tenths);
}

// High resolution sleep for the specified time.
// Return FALSE if time is already past.
void sleepf(double howlong)
{
	if (howlong <= 0.00001) return;		// Less than 10 usecs, forget it.
	usleep((useconds_t) (1000000.0 * howlong));
}

//bool sleepuntil(double untilwhen)
//{
	//double now = timef();
	//double howlong = untilwhen - now;		// Fractional time in seconds.
	// We are not worrying about overflow because all times should be in the near future.
	//if (howlong <= 0.00001) return false;		// Less than 10 usecs, forget it.
	//sleepf(sleeptime);
//}

std::string Text2Str::str() const
{
	std::ostringstream ss;
	text(ss);
	return ss.str();
}

std::ostream& operator<<(std::ostream& os, const Text2Str *val)
{
	std::ostringstream ss;
	if (val) {
		val->text(ss);
		os << ss.str(); 
	} else {
		os << "(null)";
	}
	return os;
}

// Greatest Common Denominator.
// This is by Doug Brown.
int gcd(int x, int y)
{
	if (x > y) {
		return x % y == 0 ? y : gcd(y, x % y);
	} else {
		return y % x == 0 ? x : gcd(x, y % x);
	}
}


// Split a C string into an argc,argv array in place; the input string is modified.
// Returns argc, and places results in argv, up to maxargc elements.
// The final argv receives the rest of the input string from maxargc on,
// even if it contains additional splitchars.
// The correct idiom for use is to make a copy of your string, like this:
// char *copy = strcpy((char*)alloca(the_string.length()+1),the_string.c_str());
// char *argv[2];
// int argc = cstrSplit(copy,argv,2,NULL);
// If you want to detect the error of too many arguments, add 1 to argv, like this:
// char *argv[3];
// int argc = cstrSplit(copy,argv,3,NULL);
// if (argc == 3) { error("too many arguments"; }
int cstrSplit(char *in, char **pargv,int maxargc, const char *splitchars)
{
	if (splitchars == NULL) { splitchars = " \t\r\n"; }	// Default is any space.
	int argc = 0;
	while (argc < maxargc) {
		while (*in && strchr(splitchars,*in)) {in++;}	// scan past any splitchars
		if (! *in) return argc;					// return if finished.
		pargv[argc++] = in;						// save ptr to start of arg.
		in = strpbrk(in,splitchars);			// go to end of arg.
		if (!in) return	argc;					// return if finished.
		*in++ = 0;								// zero terminate this arg.
	}
	return argc;
}

std::ostream& operator<<(std::ostream& os, const Statistic<int> &stat) { stat.text(os); return os; }
std::ostream& operator<<(std::ostream& os, const Statistic<unsigned> &stat) { stat.text(os); return os; }
std::ostream& operator<<(std::ostream& os, const Statistic<float> &stat) { stat.text(os); return os; }
std::ostream& operator<<(std::ostream& os, const Statistic<double> &stat) { stat.text(os); return os; }

std::string replaceAll(const std::string input, const std::string search, const std::string replace)
{
	std::string output = input;
 	int index = 0;

	while (true) {
		index = output.find(search, index);
		if (index == std::string::npos) {
			break;
		}

		output.replace(index, replace.length(), replace);
		index += replace.length();
	}

	return output;
}

};