hidl_utils.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include "hidl_utils.hpp"
  15. // borrow from jlib
  16. bool checkDirExists(const char * filename)
  17. {
  18. #ifdef _WIN32
  19. DWORD attr = GetFileAttributes(filename);
  20. return (attr != (DWORD)-1)&&(attr & FILE_ATTRIBUTE_DIRECTORY);
  21. #else
  22. struct stat info;
  23. if (stat(filename, &info) != 0)
  24. return false;
  25. return S_ISDIR(info.st_mode);
  26. #endif
  27. }
  28. void createDirectory(const char* dir)
  29. {
  30. if (dir && *dir)
  31. {
  32. if (!checkDirExists(dir)) {
  33. #ifdef WIN32
  34. if (mkdir(dir)!=0)
  35. #else
  36. if (mkdir(dir,0755)!=0)
  37. #endif
  38. {
  39. if (!checkDirExists(dir))
  40. {
  41. fprintf(stderr,"Create directory %s failed", dir);
  42. exit(1);
  43. }
  44. }
  45. }
  46. }
  47. }
  48. int createFile(const char* src, const char* ext)
  49. {
  50. char * path = changeext(src,ext);
  51. //printf("Target: %s\n", path);
  52. int h = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_TEXT , _S_IREAD|_S_IWRITE);
  53. if (h==-1)
  54. {
  55. printf("Could not open file for write: %s (current dir: %s)\n",path,getcwd(NULL,0));
  56. }
  57. free(path);
  58. return h;
  59. }
  60. char * gettail(const char *fn)
  61. {
  62. const char *e=NULL;
  63. const char *e1=fn;
  64. while((e1=strchr(e1,'.'))!=NULL)
  65. e = e1++;
  66. const char *s=fn;
  67. const char *s1;
  68. #ifdef _WIN32
  69. if (*s&&s[1]==':')
  70. s+=2;
  71. #endif
  72. for (s1 = s;*s1&&(s1!=e);s1++)
  73. {
  74. if (*s1=='\\' || *s1=='/')
  75. s = s1+1;
  76. }
  77. size_t l = s1-s;
  78. char *ret = (char *)malloc(l+1);
  79. memcpy(ret,s,l);
  80. ret[l] = 0;
  81. return ret;
  82. }
  83. char * changeext(const char *fn,const char *ext)
  84. {
  85. int preext, l;
  86. preext = l = (int)strlen(fn);
  87. char *p;
  88. for (p=(char*)(fn+preext-1); p>=fn; p--)
  89. {
  90. if (*p == '.')
  91. {
  92. preext = (int)(p-fn);
  93. break;
  94. }
  95. }
  96. // char *ret=gettail(fn);
  97. // size_t l = strlen(ret);
  98. // ret = (char *)realloc(ret,l+strlen(ext)+2);
  99. char *ret = (char *)malloc(preext+strlen(ext)+2);
  100. memcpy(ret, fn, preext);
  101. ret[preext] = '.';
  102. strcpy(ret+preext+1,ext);
  103. return ret;
  104. }
  105. char * changetail(const char *fn,const char *tail, const char *ext)
  106. {
  107. int preext, l;
  108. preext = l = (int)strlen(fn);
  109. char *p;
  110. for (p=(char*)(fn+preext-1); p>=fn; p--)
  111. {
  112. if (*p == '.')
  113. {
  114. preext = (int)(p-fn);
  115. break;
  116. }
  117. }
  118. char *ret = (char *)malloc(preext+strlen(tail)+strlen(ext)+2);
  119. memcpy(ret, fn, preext);
  120. ret[preext] = 0;
  121. strcat(ret,tail);
  122. strcat(ret,".");
  123. strcat(ret,ext);
  124. return ret;
  125. }
  126. bool hasext(const char *fn,const char *ext)
  127. { // assumes 3 char ext
  128. const char *s = strstr(fn,ext);
  129. if (!s)
  130. return false;
  131. return (s!=fn)&&(*(s-1)=='.')&&(s[4]==0);
  132. }
  133. int createFile(const char* src, const char* tail, const char* ext)
  134. {
  135. char * path=changetail(src,tail,ext);
  136. int h = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_TEXT , _S_IREAD|_S_IWRITE);
  137. if (h==-1)
  138. {
  139. printf("Could not open file for write: %s (current dir: %s)\n",path,getcwd(NULL,0));
  140. }
  141. free(path);
  142. return h;
  143. }
  144. //==============================================================
  145. // class StrBuffer
  146. #include <stdarg.h>
  147. static const char * TheNullStr = "";
  148. #define FIRST_CHUNK_SIZE 8
  149. #define DOUBLE_LIMIT 0x100000 // must be a power of 2
  150. //#define DETACH_GRANULARITY 16
  151. StrBuffer::StrBuffer()
  152. {
  153. init();
  154. }
  155. StrBuffer::StrBuffer(const char *value)
  156. {
  157. init();
  158. append(value);
  159. }
  160. StrBuffer::StrBuffer(unsigned len, const char *value)
  161. {
  162. init();
  163. append(len, value);
  164. }
  165. void StrBuffer::_realloc(size32_t newLen)
  166. {
  167. if (newLen >= maxLen)
  168. {
  169. size32_t newMax = maxLen;
  170. if (newMax == 0)
  171. newMax = FIRST_CHUNK_SIZE;
  172. if (newLen > DOUBLE_LIMIT)
  173. {
  174. newMax = (newLen + DOUBLE_LIMIT) & ~(DOUBLE_LIMIT-1);
  175. if (newLen >= newMax)
  176. throw "StrBuffer::_realloc: Request for memory is too big";
  177. }
  178. else
  179. {
  180. while (newLen >= newMax)
  181. newMax += newMax;
  182. }
  183. char * newStr;
  184. if(!newMax || !(newStr=(char *)realloc(buffer, newMax)))
  185. throw "StrBuffer::_realloc: Failed to realloc memory";
  186. buffer = newStr;
  187. maxLen = newMax;
  188. }
  189. }
  190. StrBuffer & StrBuffer::append(int value)
  191. {
  192. char temp[12];
  193. unsigned written = sprintf(temp, "%d", value);
  194. return append(written, temp);
  195. }
  196. StrBuffer & StrBuffer::append(unsigned int value)
  197. {
  198. char temp[12];
  199. unsigned written = sprintf(temp, "%u", value);
  200. return append(written, temp);
  201. }
  202. StrBuffer & StrBuffer::append(char c)
  203. {
  204. appendf("%c",c);
  205. return *this;
  206. }
  207. StrBuffer & StrBuffer::append(double value)
  208. {
  209. char temp[317];
  210. unsigned written = sprintf(temp, "%g", value);
  211. return append(written, temp);
  212. }
  213. StrBuffer & StrBuffer::append(const char * value)
  214. {
  215. if (value)
  216. {
  217. size32_t SourceLen = (size32_t)::strlen(value);
  218. ensureCapacity(SourceLen);
  219. memcpy(buffer + curLen, value, SourceLen);
  220. curLen += SourceLen;
  221. }
  222. return *this;
  223. }
  224. StrBuffer & StrBuffer::append(unsigned len, const char * value)
  225. {
  226. if (len)
  227. {
  228. ensureCapacity(len);
  229. memcpy(buffer + curLen, value, len);
  230. curLen += len;
  231. }
  232. return *this;
  233. }
  234. StrBuffer & StrBuffer::appendf(const char *format, ...)
  235. {
  236. va_list args;
  237. va_start(args, format);
  238. va_append(format, args);
  239. va_end(args);
  240. return *this;
  241. }
  242. StrBuffer & StrBuffer::setf(const char *format, ...)
  243. {
  244. clear();
  245. va_list args;
  246. va_start(args, format);
  247. va_append(format, args);
  248. va_end(args);
  249. return *this;
  250. }
  251. StrBuffer & StrBuffer::va_append(const char *format, va_list args)
  252. {
  253. const int BUF_SIZE = 1024;
  254. char buf[BUF_SIZE];
  255. int len = _vsnprintf(buf,sizeof(buf),format,args);
  256. if (len >= 0)
  257. {
  258. if (len < BUF_SIZE)
  259. append(len, buf);
  260. else
  261. {
  262. ensureCapacity(len);
  263. // no need for _vsnprintf since the buffer is already made big enough
  264. vsprintf(buffer+curLen,format,args);
  265. curLen += len;
  266. }
  267. }
  268. else
  269. {
  270. size32_t size = BUF_SIZE * 2;
  271. char* pbuf = (char *)malloc(size);
  272. while ((len = _vsnprintf(pbuf,size,format,args)) < 0)
  273. {
  274. size <<= 1;
  275. pbuf = (char*)realloc(pbuf,size);
  276. }
  277. append(len, pbuf);
  278. free(pbuf);
  279. }
  280. return *this;
  281. }
  282. const char * StrBuffer::str() const
  283. {
  284. if (buffer)
  285. {
  286. buffer[curLen] = '\0'; // There is always room for this null
  287. return buffer;
  288. }
  289. return TheNullStr;
  290. }
  291. void StrBuffer::setLength(unsigned len)
  292. {
  293. if (len > curLen)
  294. {
  295. ensureCapacity(len-curLen);
  296. }
  297. curLen = len;
  298. }
  299. VStrBuffer::VStrBuffer(const char* format, ...)
  300. {
  301. va_list args;
  302. va_start(args,format);
  303. va_append(format,args);
  304. va_end(args);
  305. }
  306. StrBuffer& printfEncode(const char* src, StrBuffer& encoded)
  307. {
  308. for (const char* p = src; *p!=0; p++)
  309. {
  310. switch(*p)
  311. {
  312. case '%': encoded.append("%%%%"); break;
  313. case '\\': encoded.append("\\\\"); break;
  314. case '"': encoded.append("\\\""); break;
  315. default: encoded.appendf("%c",*p); break;
  316. }
  317. }
  318. return encoded;
  319. }
  320. // steal from jlib with some simplification
  321. StrBuffer& encodeXML(const char *x, StrBuffer &ret)
  322. {
  323. while (true)
  324. {
  325. switch(*x)
  326. {
  327. case '&':
  328. ret.append("&amp;");
  329. break;
  330. case '<':
  331. ret.append("&lt;");
  332. break;
  333. case '>':
  334. ret.append("&gt;");
  335. break;
  336. case '\"':
  337. ret.append("&quot;");
  338. break;
  339. case '\'':
  340. ret.append("&apos;");
  341. break;
  342. case ' ':
  343. //ret.append("&#32;");
  344. ret.append(" ");
  345. break;
  346. case '\n':
  347. ret.append("&#10;");
  348. break;
  349. case '\r':
  350. ret.append("&#13;");
  351. break;
  352. case '\t':
  353. ret.append("&#9;");
  354. break;
  355. case '\0':
  356. return ret;
  357. default:
  358. if (*x >= ' ' && ((byte)*x) < 128)
  359. ret.append(*x);
  360. else if (*x < ' ' && *x > 0)
  361. ret.append("&#xe0").append((unsigned int)*(unsigned char *) x).append(';'); // HACK
  362. else
  363. ret.append("&#").append((unsigned int)*(unsigned char *) x).append(';');
  364. break;
  365. }
  366. ++x;
  367. }
  368. return ret;
  369. }
  370. // borrow from hqltest
  371. void initLeakCheck(bool fullMemoryCheck)
  372. {
  373. #if defined(_WIN32) && defined(_DEBUG)
  374. _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG );
  375. _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
  376. _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG );
  377. _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
  378. _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG );
  379. _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
  380. //
  381. // set the states we want to monitor
  382. //
  383. int LeakTmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  384. LeakTmpFlag &= ~_CRTDBG_CHECK_CRT_DF;
  385. LeakTmpFlag |= _CRTDBG_LEAK_CHECK_DF;
  386. if (fullMemoryCheck)
  387. {
  388. LeakTmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
  389. LeakTmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
  390. /* This check is not needed since CRT block only exists in debug version */
  391. // LeakTmpFlag |= _CRTDBG_CHECK_CRT_DF;
  392. }
  393. _CrtSetDbgFlag(LeakTmpFlag);
  394. #endif
  395. }