File indexing completed on 2024-04-28 09:36:50
0001 /* 0002 This file is part of KCachegrind. 0003 0004 SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-only 0007 */ 0008 0009 /* 0010 * Utility classes for KCachegrind 0011 */ 0012 0013 #include "utils.h" 0014 0015 #include <errno.h> 0016 0017 #include <QIODevice> 0018 #include <QFile> 0019 0020 0021 0022 // class FixString 0023 0024 FixString::FixString(const char* str, int len) 0025 { 0026 _str = str; 0027 _len = len; 0028 } 0029 0030 bool FixString::stripFirst(char& c) 0031 { 0032 if (!_len) { 0033 c = 0; 0034 return false; 0035 } 0036 0037 c = *_str; 0038 _str++; 0039 _len--; 0040 return true; 0041 } 0042 0043 bool FixString::stripPrefix(const char* p) 0044 { 0045 if (_len == 0) return false; 0046 if (!p || (*p != *_str)) return false; 0047 0048 const char* s = _str+1; 0049 int l = _len-1; 0050 p++; 0051 while(*p) { 0052 if (l==0) return false; 0053 if (*s != *p) return false; 0054 p++; 0055 s++; 0056 l--; 0057 } 0058 _str = s; 0059 _len = l; 0060 return true; 0061 } 0062 0063 0064 // this parses hexadecimal (with prefix '0x' too) 0065 bool FixString::stripUInt(unsigned int& v, bool stripSpaces) 0066 { 0067 if (_len==0) { 0068 v = 0; 0069 return false; 0070 } 0071 0072 char c = *_str; 0073 if (c<'0' || c>'9') { 0074 v = 0; 0075 return false; 0076 } 0077 0078 v = c-'0'; 0079 const char* s = _str+1; 0080 int l = _len-1; 0081 c = *s; 0082 0083 if ((l>0) && (c == 'x') && (v==0)) { 0084 // hexadecimal 0085 s++; 0086 c = *s; 0087 l--; 0088 0089 while(l>0) { 0090 if (c>='0' && c<='9') 0091 v = 16*v + (c-'0'); 0092 else if (c>='a' && c<='f') 0093 v = 16*v + 10 + (c-'a'); 0094 else if (c>='A' && c<='F') 0095 v = 16*v + 10 + (c-'A'); 0096 else 0097 break; 0098 s++; 0099 c = *s; 0100 l--; 0101 } 0102 } 0103 else { 0104 // decimal 0105 0106 while(l>0) { 0107 if (c<'0' || c>'9') break; 0108 v = 10*v + (c-'0'); 0109 s++; 0110 c = *s; 0111 l--; 0112 } 0113 } 0114 0115 if (stripSpaces) 0116 while(l>0) { 0117 if (c != ' ') break; 0118 s++; 0119 c = *s; 0120 l--; 0121 } 0122 0123 _str = s; 0124 _len = l; 0125 return true; 0126 } 0127 0128 0129 void FixString::stripSurroundingSpaces() 0130 { 0131 if (_len==0) return; 0132 0133 // leading spaces 0134 while((_len>0) && (*_str==' ')) { 0135 _len--; 0136 _str++; 0137 } 0138 0139 // trailing spaces 0140 while((_len>0) && (_str[_len-1]==' ')) { 0141 _len--; 0142 } 0143 } 0144 0145 void FixString::stripSpaces() 0146 { 0147 while((_len>0) && (*_str==' ')) { 0148 _len--; 0149 _str++; 0150 } 0151 } 0152 0153 bool FixString::stripName(FixString& s) 0154 { 0155 if (_len==0) return false; 0156 0157 // first char has to be a letter or "_" 0158 if (!QChar(*_str).isLetter() && (*_str != '_')) return false; 0159 0160 int newLen = 1; 0161 const char* newStr = _str; 0162 0163 _str++; 0164 _len--; 0165 0166 while(_len>0) { 0167 if (!QChar(*_str).isLetterOrNumber() 0168 && (*_str != '_')) break; 0169 0170 newLen++; 0171 _str++; 0172 _len--; 0173 } 0174 0175 s.set(newStr, newLen); 0176 return true; 0177 } 0178 0179 FixString FixString::stripUntil(char c) 0180 { 0181 if (_len == 0) return FixString(); 0182 0183 const char* newStr = _str; 0184 int newLen = 0; 0185 0186 while(_len>0) { 0187 if (*_str == c) { 0188 _str++; 0189 _len--; 0190 break; 0191 } 0192 0193 _str++; 0194 _len--; 0195 newLen++; 0196 } 0197 return FixString(newStr, newLen); 0198 } 0199 0200 bool FixString::stripUInt64(uint64& v, bool stripSpaces) 0201 { 0202 if (_len==0) { 0203 v = 0; 0204 return false; 0205 } 0206 0207 char c = *_str; 0208 if (c<'0' || c>'9') { 0209 v = 0; 0210 return false; 0211 } 0212 0213 v = c-'0'; 0214 const char* s = _str+1; 0215 int l = _len-1; 0216 c = *s; 0217 0218 if ((l>0) && (c == 'x') && (v==0)) { 0219 // hexadecimal 0220 s++; 0221 c = *s; 0222 l--; 0223 0224 while(l>0) { 0225 if (c>='0' && c<='9') 0226 v = 16*v + (c-'0'); 0227 else if (c>='a' && c<='f') 0228 v = 16*v + 10 + (c-'a'); 0229 else if (c>='A' && c<='F') 0230 v = 16*v + 10 + (c-'A'); 0231 else 0232 break; 0233 s++; 0234 c = *s; 0235 l--; 0236 } 0237 } 0238 else { 0239 // decimal 0240 while(l>0) { 0241 if (c<'0' || c>'9') break; 0242 v = 10*v + (c-'0'); 0243 s++; 0244 c = *s; 0245 l--; 0246 } 0247 } 0248 0249 if (stripSpaces) 0250 while(l>0) { 0251 if (c != ' ') break; 0252 s++; 0253 c = *s; 0254 l--; 0255 } 0256 0257 _str = s; 0258 _len = l; 0259 return true; 0260 } 0261 0262 0263 bool FixString::stripInt64(int64& v, bool stripSpaces) 0264 { 0265 if (_len==0) { 0266 v = 0; 0267 return false; 0268 } 0269 0270 char c = *_str; 0271 bool negative = false; 0272 if (c == '-') { 0273 negative = true; 0274 _str++; 0275 _len--; 0276 } 0277 if (_len==0) { 0278 v = 0; 0279 return false; 0280 } 0281 c = *_str; 0282 if (c<'0' || c>'9') { 0283 v = 0; 0284 return false; 0285 } 0286 0287 v = c-'0'; 0288 const char* s = _str+1; 0289 int l = _len-1; 0290 c = *s; 0291 0292 if ((l>0) && (c == 'x') && (v==0)) { 0293 // hexadecimal 0294 s++; 0295 c = *s; 0296 l--; 0297 0298 while(l>0) { 0299 if (c>='0' && c<='9') 0300 v = 16*v + (c-'0'); 0301 else if (c>='a' && c<='f') 0302 v = 16*v + 10 + (c-'a'); 0303 else if (c>='A' && c<='F') 0304 v = 16*v + 10 + (c-'A'); 0305 else 0306 break; 0307 s++; 0308 c = *s; 0309 l--; 0310 } 0311 } 0312 else { 0313 // decimal 0314 0315 while(l>0) { 0316 if (c<'0' || c>'9') break; 0317 v = 10*v + (c-'0'); 0318 s++; 0319 c = *s; 0320 l--; 0321 } 0322 } 0323 0324 if (negative) 0325 v = -v; 0326 0327 if (stripSpaces) 0328 while(l>0) { 0329 if (c != ' ') break; 0330 s++; 0331 c = *s; 0332 l--; 0333 } 0334 0335 _str = s; 0336 _len = l; 0337 return true; 0338 } 0339 0340 0341 0342 // class FixFile 0343 0344 FixFile::FixFile(QIODevice* file, const QString& filename) 0345 { 0346 _file = file; 0347 0348 if (!file) { 0349 _len = 0; 0350 _currentLeft = 0; 0351 _openError = true; 0352 return; 0353 } 0354 0355 _filename = filename; 0356 if (!file->isOpen() && !file->open( QIODevice::ReadOnly ) ) { 0357 qWarning( "%s: %s", (const char*)QFile::encodeName(_filename), 0358 strerror( errno ) ); 0359 _len = 0; 0360 _currentLeft = 0; 0361 _openError = true; 0362 return; 0363 } 0364 0365 _openError = false; 0366 _used_mmap = false; 0367 0368 uchar* addr = nullptr; 0369 0370 #if QT_VERSION >= 0x040400 0371 // QFile::map was introduced with Qt 4.4 0372 if (file->size() >0) { 0373 QFile* mappableDevice = dynamic_cast<QFile*>(file); 0374 if (mappableDevice) { 0375 addr = mappableDevice->map( 0, file->size() ); 0376 } 0377 } 0378 #endif 0379 0380 if (addr) { 0381 // map succeeded 0382 _base = (char*) addr; 0383 _len = file->size(); 0384 _used_mmap = true; 0385 0386 if (0) qDebug("Mapped '%s'", qPrintable( _filename )); 0387 } 0388 else { 0389 // try reading the data into memory instead 0390 file->seek(0); 0391 _data = file->readAll(); 0392 _base = _data.data(); 0393 _len = _data.size(); 0394 } 0395 0396 _current = _base; 0397 _currentLeft = _len; 0398 } 0399 0400 FixFile::~FixFile() 0401 { 0402 // if the file was read into _data, it will be deleted automatically 0403 0404 if (_used_mmap && _file) { 0405 if (0) qDebug("Unmapping '%s'", qPrintable( _filename )); 0406 #if QT_VERSION >= 0x040400 0407 QFile* mappableDevice = dynamic_cast<QFile*>(_file); 0408 Q_ASSERT(mappableDevice); 0409 if (!mappableDevice->unmap( (uchar*) _base )) 0410 qWarning( "munmap: %s", strerror( errno ) ); 0411 #endif 0412 } 0413 } 0414 0415 bool FixFile::nextLine(FixString& str) 0416 { 0417 if (_currentLeft == 0) return false; 0418 0419 unsigned left = _currentLeft; 0420 char* current = _current; 0421 0422 while(left>0) { 0423 if (*current == 0 || *current == '\n') break; 0424 current++; 0425 left--; 0426 } 0427 0428 if (0) { 0429 char tmp[200]; 0430 int l = _currentLeft-left; 0431 if (l>199) l = 199; 0432 strncpy(tmp, _current, l); 0433 tmp[l] = 0; 0434 qDebug("[FixFile::nextLine] At %lu, len %u: '%s'", 0435 (unsigned long) (_current - _base), _currentLeft-left, tmp); 0436 } 0437 0438 int len = _currentLeft-left; 0439 // get rid of any carriage return at end 0440 if ((len>0) && (*(current-1) == '\r')) len--; 0441 str.set(_current, len); 0442 0443 if ((left > 0) && (*current == '\n')) { 0444 current++; 0445 left--; 0446 } 0447 _current = current; 0448 _currentLeft = left; 0449 0450 return true; 0451 } 0452 0453 bool FixFile::setCurrent(unsigned pos) 0454 { 0455 if (pos > _len) return false; 0456 0457 _current = _base + pos; 0458 _currentLeft = _len - pos; 0459 return true; 0460 } 0461 0462 0463 #if 0 0464 0465 // class AppendList 0466 0467 0468 AppendList::AppendList() 0469 { 0470 _next = 0; 0471 _current = 0; 0472 _last = 0; 0473 0474 _count = 0; 0475 _currentIndex = 0; 0476 _lastIndex = 0; 0477 _autoDelete = false; 0478 } 0479 0480 0481 void AppendList::clear() 0482 { 0483 int count = _count; 0484 int i; 0485 0486 if (count <= firstLen) { 0487 if (_autoDelete) 0488 for (i=0;i<count;i++) 0489 delete _first[i]; 0490 } 0491 } 0492 0493 #endif 0494