XUtils.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. htop - StringUtils.c
  3. (C) 2004-2011 Hisham H. Muhammad
  4. Released under the GNU GPLv2+, see the COPYING file
  5. in the source distribution for its full text.
  6. */
  7. #include "config.h" // IWYU pragma: keep
  8. #include "XUtils.h"
  9. #include <assert.h>
  10. #include <errno.h>
  11. #include <fcntl.h>
  12. #include <math.h>
  13. #include <stdarg.h>
  14. #include <stdint.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include "CRT.h"
  19. #include "Macros.h"
  20. void fail(void) {
  21. CRT_done();
  22. abort();
  23. _exit(1); // Should never reach here
  24. }
  25. void* xMalloc(size_t size) {
  26. assert(size > 0);
  27. void* data = malloc(size);
  28. if (!data) {
  29. fail();
  30. }
  31. return data;
  32. }
  33. void* xMallocArray(size_t nmemb, size_t size) {
  34. assert(nmemb > 0);
  35. assert(size > 0);
  36. if (SIZE_MAX / nmemb < size) {
  37. fail();
  38. }
  39. return xMalloc(nmemb * size);
  40. }
  41. void* xCalloc(size_t nmemb, size_t size) {
  42. assert(nmemb > 0);
  43. assert(size > 0);
  44. if (SIZE_MAX / nmemb < size) {
  45. fail();
  46. }
  47. void* data = calloc(nmemb, size);
  48. if (!data) {
  49. fail();
  50. }
  51. return data;
  52. }
  53. void* xRealloc(void* ptr, size_t size) {
  54. assert(size > 0);
  55. void* data = realloc(ptr, size);
  56. if (!data) {
  57. /* free'ing ptr here causes an indirect memory leak if pointers
  58. * are held as part of an potential array referenced in ptr.
  59. * In GCC 14 -fanalyzer recognizes this leak, but fails to
  60. * ignore it given that this path ends in a noreturn function.
  61. * Thus to avoid this confusing diagnostic we opt to leave
  62. * that pointer alone instead.
  63. */
  64. // free(ptr);
  65. fail();
  66. }
  67. return data;
  68. }
  69. void* xReallocArray(void* ptr, size_t nmemb, size_t size) {
  70. assert(nmemb > 0);
  71. assert(size > 0);
  72. if (SIZE_MAX / nmemb < size) {
  73. fail();
  74. }
  75. return xRealloc(ptr, nmemb * size);
  76. }
  77. void* xReallocArrayZero(void* ptr, size_t prevmemb, size_t newmemb, size_t size) {
  78. assert((ptr == NULL) == (prevmemb == 0));
  79. if (prevmemb == newmemb) {
  80. return ptr;
  81. }
  82. void* ret = xReallocArray(ptr, newmemb, size);
  83. if (newmemb > prevmemb) {
  84. memset((unsigned char*)ret + prevmemb * size, '\0', (newmemb - prevmemb) * size);
  85. }
  86. return ret;
  87. }
  88. inline bool String_contains_i(const char* s1, const char* s2, bool multi) {
  89. // we have a multi-string search term, handle as special case for performance reasons
  90. if (multi && strstr(s2, "|")) {
  91. size_t nNeedles;
  92. char** needles = String_split(s2, '|', &nNeedles);
  93. for (size_t i = 0; i < nNeedles; i++) {
  94. if (strcasestr(s1, needles[i]) != NULL) {
  95. String_freeArray(needles);
  96. return true;
  97. }
  98. }
  99. String_freeArray(needles);
  100. return false;
  101. } else {
  102. return strcasestr(s1, s2) != NULL;
  103. }
  104. }
  105. char* String_cat(const char* s1, const char* s2) {
  106. const size_t l1 = strlen(s1);
  107. const size_t l2 = strlen(s2);
  108. if (SIZE_MAX - l1 <= l2) {
  109. fail();
  110. }
  111. char* out = xMalloc(l1 + l2 + 1);
  112. memcpy(out, s1, l1);
  113. memcpy(out + l1, s2, l2);
  114. out[l1 + l2] = '\0';
  115. return out;
  116. }
  117. char* String_trim(const char* in) {
  118. while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') {
  119. in++;
  120. }
  121. size_t len = strlen(in);
  122. while (len > 0 && (in[len - 1] == ' ' || in[len - 1] == '\t' || in[len - 1] == '\n')) {
  123. len--;
  124. }
  125. return xStrndup(in, len);
  126. }
  127. char** String_split(const char* s, char sep, size_t* n) {
  128. const size_t rate = 10;
  129. char** out = xCalloc(rate, sizeof(char*));
  130. size_t ctr = 0;
  131. size_t blocks = rate;
  132. const char* where;
  133. while ((where = strchr(s, sep)) != NULL) {
  134. size_t size = (size_t)(where - s);
  135. out[ctr] = xStrndup(s, size);
  136. ctr++;
  137. if (ctr == blocks) {
  138. blocks += rate;
  139. out = (char**) xRealloc(out, sizeof(char*) * blocks);
  140. }
  141. s += size + 1;
  142. }
  143. if (s[0] != '\0') {
  144. out[ctr] = xStrdup(s);
  145. ctr++;
  146. }
  147. out = xRealloc(out, sizeof(char*) * (ctr + 1));
  148. out[ctr] = NULL;
  149. if (n)
  150. *n = ctr;
  151. return out;
  152. }
  153. void String_freeArray(char** s) {
  154. if (!s) {
  155. return;
  156. }
  157. for (size_t i = 0; s[i] != NULL; i++) {
  158. free(s[i]);
  159. }
  160. free(s);
  161. }
  162. char* String_readLine(FILE* fp) {
  163. const size_t step = 1024;
  164. size_t bufSize = step;
  165. char* buffer = xMalloc(step + 1);
  166. char* at = buffer;
  167. for (;;) {
  168. const char* ok = fgets(at, step + 1, fp);
  169. if (!ok) {
  170. free(buffer);
  171. return NULL;
  172. }
  173. char* newLine = strrchr(at, '\n');
  174. if (newLine) {
  175. *newLine = '\0';
  176. return buffer;
  177. } else {
  178. if (feof(fp)) {
  179. return buffer;
  180. }
  181. }
  182. bufSize += step;
  183. buffer = xRealloc(buffer, bufSize + 1);
  184. at = buffer + bufSize - step;
  185. }
  186. }
  187. size_t String_safeStrncpy(char* restrict dest, const char* restrict src, size_t size) {
  188. assert(size > 0);
  189. size_t i = 0;
  190. for (; i < size - 1 && src[i]; i++)
  191. dest[i] = src[i];
  192. dest[i] = '\0';
  193. return i;
  194. }
  195. int xAsprintf(char** strp, const char* fmt, ...) {
  196. va_list vl;
  197. va_start(vl, fmt);
  198. int r = vasprintf(strp, fmt, vl);
  199. va_end(vl);
  200. if (r < 0 || !*strp) {
  201. fail();
  202. }
  203. return r;
  204. }
  205. int xSnprintf(char* buf, size_t len, const char* fmt, ...) {
  206. assert(len > 0);
  207. va_list vl;
  208. va_start(vl, fmt);
  209. int n = vsnprintf(buf, len, fmt, vl);
  210. va_end(vl);
  211. if (n < 0 || (size_t)n >= len) {
  212. fail();
  213. }
  214. return n;
  215. }
  216. char* xStrdup(const char* str) {
  217. char* data = strdup(str);
  218. if (!data) {
  219. fail();
  220. }
  221. return data;
  222. }
  223. void free_and_xStrdup(char** ptr, const char* str) {
  224. if (*ptr && String_eq(*ptr, str))
  225. return;
  226. free(*ptr);
  227. *ptr = xStrdup(str);
  228. }
  229. char* xStrndup(const char* str, size_t len) {
  230. char* data = strndup(str, len);
  231. if (!data) {
  232. fail();
  233. }
  234. return data;
  235. }
  236. ATTR_ACCESS3_W(2, 3)
  237. static ssize_t readfd_internal(int fd, void* buffer, size_t count) {
  238. if (!count) {
  239. close(fd);
  240. return -EINVAL;
  241. }
  242. ssize_t alreadyRead = 0;
  243. count--; // reserve one for null-terminator
  244. for (;;) {
  245. ssize_t res = read(fd, buffer, count);
  246. if (res == -1) {
  247. if (errno == EINTR)
  248. continue;
  249. close(fd);
  250. *((char*)buffer) = '\0';
  251. return -errno;
  252. }
  253. if (res > 0) {
  254. assert((size_t)res <= count);
  255. buffer = ((char*)buffer) + res;
  256. count -= (size_t)res;
  257. alreadyRead += res;
  258. }
  259. if (count == 0 || res == 0) {
  260. close(fd);
  261. *((char*)buffer) = '\0';
  262. return alreadyRead;
  263. }
  264. }
  265. }
  266. ssize_t xReadfile(const char* pathname, void* buffer, size_t count) {
  267. int fd = open(pathname, O_RDONLY);
  268. if (fd < 0)
  269. return -errno;
  270. return readfd_internal(fd, buffer, count);
  271. }
  272. ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count) {
  273. int fd = Compat_openat(dirfd, pathname, O_RDONLY);
  274. if (fd < 0)
  275. return -errno;
  276. return readfd_internal(fd, buffer, count);
  277. }
  278. ssize_t full_write(int fd, const void* buf, size_t count) {
  279. ssize_t written = 0;
  280. while (count > 0) {
  281. ssize_t r = write(fd, buf, count);
  282. if (r < 0) {
  283. if (errno == EINTR)
  284. continue;
  285. return r;
  286. }
  287. if (r == 0)
  288. break;
  289. written += r;
  290. buf = (const unsigned char*)buf + r;
  291. count -= (size_t)r;
  292. }
  293. return written;
  294. }
  295. /* Compares floating point values for ordering data entries. In this function,
  296. NaN is considered "less than" any other floating point value (regardless of
  297. sign), and two NaNs are considered "equal" regardless of payload. */
  298. int compareRealNumbers(double a, double b) {
  299. int result = isgreater(a, b) - isgreater(b, a);
  300. if (result)
  301. return result;
  302. return !isNaN(a) - !isNaN(b);
  303. }
  304. /* Computes the sum of all positive floating point values in an array.
  305. NaN values in the array are skipped. The returned sum will always be
  306. nonnegative. */
  307. double sumPositiveValues(const double* array, size_t count) {
  308. double sum = 0.0;
  309. for (size_t i = 0; i < count; i++) {
  310. if (isPositive(array[i]))
  311. sum += array[i];
  312. }
  313. return sum;
  314. }
  315. #if !defined(HAVE_BUILTIN_CTZ)
  316. // map a bit value mod 37 to its position
  317. static const uint8_t mod37BitPosition[] = {
  318. 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4,
  319. 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5,
  320. 20, 8, 19, 18
  321. };
  322. /* Returns the number of trailing zero bits */
  323. unsigned int countTrailingZeros(unsigned int x) {
  324. return mod37BitPosition[(-x & x) % 37];
  325. }
  326. #endif