2
// ZoneMinder General Utility Functions, $Date$, $Revision$
3
// Copyright (C) 2001-2008 Philip Coombes
5
// This program is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU General Public License
7
// as published by the Free Software Foundation; either version 2
8
// of the License, or (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
//#include "zm_logger.h"
28
unsigned int sseversion = 0;
30
const std::string stringtf( const char *format, ... )
33
char tempBuffer[8192];
34
std::string tempString;
36
va_start(ap, format );
37
vsnprintf( tempBuffer, sizeof(tempBuffer), format , ap );
40
tempString = tempBuffer;
45
const std::string stringtf( const std::string &format, ... )
48
char tempBuffer[8192];
49
std::string tempString;
51
va_start(ap, format );
52
vsnprintf( tempBuffer, sizeof(tempBuffer), format.c_str() , ap );
55
tempString = tempBuffer;
60
bool startsWith( const std::string &haystack, const std::string &needle )
62
return( haystack.substr( 0, needle.length() ) == needle );
65
StringVector split( const std::string &string, const std::string chars, int limit )
67
StringVector stringVector;
68
std::string tempString = string;
69
std::string::size_type startIndex = 0;
70
std::string::size_type endIndex = 0;
72
//Info( "Looking for '%s' in '%s', limit %d", chars.c_str(), string.c_str(), limit );
76
endIndex = string.find_first_of( chars, startIndex );
77
//Info( "Got endIndex at %d", endIndex );
80
//Info( "Adding '%s'", string.substr( startIndex, endIndex-startIndex ).c_str() );
81
stringVector.push_back( string.substr( startIndex, endIndex-startIndex ) );
83
if ( endIndex == std::string::npos )
85
// Find non-delimiters
86
startIndex = tempString.find_first_not_of( chars, endIndex );
87
if ( limit && (stringVector.size() == (unsigned int)(limit-1)) )
89
stringVector.push_back( string.substr( startIndex ) );
92
//Info( "Got new startIndex at %d", startIndex );
93
} while ( startIndex != std::string::npos );
94
//Info( "Finished with %d strings", stringVector.size() );
96
return( stringVector );
99
const std::string base64Encode( const std::string &inString )
101
static char base64_table[64] = { '\0' };
103
if ( !base64_table[0] )
106
for ( char c = 'A'; c <= 'Z'; c++ )
107
base64_table[i++] = c;
108
for ( char c = 'a'; c <= 'z'; c++ )
109
base64_table[i++] = c;
110
for ( char c = '0'; c <= '9'; c++ )
111
base64_table[i++] = c;
112
base64_table[i++] = '+';
113
base64_table[i++] = '/';
116
std::string outString;
117
outString.reserve( 2 * inString.size() );
119
const char *inPtr = inString.c_str();
122
unsigned char selection = *inPtr >> 2;
123
unsigned char remainder = (*inPtr++ & 0x03) << 4;
124
outString += base64_table[selection];
128
selection = remainder | (*inPtr >> 4);
129
remainder = (*inPtr++ & 0x0f) << 2;
130
outString += base64_table[selection];
134
selection = remainder | (*inPtr >> 6);
135
outString += base64_table[selection];
136
selection = (*inPtr++ & 0x3f);
137
outString += base64_table[selection];
141
outString += base64_table[remainder];
147
outString += base64_table[remainder];
155
/* Sets sse_version */
157
#if (defined(__i386__) || defined(__x86_64__))
158
/* x86 or x86-64 processor */
159
uint32_t r_edx, r_ecx;
161
__asm__ __volatile__(
164
: "=d" (r_edx), "=c" (r_ecx)
169
if (r_ecx & 0x00000200) {
170
sseversion = 35; /* SSSE3 */
171
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
172
} else if (r_ecx & 0x00000001) {
173
sseversion = 30; /* SSE3 */
174
Debug(1,"Detected a x86\\x86-64 processor with SSE3");
175
} else if (r_edx & 0x04000000) {
176
sseversion = 20; /* SSE2 */
177
Debug(1,"Detected a x86\\x86-64 processor with SSE2");
178
} else if (r_edx & 0x02000000) {
179
sseversion = 10; /* SSE */
180
Debug(1,"Detected a x86\\x86-64 processor with SSE");
183
Debug(1,"Detected a x86\\x86-64 processor");
187
/* Non x86 or x86-64 processor, SSE2 is not available */
188
Debug(1,"Detected a non x86\\x86-64 processor");
193
/* SSE2 aligned memory copy. Useful for big copying of aligned memory like image buffers in ZM */
194
/* For platforms without SSE2 we will use standard x86 asm memcpy or glibc's memcpy() */
195
__attribute__((noinline,__target__("sse2"))) void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes) {
196
#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE))
198
unsigned int remainder = bytes % 128;
199
const uint8_t* lastsrc = (uint8_t*)src + (bytes - remainder);
201
__asm__ __volatile__(
202
"sse2_copy_iter:\n\t"
203
"movdqa (%0),%%xmm0\n\t"
204
"movdqa 0x10(%0),%%xmm1\n\t"
205
"movdqa 0x20(%0),%%xmm2\n\t"
206
"movdqa 0x30(%0),%%xmm3\n\t"
207
"movdqa 0x40(%0),%%xmm4\n\t"
208
"movdqa 0x50(%0),%%xmm5\n\t"
209
"movdqa 0x60(%0),%%xmm6\n\t"
210
"movdqa 0x70(%0),%%xmm7\n\t"
211
"movntdq %%xmm0,(%1)\n\t"
212
"movntdq %%xmm1,0x10(%1)\n\t"
213
"movntdq %%xmm2,0x20(%1)\n\t"
214
"movntdq %%xmm3,0x30(%1)\n\t"
215
"movntdq %%xmm4,0x40(%1)\n\t"
216
"movntdq %%xmm5,0x50(%1)\n\t"
217
"movntdq %%xmm6,0x60(%1)\n\t"
218
"movntdq %%xmm7,0x70(%1)\n\t"
222
"jb sse2_copy_iter\n\t"
224
"jz sse2_copy_finish\n\t"
227
"sse2_copy_finish:\n\t"
229
: "S" (src), "D" (dest), "r" (lastsrc), "c" (remainder)
230
: "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory"
234
/* Standard memcpy */
235
__asm__ __volatile__("cld; rep movsb" :: "S"(src), "D"(dest), "c"(bytes) : "cc", "memory");
238
/* Non x86\x86-64 platform, use memcpy */
239
memcpy(dest,src,bytes);
244
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff) {
245
if (((end->tv_nsec)-(start->tv_nsec))<0) {
246
diff->tv_sec = end->tv_sec-start->tv_sec-1;
247
diff->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec;
249
diff->tv_sec = end->tv_sec-start->tv_sec;
250
diff->tv_nsec = end->tv_nsec-start->tv_nsec;