Util.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  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. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "Util.h"
  36. #include "File.h"
  37. #include "message.h"
  38. #include "Randomizer.h"
  39. #include "a2netcompat.h"
  40. #include "a2time.h"
  41. #include "DlAbortEx.h"
  42. #include "BitfieldMan.h"
  43. #include "DefaultDiskWriter.h"
  44. #include "BinaryStream.h"
  45. #include "FatalException.h"
  46. #include <ctype.h>
  47. #include <errno.h>
  48. #include <fcntl.h>
  49. #include <unistd.h>
  50. #include <signal.h>
  51. #include <iomanip>
  52. #include <sstream>
  53. #ifndef HAVE_SLEEP
  54. # ifdef HAVE_WINSOCK_H
  55. # define WIN32_LEAN_AND_MEAN
  56. # include <windows.h>
  57. # endif // HAVE_WINSOCK_H
  58. #endif // HAVE_SLEEP
  59. template<typename T>
  60. string uint2str(T value, bool comma)
  61. {
  62. string str;
  63. if(value == 0) {
  64. str = "0";
  65. return str;
  66. }
  67. int32_t count = 0;
  68. while(value) {
  69. ++count;
  70. char digit = value%10+'0';
  71. str.insert(str.begin(), digit);
  72. value /= 10;
  73. if(comma && count > 3 && count%3 == 1) {
  74. str.insert(str.begin()+1, ',');
  75. }
  76. }
  77. return str;
  78. }
  79. template<typename T>
  80. string int2str(T value, bool comma)
  81. {
  82. bool flag = false;
  83. if(value < 0) {
  84. flag = true;
  85. value = -value;
  86. }
  87. string str = uint2str<T>(value, comma);
  88. if(flag) {
  89. str.insert(str.begin(), '-');
  90. }
  91. return str;
  92. }
  93. string Util::uitos(uint16_t value, bool comma)
  94. {
  95. return uint2str<uint16_t>(value, comma);
  96. }
  97. string Util::itos(int16_t value, bool comma)
  98. {
  99. return int2str<int16_t>(value, comma);
  100. }
  101. string Util::uitos(uint32_t value, bool comma)
  102. {
  103. return uint2str<uint32_t>(value, comma);
  104. }
  105. string Util::itos(int32_t value, bool comma)
  106. {
  107. return int2str<int32_t>(value, comma);
  108. }
  109. string Util::ullitos(uint64_t value, bool comma)
  110. {
  111. return uint2str<uint64_t>(value, comma);
  112. }
  113. string Util::llitos(int64_t value, bool comma)
  114. {
  115. return int2str<int64_t>(value, comma);
  116. }
  117. string Util::trim(const string& src, const string& trimCharset)
  118. {
  119. string::size_type sp = src.find_first_not_of(trimCharset);
  120. string::size_type ep = src.find_last_not_of(trimCharset);
  121. if(sp == string::npos || ep == string::npos) {
  122. return "";
  123. } else {
  124. return src.substr(sp, ep-sp+1);
  125. }
  126. }
  127. void Util::split(pair<string, string>& hp, const string& src, char delim)
  128. {
  129. hp.first = "";
  130. hp.second = "";
  131. string::size_type p = src.find(delim);
  132. if(p == string::npos) {
  133. hp.first = src;
  134. hp.second = "";
  135. } else {
  136. hp.first = trim(src.substr(0, p));
  137. hp.second = trim(src.substr(p+1));
  138. }
  139. }
  140. pair<string, string> Util::split(const string& src, const string& delims)
  141. {
  142. pair<string, string> hp;
  143. hp.first = "";
  144. hp.second = "";
  145. string::size_type p = src.find_first_of(delims);
  146. if(p == string::npos) {
  147. hp.first = src;
  148. hp.second = "";
  149. } else {
  150. hp.first = trim(src.substr(0, p));
  151. hp.second = trim(src.substr(p+1));
  152. }
  153. return hp;
  154. }
  155. int64_t Util::difftv(struct timeval tv1, struct timeval tv2) {
  156. if(tv1.tv_sec < tv2.tv_sec || tv1.tv_sec == tv2.tv_sec && tv1.tv_usec < tv2.tv_usec) {
  157. return 0;
  158. }
  159. return ((int64_t)(tv1.tv_sec-tv2.tv_sec)*1000000+
  160. tv1.tv_usec-tv2.tv_usec);
  161. }
  162. int32_t Util::difftvsec(struct timeval tv1, struct timeval tv2) {
  163. if(tv1.tv_sec < tv2.tv_sec) {
  164. return 0;
  165. }
  166. return tv1.tv_sec-tv2.tv_sec;
  167. }
  168. void Util::slice(Strings& result, const string& src, char delim, bool doTrim) {
  169. string::size_type p = 0;
  170. while(1) {
  171. string::size_type np = src.find(delim, p);
  172. if(np == string::npos) {
  173. string term = src.substr(p);
  174. if(doTrim) {
  175. term = trim(term);
  176. }
  177. if(term.size()) {
  178. result.push_back(term);
  179. }
  180. break;
  181. }
  182. string term = src.substr(p, np-p);
  183. if(doTrim) {
  184. term = trim(term);
  185. }
  186. p = np+1;
  187. if(term.size()) {
  188. result.push_back(term);
  189. }
  190. }
  191. }
  192. bool Util::startsWith(const string& target, const string& part) {
  193. if(target.size() < part.size()) {
  194. return false;
  195. }
  196. if(part == "") {
  197. return true;
  198. }
  199. if(target.find(part) == 0) {
  200. return true;
  201. } else {
  202. return false;
  203. }
  204. }
  205. bool Util::endsWith(const string& target, const string& part) {
  206. if(target.size() < part.size()) {
  207. return false;
  208. }
  209. if(part == "") {
  210. return true;
  211. }
  212. if(target.rfind(part) == target.size()-part.size()) {
  213. return true;
  214. } else {
  215. return false;
  216. }
  217. }
  218. string Util::replace(const string& target, const string& oldstr, const string& newstr) {
  219. if(target == "" || oldstr == "" ) {
  220. return target;
  221. }
  222. string result;
  223. string::size_type p = 0;
  224. string::size_type np = target.find(oldstr);
  225. while(np != string::npos) {
  226. result += target.substr(p, np-p)+newstr;
  227. p = np+oldstr.size();
  228. np = target.find(oldstr, p);
  229. }
  230. result += target.substr(p);
  231. return result;
  232. }
  233. bool Util::shouldUrlencode(const char c)
  234. {
  235. return !(// ALPHA
  236. 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' ||
  237. // DIGIT
  238. '0' <= c && c <= '9' ||
  239. // safe
  240. '$' == c || '-' == c || '_' == c || '.' == c ||
  241. // extra
  242. '!' == c || '*' == c || '\'' == c ||'(' == c ||
  243. ')' == c || ',' == c ||
  244. // reserved
  245. ';' == c || '/' == c || '?' == c || ':' == c ||
  246. '@' == c || '&' == c || '=' == c || '+' == c);
  247. }
  248. string Util::urlencode(const unsigned char* target, int32_t len) {
  249. string dest;
  250. for(int32_t i = 0; i < len; i++) {
  251. if(shouldUrlencode(target[i])) {
  252. char temp[4];
  253. sprintf(temp, "%%%02x", target[i]);
  254. temp[sizeof(temp)-1] = '\0';
  255. dest.append(temp);
  256. } else {
  257. dest += target[i];
  258. }
  259. }
  260. return dest;
  261. }
  262. string Util::torrentUrlencode(const unsigned char* target, int32_t len) {
  263. string dest;
  264. for(int32_t i = 0; i < len; i++) {
  265. if('0' <= target[i] && target[i] <= '9' ||
  266. 'A' <= target[i] && target[i] <= 'Z' ||
  267. 'a' <= target[i] && target[i] <= 'z') {
  268. dest += target[i];
  269. } else {
  270. char temp[4];
  271. sprintf(temp, "%%%02x", target[i]);
  272. temp[sizeof(temp)-1] = '\0';
  273. dest.append(temp);
  274. }
  275. }
  276. return dest;
  277. }
  278. string Util::urldecode(const string& target) {
  279. string result;
  280. for(string::const_iterator itr = target.begin();
  281. itr != target.end(); itr++) {
  282. if(*itr == '%') {
  283. if(itr+1 != target.end() && itr+2 != target.end() &&
  284. isxdigit(*(itr+1)) && isxdigit(*(itr+2))) {
  285. result += Util::parseInt(string(itr+1, itr+3), 16);
  286. itr += 2;
  287. } else {
  288. result += *itr;
  289. }
  290. } else {
  291. result += *itr;
  292. }
  293. }
  294. return result;
  295. }
  296. string Util::toHex(const unsigned char* src, int32_t len) {
  297. char* temp = new char[len*2+1];
  298. for(int32_t i = 0; i < len; i++) {
  299. sprintf(temp+i*2, "%02x", src[i]);
  300. }
  301. temp[len*2] = '\0';
  302. string hex = temp;
  303. delete [] temp;
  304. return hex;
  305. }
  306. FILE* Util::openFile(const string& filename, const string& mode) {
  307. FILE* file = fopen(filename.c_str(), mode.c_str());
  308. return file;
  309. }
  310. void Util::fileCopy(const string& dest, const string& src) {
  311. File file(src);
  312. rangedFileCopy(dest, src, 0, file.size());
  313. }
  314. void Util::rangedFileCopy(const string& dest, const string& src, int64_t srcOffset, int64_t length)
  315. {
  316. int32_t bufSize = 4096;
  317. unsigned char buf[bufSize];
  318. DefaultDiskWriter srcdw;
  319. DefaultDiskWriter destdw;
  320. srcdw.openExistingFile(src);
  321. destdw.initAndOpenFile(dest);
  322. int32_t x = length/bufSize;
  323. int32_t r = length%bufSize;
  324. int64_t initialOffset = srcOffset;
  325. for(int32_t i = 0; i < x; ++i) {
  326. int32_t readLength = 0;
  327. while(readLength < bufSize) {
  328. int32_t ret = srcdw.readData(buf, bufSize-readLength, srcOffset);
  329. destdw.writeData(buf, ret, srcOffset-initialOffset);
  330. srcOffset += ret;
  331. readLength += ret;
  332. }
  333. }
  334. if(r > 0) {
  335. int32_t readLength = 0;
  336. while(readLength < r) {
  337. int32_t ret = srcdw.readData(buf, r-readLength, srcOffset);
  338. destdw.writeData(buf, ret, srcOffset-initialOffset);
  339. srcOffset += ret;
  340. readLength += ret;
  341. }
  342. }
  343. }
  344. bool Util::isPowerOf(int32_t num, int32_t base) {
  345. if(base <= 0) { return false; }
  346. if(base == 1) { return true; }
  347. while(num%base == 0) {
  348. num /= base;
  349. if(num == 1) {
  350. return true;
  351. }
  352. }
  353. return false;
  354. }
  355. string Util::secfmt(int32_t sec) {
  356. string str;
  357. if(sec >= 3600) {
  358. str = itos(sec/3600)+"h";
  359. sec %= 3600;
  360. }
  361. if(sec >= 60) {
  362. int32_t min = sec/60;
  363. if(min < 10) {
  364. str += "0";
  365. }
  366. str += itos(min)+"m";
  367. sec %= 60;
  368. }
  369. if(sec < 10) {
  370. str += "0";
  371. }
  372. str += itos(sec)+"s";
  373. return str;
  374. }
  375. int32_t Util::expandBuffer(char** pbuf, int32_t curLength, int32_t newLength) {
  376. char* newbuf = new char[newLength];
  377. memcpy(newbuf, *pbuf, curLength);
  378. delete [] *pbuf;
  379. *pbuf = newbuf;
  380. return newLength;
  381. }
  382. int32_t getNum(const char* buf, int32_t offset, int32_t length) {
  383. char* temp = new char[length+1];
  384. memcpy(temp, buf+offset, length);
  385. temp[length] = '\0';
  386. int32_t x = strtol(temp, NULL, 10);
  387. delete [] temp;
  388. return x;
  389. }
  390. void unfoldSubRange(const string& src, Integers& range) {
  391. if(src.empty()) {
  392. return;
  393. }
  394. string::size_type p = src.find_first_of(",-");
  395. if(p == 0) {
  396. return;
  397. } else if(p == string::npos) {
  398. range.push_back(atoi(src.c_str()));
  399. } else {
  400. if(src.at(p) == ',') {
  401. int32_t num = getNum(src.c_str(), 0, p);
  402. range.push_back(num);
  403. unfoldSubRange(src.substr(p+1), range);
  404. } else if(src.at(p) == '-') {
  405. int32_t rightNumBegin = p+1;
  406. string::size_type nextDelim = src.find_first_of(",", rightNumBegin);
  407. if(nextDelim == string::npos) {
  408. nextDelim = src.size();
  409. }
  410. int32_t left = getNum(src.c_str(), 0, p);
  411. int32_t right = getNum(src.c_str(), rightNumBegin, nextDelim-rightNumBegin);
  412. for(int32_t i = left; i <= right; i++) {
  413. range.push_back(i);
  414. }
  415. if(src.size() > nextDelim) {
  416. unfoldSubRange(src.substr(nextDelim+1), range);
  417. }
  418. }
  419. }
  420. }
  421. void Util::unfoldRange(const string& src, Integers& range) {
  422. unfoldSubRange(src, range);
  423. sort(range.begin(), range.end());
  424. range.erase(unique(range.begin(), range.end()), range.end());
  425. }
  426. int32_t Util::parseInt(const string& s, int32_t base)
  427. {
  428. string trimed = Util::trim(s);
  429. if(trimed.empty()) {
  430. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  431. "empty string");
  432. }
  433. char* stop;
  434. errno = 0;
  435. long int v = strtol(trimed.c_str(), &stop, base);
  436. if(*stop != '\0') {
  437. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  438. trimed.c_str());
  439. } else if((v == LONG_MIN || v == LONG_MAX) && errno == ERANGE || v > INT32_MAX || v < INT32_MIN) {
  440. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  441. trimed.c_str());
  442. }
  443. return v;
  444. }
  445. int64_t Util::parseLLInt(const string& s, int32_t base)
  446. {
  447. string trimed = Util::trim(s);
  448. if(trimed.empty()) {
  449. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  450. "empty string");
  451. }
  452. char* stop;
  453. errno = 0;
  454. int64_t v = strtoll(trimed.c_str(), &stop, base);
  455. if(*stop != '\0') {
  456. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  457. trimed.c_str());
  458. } else if((v == INT64_MIN || v == INT64_MAX) && errno == ERANGE) {
  459. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  460. trimed.c_str());
  461. }
  462. return v;
  463. }
  464. IntSequence Util::parseIntRange(const string& src)
  465. {
  466. IntSequence::Values values;
  467. string temp = src;
  468. while(temp.size()) {
  469. pair<string, string> p = Util::split(temp, ",");
  470. temp = p.second;
  471. if(p.first.empty()) {
  472. continue;
  473. }
  474. if(p.first.find("-") == string::npos) {
  475. int32_t v = Util::parseInt(p.first.c_str());
  476. values.push_back(IntSequence::Value(v, v+1));
  477. } else {
  478. pair<string, string> vp = Util::split(p.first.c_str(), "-");
  479. if(vp.first.empty() || vp.second.empty()) {
  480. throw new DlAbortEx(MSG_INCOMPLETE_RANGE, p.first.c_str());
  481. }
  482. int32_t v1 = Util::parseInt(vp.first.c_str());
  483. int32_t v2 = Util::parseInt(vp.second.c_str());
  484. values.push_back(IntSequence::Value(v1, v2+1));
  485. }
  486. }
  487. return values;
  488. }
  489. string Util::getContentDispositionFilename(const string& header) {
  490. string keyName = "filename=";
  491. string::size_type attributesp = header.find(keyName);
  492. if(attributesp == string::npos) {
  493. return "";
  494. }
  495. string::size_type filenamesp = attributesp+strlen(keyName.c_str());
  496. string::size_type filenameep;
  497. if(filenamesp == header.size()) {
  498. return "";
  499. }
  500. if(header[filenamesp] == '\'' || header[filenamesp] == '"') {
  501. char quoteChar = header[filenamesp];
  502. filenameep = header.find(quoteChar, filenamesp+1);
  503. } else {
  504. filenameep = header.find(';', filenamesp);
  505. }
  506. if(filenameep == string::npos) {
  507. filenameep = header.size();
  508. }
  509. return trim(header.substr(filenamesp, filenameep-filenamesp), "\r\n '\"");
  510. }
  511. static int32_t nbits[] = {
  512. 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
  513. 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  514. 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  515. 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  516. 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  517. 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  518. 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  519. 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  520. 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  521. 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  522. 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  523. 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  524. 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  525. 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  526. 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  527. 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
  528. };
  529. int32_t Util::countBit(uint32_t n) {
  530. return
  531. nbits[n&0xffu]+
  532. nbits[(n >> 8)&0xffu]+
  533. nbits[(n >> 16)&0xffu]+
  534. nbits[(n >> 24)&0xffu];
  535. }
  536. string Util::randomAlpha(int32_t length, const RandomizerHandle& randomizer) {
  537. static const char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  538. string str;
  539. for(int32_t i = 0; i < length; i++) {
  540. int32_t index = randomizer->getRandomNumber(strlen(random_chars));
  541. str += random_chars[index];
  542. }
  543. return str;
  544. }
  545. string Util::toUpper(const string& src) {
  546. string temp = src;
  547. transform(temp.begin(), temp.end(), temp.begin(), ::toupper);
  548. return temp;
  549. }
  550. string Util::toLower(const string& src) {
  551. string temp = src;
  552. transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
  553. return temp;
  554. }
  555. bool Util::isNumbersAndDotsNotation(const string& name) {
  556. struct sockaddr_in sockaddr;
  557. if(inet_aton(name.c_str(), &sockaddr.sin_addr)) {
  558. return true;
  559. } else {
  560. return false;
  561. }
  562. }
  563. void Util::setGlobalSignalHandler(int32_t sig, void (*handler)(int), int32_t flags) {
  564. #ifdef HAVE_SIGACTION
  565. struct sigaction sigact;
  566. sigact.sa_handler = handler;
  567. sigact.sa_flags = flags;
  568. sigemptyset(&sigact.sa_mask);
  569. sigaction(sig, &sigact, NULL);
  570. #else
  571. signal(sig, handler);
  572. #endif // HAVE_SIGACTION
  573. }
  574. void Util::indexRange(int32_t& startIndex, int32_t& endIndex,
  575. int64_t offset, int32_t srcLength, int32_t destLength)
  576. {
  577. int64_t _startIndex = offset/destLength;
  578. int64_t _endIndex = (offset+srcLength-1)/destLength;
  579. assert(_startIndex <= INT32_MAX);
  580. assert(_endIndex <= INT32_MAX);
  581. startIndex = _startIndex;
  582. endIndex = _endIndex;
  583. }
  584. string Util::getHomeDir()
  585. {
  586. const char* p = getenv("HOME");
  587. if(p) {
  588. return p;
  589. } else {
  590. return "";
  591. }
  592. }
  593. int64_t Util::getRealSize(const string& sizeWithUnit)
  594. {
  595. string::size_type p = sizeWithUnit.find_first_of("KM");
  596. string size;
  597. int32_t mult = 1;
  598. if(p == string::npos) {
  599. size = sizeWithUnit;
  600. } else {
  601. if(sizeWithUnit[p] == 'K') {
  602. mult = 1024;
  603. } else if(sizeWithUnit[p] == 'M') {
  604. mult = 1024*1024;
  605. }
  606. size = sizeWithUnit.substr(0, p);
  607. }
  608. int64_t v = Util::parseLLInt(size);
  609. if(v < 0) {
  610. throw new DlAbortEx("Negative value detected: %s", sizeWithUnit.c_str());
  611. } else if(v*mult < 0) {
  612. throw new DlAbortEx(MSG_STRING_INTEGER_CONVERSION_FAILURE,
  613. "overflow/underflow");
  614. }
  615. return v*mult;
  616. }
  617. string Util::abbrevSize(int64_t size)
  618. {
  619. if(size < 1024) {
  620. return Util::llitos(size, true);
  621. }
  622. char units[] = { 'K', 'M' };
  623. int32_t numUnit = sizeof(units)/sizeof(char);
  624. int32_t i = 0;
  625. int32_t r = size&0x3ff;
  626. size >>= 10;
  627. for(; i < numUnit-1 && size >= 1024; ++i) {
  628. r = size&0x3ff;
  629. size >>= 10;
  630. }
  631. return Util::llitos(size, true)+"."+Util::itos(r*10/1024)+units[i]+"i";
  632. }
  633. time_t Util::httpGMT(const string& httpStdTime)
  634. {
  635. struct tm tm;
  636. memset(&tm, 0, sizeof(tm));
  637. strptime(httpStdTime.c_str(), "%a, %Y-%m-%d %H:%M:%S GMT", &tm);
  638. time_t thetime = timegm(&tm);
  639. return thetime;
  640. }
  641. void Util::toStream(ostream& os, const FileEntries& fileEntries)
  642. {
  643. os << _("Files:") << "\n";
  644. os << "idx|path/length" << "\n";
  645. os << "===+===========================================================================" << "\n";
  646. int32_t count = 1;
  647. for(FileEntries::const_iterator itr = fileEntries.begin();
  648. itr != fileEntries.end(); count++, itr++) {
  649. os << setw(3) << count << "|" << (*itr)->getPath() << "\n";
  650. os << " |" << Util::abbrevSize((*itr)->getLength()) << "B" << "\n";
  651. os << "---+---------------------------------------------------------------------------" << "\n";
  652. }
  653. }
  654. void Util::sleep(long seconds) {
  655. #ifdef HAVE_SLEEP
  656. ::sleep(seconds);
  657. #elif defined(HAVE_USLEEP)
  658. ::usleep(seconds * 1000000);
  659. #elif defined(HAVE_WINSOCK2_H)
  660. ::Sleep(seconds * 1000);
  661. #else
  662. #error no sleep function is available (nanosleep?)
  663. #endif
  664. }
  665. void Util::usleep(long microseconds) {
  666. #ifdef HAVE_USLEEP
  667. ::usleep(microseconds);
  668. #elif defined(HAVE_WINSOCK2_H)
  669. LARGE_INTEGER current, freq, end;
  670. static enum {GET_FREQUENCY, GET_MICROSECONDS, SKIP_MICROSECONDS} state = GET_FREQUENCY;
  671. if (state == GET_FREQUENCY) {
  672. if (QueryPerformanceFrequency(&freq))
  673. state = GET_MICROSECONDS;
  674. else
  675. state = SKIP_MICROSECONDS;
  676. }
  677. long msec = microseconds / 1000;
  678. microseconds %= 1000;
  679. if (state == GET_MICROSECONDS && microseconds) {
  680. QueryPerformanceCounter(&end);
  681. end.QuadPart += (freq.QuadPart * microseconds) / 1000000;
  682. while (QueryPerformanceCounter(&current) && (current.QuadPart <= end.QuadPart))
  683. /* noop */ ;
  684. }
  685. if (msec)
  686. Sleep(msec);
  687. #else
  688. #error no usleep function is available (nanosleep?)
  689. #endif
  690. }
  691. bool Util::isNumber(const string& what)
  692. {
  693. if(what.empty()) {
  694. return false;
  695. }
  696. for(uint32_t i = 0; i < what.size(); ++i) {
  697. if(!isdigit(what[i])) {
  698. return false;
  699. }
  700. }
  701. return true;
  702. }
  703. bool Util::isLowercase(const string& what)
  704. {
  705. if(what.empty()) {
  706. return false;
  707. }
  708. for(uint32_t i = 0; i < what.size(); ++i) {
  709. if(!('a' <= what[i] && what[i] <= 'z')) {
  710. return false;
  711. }
  712. }
  713. return true;
  714. }
  715. bool Util::isUppercase(const string& what)
  716. {
  717. if(what.empty()) {
  718. return false;
  719. }
  720. for(uint32_t i = 0; i < what.size(); ++i) {
  721. if(!('A' <= what[i] && what[i] <= 'Z')) {
  722. return false;
  723. }
  724. }
  725. return true;
  726. }
  727. int32_t Util::alphaToNum(const string& alphabets)
  728. {
  729. if(alphabets.empty()) {
  730. return 0;
  731. }
  732. char base;
  733. if(islower(alphabets[0])) {
  734. base = 'a';
  735. } else {
  736. base = 'A';
  737. }
  738. int32_t num = 0;
  739. for(uint32_t i = 0; i < alphabets.size(); ++i) {
  740. int32_t v = alphabets[i]-base;
  741. num = num*26+v;
  742. }
  743. return num;
  744. }
  745. void Util::mkdirs(const string& dirpath)
  746. {
  747. File dir(dirpath);
  748. if(dir.isDir()) {
  749. // do nothing
  750. } else if(dir.exists()) {
  751. throw new DlAbortEx(EX_MAKE_DIR, dir.getPath().c_str(), "File already exists.");
  752. } else if(!dir.mkdirs()) {
  753. throw new DlAbortEx(EX_MAKE_DIR, dir.getPath().c_str(), strerror(errno));
  754. }
  755. }
  756. void Util::convertBitfield(BitfieldMan* dest, const BitfieldMan* src)
  757. {
  758. for(int32_t index = 0; index < dest->countBlock(); ++index) {
  759. if(src->isBitSetOffsetRange((int64_t)index*dest->getBlockLength(),
  760. dest->getBlockLength())) {
  761. dest->setBit(index);
  762. }
  763. }
  764. }
  765. string Util::toString(const BinaryStreamHandle& binaryStream)
  766. {
  767. stringstream strm;
  768. char data[2048];
  769. while(1) {
  770. int32_t dataLength = binaryStream->readData((unsigned char*)data, sizeof(data), strm.tellp());
  771. strm.write(data, dataLength);
  772. if(dataLength == 0) {
  773. break;
  774. }
  775. }
  776. return strm.str();
  777. }
  778. #ifdef HAVE_POSIX_MEMALIGN
  779. /**
  780. * In linux 2.6, alignment and size should be a multiple of 512.
  781. */
  782. void* Util::allocateAlignedMemory(size_t alignment, size_t size)
  783. {
  784. void* buffer;
  785. int32_t res;
  786. if((res = posix_memalign(&buffer, alignment, size)) != 0) {
  787. throw new FatalException("Error in posix_memalign: %s", strerror(res));
  788. }
  789. return buffer;
  790. }
  791. #endif // HAVE_POSIX_MEMALIGN