gstr.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. /*
  2. * gstr.c: String Utility Functions.
  3. *
  4. * Author:
  5. * Miguel de Icaza (miguel@novell.com)
  6. * Aaron Bockover (abockover@novell.com)
  7. *
  8. * (C) 2006 Novell, Inc.
  9. *
  10. * Permission is hereby granted, free of charge, to any person obtaining
  11. * a copy of this software and associated documentation files (the
  12. * "Software"), to deal in the Software without restriction, including
  13. * without limitation the rights to use, copy, modify, merge, publish,
  14. * distribute, sublicense, and/or sell copies of the Software, and to
  15. * permit persons to whom the Software is furnished to do so, subject to
  16. * the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be
  19. * included in all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. */
  29. #include <config.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <glib.h>
  34. #ifndef G_OS_WIN32
  35. #include <pthread.h>
  36. #endif
  37. #include <errno.h>
  38. /*
  39. * g_strndup and g_vasprintf need to allocate memory with g_malloc if
  40. * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free
  41. * rather than free.
  42. */
  43. /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
  44. gchar *
  45. g_strndup (const gchar *str, gsize n)
  46. {
  47. #if defined (HAVE_STRNDUP) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS)
  48. return strndup (str, n);
  49. #else
  50. if (str) {
  51. char *retval = g_malloc(n+1);
  52. if (retval) {
  53. strncpy(retval, str, n)[n] = 0;
  54. }
  55. return retval;
  56. }
  57. return NULL;
  58. #endif
  59. }
  60. gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap)
  61. {
  62. #if defined (HAVE_VASPRINTF) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS)
  63. return vasprintf (ret, fmt, ap);
  64. #else
  65. char *buf;
  66. int len;
  67. size_t buflen;
  68. va_list ap2;
  69. #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
  70. ap2 = ap;
  71. len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( )
  72. #else
  73. va_copy(ap2, ap);
  74. len = vsnprintf(NULL, 0, fmt, ap2);
  75. #endif
  76. if (len >= 0 && (buf = g_malloc ((buflen = (size_t) (len + 1)))) != NULL) {
  77. len = vsnprintf(buf, buflen, fmt, ap);
  78. *ret = buf;
  79. } else {
  80. *ret = NULL;
  81. len = -1;
  82. }
  83. va_end(ap2);
  84. return len;
  85. #endif
  86. }
  87. void
  88. g_strfreev (gchar **str_array)
  89. {
  90. gchar **orig = str_array;
  91. if (str_array == NULL)
  92. return;
  93. while (*str_array != NULL){
  94. g_free (*str_array);
  95. str_array++;
  96. }
  97. g_free (orig);
  98. }
  99. gchar **
  100. g_strdupv (gchar **str_array)
  101. {
  102. guint length;
  103. gchar **ret;
  104. guint i;
  105. if (!str_array)
  106. return NULL;
  107. length = g_strv_length(str_array);
  108. ret = g_new0(gchar *, length + 1);
  109. for (i = 0; str_array[i]; i++) {
  110. ret[i] = g_strdup(str_array[i]);
  111. }
  112. ret[length] = NULL;
  113. return ret;
  114. }
  115. guint
  116. g_strv_length(gchar **str_array)
  117. {
  118. gint length = 0;
  119. g_return_val_if_fail(str_array != NULL, 0);
  120. for(length = 0; str_array[length] != NULL; length++);
  121. return length;
  122. }
  123. gboolean
  124. g_str_has_suffix(const gchar *str, const gchar *suffix)
  125. {
  126. size_t str_length;
  127. size_t suffix_length;
  128. g_return_val_if_fail(str != NULL, FALSE);
  129. g_return_val_if_fail(suffix != NULL, FALSE);
  130. str_length = strlen(str);
  131. suffix_length = strlen(suffix);
  132. return suffix_length <= str_length ?
  133. strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0 :
  134. FALSE;
  135. }
  136. gboolean
  137. g_str_has_prefix(const gchar *str, const gchar *prefix)
  138. {
  139. size_t str_length;
  140. size_t prefix_length;
  141. g_return_val_if_fail(str != NULL, FALSE);
  142. g_return_val_if_fail(prefix != NULL, FALSE);
  143. str_length = strlen(str);
  144. prefix_length = strlen(prefix);
  145. return prefix_length <= str_length ?
  146. strncmp(str, prefix, prefix_length) == 0 :
  147. FALSE;
  148. }
  149. gchar *
  150. g_strdup_vprintf (const gchar *format, va_list args)
  151. {
  152. int n;
  153. char *ret;
  154. n = g_vasprintf (&ret, format, args);
  155. if (n == -1)
  156. return NULL;
  157. return ret;
  158. }
  159. gchar *
  160. g_strdup_printf (const gchar *format, ...)
  161. {
  162. gchar *ret;
  163. va_list args;
  164. int n;
  165. va_start (args, format);
  166. n = g_vasprintf (&ret, format, args);
  167. va_end (args);
  168. if (n == -1)
  169. return NULL;
  170. return ret;
  171. }
  172. /*
  173. Max error number we support. It's empirically found by looking at our target OS.
  174. Last this was checked was June-2017.
  175. Apple is at 106.
  176. Android is at 133.
  177. Haiku starts numbering at 0x8000_7000 (like HRESULT on Win32) for POSIX errno,
  178. but errors from BeAPI or custom user libraries could be lower or higher.
  179. (Technically, this is C and old POSIX compliant, but not new POSIX compliant.)
  180. The big problem with this is that it effectively means errors start at a
  181. negative offset. As such, disable the whole strerror caching mechanism.
  182. */
  183. #define MONO_ERRNO_MAX 200
  184. #define str(s) #s
  185. #ifndef G_OS_WIN32
  186. static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER;
  187. #endif
  188. #if defined(__HAIKU__)
  189. const gchar *
  190. g_strerror (gint errnum)
  191. {
  192. /* returns a const char* on Haiku */
  193. return strerror(errnum);
  194. }
  195. #else
  196. static char *error_messages [MONO_ERRNO_MAX];
  197. const gchar *
  198. g_strerror (gint errnum)
  199. {
  200. if (errnum < 0)
  201. errnum = -errnum;
  202. if (errnum >= MONO_ERRNO_MAX)
  203. return ("Error number higher than " str (MONO_ERRNO_MAX));
  204. if (!error_messages [errnum]) {
  205. #ifndef G_OS_WIN32
  206. pthread_mutex_lock (&strerror_lock);
  207. #endif
  208. #ifdef HAVE_STRERROR_R
  209. char tmp_buff [128]; //Quite arbitrary, should be large enough
  210. char *buff = tmp_buff;
  211. size_t buff_len = sizeof (tmp_buff);
  212. buff [0] = 0;
  213. #ifndef STRERROR_R_CHAR_P
  214. int r;
  215. while ((r = strerror_r (errnum, buff, buff_len - 1))) {
  216. if (r != ERANGE) {
  217. buff = g_strdup_printf ("Invalid Error code '%d'", errnum);
  218. break;
  219. }
  220. if (buff == tmp_buff)
  221. buff = g_malloc (buff_len * 2);
  222. else
  223. buff = g_realloc (buff, buff_len * 2);
  224. buff_len *= 2;
  225. //Spec is not clean on whether size argument includes space for null terminator or not
  226. }
  227. if (!error_messages [errnum])
  228. error_messages [errnum] = g_strdup (buff);
  229. if (buff != tmp_buff)
  230. g_free (buff);
  231. #else /* STRERROR_R_CHAR_P */
  232. buff = strerror_r (errnum, buff, buff_len);
  233. if (!error_messages [errnum])
  234. error_messages [errnum] = g_strdup (buff);
  235. #endif /* STRERROR_R_CHAR_P */
  236. #else /* HAVE_STRERROR_R */
  237. if (!error_messages [errnum])
  238. error_messages [errnum] = g_strdup_printf ("Error code '%d'", errnum);
  239. #endif /* HAVE_STRERROR_R */
  240. #ifndef G_OS_WIN32
  241. pthread_mutex_unlock (&strerror_lock);
  242. #endif
  243. }
  244. return error_messages [errnum];
  245. }
  246. #endif
  247. gchar *
  248. g_strconcat (const gchar *first, ...)
  249. {
  250. va_list args;
  251. char *s, *ret;
  252. g_return_val_if_fail (first != NULL, NULL);
  253. size_t len = strlen (first);
  254. va_start (args, first);
  255. for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
  256. len += strlen (s);
  257. }
  258. va_end (args);
  259. ret = (char*)g_malloc (len + 1);
  260. if (ret == NULL)
  261. return NULL;
  262. ret [len] = 0;
  263. len = strlen (first);
  264. memcpy (ret, first, len);
  265. va_start (args, first);
  266. first = ret; // repurpose first as cursor
  267. for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
  268. first += len;
  269. memcpy ((char*)first, s, len = strlen (s));
  270. }
  271. va_end (args);
  272. return ret;
  273. }
  274. static void
  275. add_to_vector (gchar ***vector, int size, gchar *token)
  276. {
  277. *vector = *vector == NULL ?
  278. (gchar **)g_malloc(2 * sizeof(*vector)) :
  279. (gchar **)g_realloc(*vector, (size + 1) * sizeof(*vector));
  280. (*vector)[size - 1] = token;
  281. }
  282. gchar **
  283. g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
  284. {
  285. const gchar *c;
  286. gchar *token, **vector;
  287. gint size = 1;
  288. g_return_val_if_fail (string != NULL, NULL);
  289. g_return_val_if_fail (delimiter != NULL, NULL);
  290. g_return_val_if_fail (delimiter[0] != 0, NULL);
  291. if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
  292. vector = (gchar **)g_malloc (2 * sizeof(vector));
  293. vector[0] = g_strdup ("");
  294. size++;
  295. string += strlen (delimiter);
  296. } else {
  297. vector = NULL;
  298. }
  299. while (*string && !(max_tokens > 0 && size >= max_tokens)) {
  300. c = string;
  301. if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
  302. token = g_strdup ("");
  303. string += strlen (delimiter);
  304. } else {
  305. while (*string && strncmp (string, delimiter, strlen (delimiter)) != 0) {
  306. string++;
  307. }
  308. if (*string) {
  309. gsize toklen = (string - c);
  310. token = g_strndup (c, toklen);
  311. /* Need to leave a trailing empty
  312. * token if the delimiter is the last
  313. * part of the string
  314. */
  315. if (strcmp (string, delimiter) != 0) {
  316. string += strlen (delimiter);
  317. }
  318. } else {
  319. token = g_strdup (c);
  320. }
  321. }
  322. add_to_vector (&vector, size, token);
  323. size++;
  324. }
  325. if (*string) {
  326. if (strcmp (string, delimiter) == 0)
  327. add_to_vector (&vector, size, g_strdup (""));
  328. else {
  329. /* Add the rest of the string as the last element */
  330. add_to_vector (&vector, size, g_strdup (string));
  331. }
  332. size++;
  333. }
  334. if (vector == NULL) {
  335. vector = (gchar **) g_malloc (2 * sizeof (vector));
  336. vector [0] = NULL;
  337. } else if (size > 0) {
  338. vector[size - 1] = NULL;
  339. }
  340. return vector;
  341. }
  342. static gboolean
  343. charcmp (gchar testchar, const gchar *compare)
  344. {
  345. while(*compare) {
  346. if (*compare == testchar) {
  347. return TRUE;
  348. }
  349. compare++;
  350. }
  351. return FALSE;
  352. }
  353. gchar **
  354. g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens)
  355. {
  356. const gchar *c;
  357. gchar *token, **vector;
  358. gint size = 1;
  359. g_return_val_if_fail (string != NULL, NULL);
  360. g_return_val_if_fail (delimiter != NULL, NULL);
  361. g_return_val_if_fail (delimiter[0] != 0, NULL);
  362. if (charcmp (*string, delimiter)) {
  363. vector = (gchar **)g_malloc (2 * sizeof(vector));
  364. vector[0] = g_strdup ("");
  365. size++;
  366. string++;
  367. } else {
  368. vector = NULL;
  369. }
  370. c = string;
  371. while (*string && !(max_tokens > 0 && size >= max_tokens)) {
  372. if (charcmp (*string, delimiter)) {
  373. gsize toklen = (string - c);
  374. if (toklen == 0) {
  375. token = g_strdup ("");
  376. } else {
  377. token = g_strndup (c, toklen);
  378. }
  379. c = string + 1;
  380. add_to_vector (&vector, size, token);
  381. size++;
  382. }
  383. string++;
  384. }
  385. if (max_tokens > 0 && size >= max_tokens) {
  386. if (*string) {
  387. /* Add the rest of the string as the last element */
  388. add_to_vector (&vector, size, g_strdup (string));
  389. size++;
  390. }
  391. } else {
  392. if (*c) {
  393. /* Fill in the trailing last token */
  394. add_to_vector (&vector, size, g_strdup (c));
  395. size++;
  396. } else {
  397. /* Need to leave a trailing empty token if the
  398. * delimiter is the last part of the string
  399. */
  400. add_to_vector (&vector, size, g_strdup (""));
  401. size++;
  402. }
  403. }
  404. if (vector == NULL) {
  405. vector = (gchar **) g_malloc (2 * sizeof (vector));
  406. vector [0] = NULL;
  407. } else if (size > 0) {
  408. vector[size - 1] = NULL;
  409. }
  410. return vector;
  411. }
  412. gchar *
  413. g_strreverse (gchar *str)
  414. {
  415. size_t i, j;
  416. gchar c;
  417. if (str == NULL)
  418. return NULL;
  419. if (*str == 0)
  420. return str;
  421. for (i = 0, j = strlen (str) - 1; i < j; i++, j--) {
  422. c = str [i];
  423. str [i] = str [j];
  424. str [j] = c;
  425. }
  426. return str;
  427. }
  428. gchar *
  429. g_strjoin (const gchar *separator, ...)
  430. {
  431. va_list args;
  432. char *res, *s, *r;
  433. size_t len, slen;
  434. if (separator != NULL)
  435. slen = strlen (separator);
  436. else
  437. slen = 0;
  438. len = 0;
  439. va_start (args, separator);
  440. for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
  441. len += strlen (s);
  442. len += slen;
  443. }
  444. va_end (args);
  445. if (len == 0)
  446. return g_strdup ("");
  447. /* Remove the last separator */
  448. if (slen > 0 && len > 0)
  449. len -= slen;
  450. res = (char*)g_malloc (len + 1);
  451. va_start (args, separator);
  452. s = va_arg (args, char *);
  453. r = g_stpcpy (res, s);
  454. for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
  455. if (separator != NULL)
  456. r = g_stpcpy (r, separator);
  457. r = g_stpcpy (r, s);
  458. }
  459. va_end (args);
  460. return res;
  461. }
  462. gchar *
  463. g_strjoinv (const gchar *separator, gchar **str_array)
  464. {
  465. char *res, *r;
  466. size_t slen, len, i;
  467. if (separator != NULL)
  468. slen = strlen (separator);
  469. else
  470. slen = 0;
  471. len = 0;
  472. for (i = 0; str_array [i] != NULL; i++){
  473. len += strlen (str_array [i]);
  474. len += slen;
  475. }
  476. if (len == 0)
  477. return g_strdup ("");
  478. if (slen > 0 && len > 0)
  479. len -= slen;
  480. res = g_malloc (len + 1);
  481. r = g_stpcpy (res, str_array [0]);
  482. for (i = 1; str_array [i] != NULL; i++){
  483. if (separator != NULL)
  484. r = g_stpcpy (r, separator);
  485. r = g_stpcpy (r, str_array [i]);
  486. }
  487. return res;
  488. }
  489. gchar *
  490. g_strchug (gchar *str)
  491. {
  492. size_t len;
  493. gchar *tmp;
  494. if (str == NULL)
  495. return NULL;
  496. tmp = str;
  497. while (*tmp && isspace (*tmp)) tmp++;
  498. if (str != tmp) {
  499. len = strlen (str) - (tmp - str - 1);
  500. memmove (str, tmp, len);
  501. }
  502. return str;
  503. }
  504. gchar *
  505. g_strchomp (gchar *str)
  506. {
  507. gchar *tmp;
  508. if (str == NULL)
  509. return NULL;
  510. tmp = str + strlen (str) - 1;
  511. while (*tmp && isspace (*tmp)) tmp--;
  512. *(tmp + 1) = '\0';
  513. return str;
  514. }
  515. gint
  516. g_fprintf(FILE *file, gchar const *format, ...)
  517. {
  518. va_list args;
  519. gint ret;
  520. va_start(args, format);
  521. ret = vfprintf(file, format, args);
  522. va_end(args);
  523. return ret;
  524. }
  525. gint
  526. g_sprintf(gchar *string, gchar const *format, ...)
  527. {
  528. va_list args;
  529. gint ret;
  530. va_start(args, format);
  531. ret = vsprintf(string, format, args);
  532. va_end(args);
  533. return ret;
  534. }
  535. gint
  536. g_snprintf(gchar *string, gulong n, gchar const *format, ...)
  537. {
  538. va_list args;
  539. gint ret;
  540. va_start(args, format);
  541. ret = vsnprintf(string, n, format, args);
  542. va_end(args);
  543. return ret;
  544. }
  545. static const char hx [] = { '0', '1', '2', '3', '4', '5', '6', '7',
  546. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  547. static gboolean
  548. char_needs_encoding (char c)
  549. {
  550. if (((unsigned char)c) >= 0x80)
  551. return TRUE;
  552. if ((c >= '@' && c <= 'Z') ||
  553. (c >= 'a' && c <= 'z') ||
  554. (c >= '&' && c < 0x3b) ||
  555. (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~'))
  556. return FALSE;
  557. return TRUE;
  558. }
  559. gchar *
  560. g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **gerror)
  561. {
  562. size_t n;
  563. char *ret, *rp;
  564. const char *p;
  565. #ifdef G_OS_WIN32
  566. const char *uriPrefix = "file:///";
  567. #else
  568. const char *uriPrefix = "file://";
  569. #endif
  570. g_return_val_if_fail (filename != NULL, NULL);
  571. if (hostname != NULL)
  572. g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled");
  573. if (!g_path_is_absolute (filename)){
  574. if (gerror != NULL)
  575. *gerror = g_error_new (NULL, 2, "Not an absolute filename");
  576. return NULL;
  577. }
  578. n = strlen (uriPrefix) + 1;
  579. for (p = filename; *p; p++){
  580. #ifdef G_OS_WIN32
  581. if (*p == '\\') {
  582. n++;
  583. continue;
  584. }
  585. #endif
  586. if (char_needs_encoding (*p))
  587. n += 3;
  588. else
  589. n++;
  590. }
  591. ret = g_malloc (n);
  592. strcpy (ret, uriPrefix);
  593. for (p = filename, rp = ret + strlen (ret); *p; p++){
  594. #ifdef G_OS_WIN32
  595. if (*p == '\\') {
  596. *rp++ = '/';
  597. continue;
  598. }
  599. #endif
  600. if (char_needs_encoding (*p)){
  601. *rp++ = '%';
  602. *rp++ = hx [((unsigned char)(*p)) >> 4];
  603. *rp++ = hx [((unsigned char)(*p)) & 0xf];
  604. } else
  605. *rp++ = *p;
  606. }
  607. *rp = 0;
  608. return ret;
  609. }
  610. static int
  611. decode (char p)
  612. {
  613. if (p >= '0' && p <= '9')
  614. return p - '0';
  615. if (p >= 'A' && p <= 'F')
  616. return (p - 'A') + 10;
  617. if (p >= 'a' && p <= 'f')
  618. return (p - 'a') + 10;
  619. g_assert_not_reached ();
  620. return 0;
  621. }
  622. gchar *
  623. g_filename_from_uri (const gchar *uri, gchar **hostname, GError **gerror)
  624. {
  625. const char *p;
  626. char *r, *result;
  627. int flen = 0;
  628. g_return_val_if_fail (uri != NULL, NULL);
  629. if (hostname != NULL)
  630. g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled");
  631. if (strncmp (uri, "file:///", 8) != 0){
  632. if (gerror != NULL)
  633. *gerror = g_error_new (NULL, 2, "URI does not start with the file: scheme");
  634. return NULL;
  635. }
  636. for (p = uri + 8; *p; p++){
  637. if (*p == '%'){
  638. if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){
  639. p += 2;
  640. } else {
  641. if (gerror != NULL)
  642. *gerror = g_error_new (NULL, 2, "URI contains an invalid escape sequence");
  643. return NULL;
  644. }
  645. }
  646. flen++;
  647. }
  648. #ifndef G_OS_WIN32
  649. flen++;
  650. #endif
  651. result = g_malloc (flen + 1);
  652. result [flen] = 0;
  653. #ifndef G_OS_WIN32
  654. *result = '/';
  655. r = result + 1;
  656. #else
  657. r = result;
  658. #endif
  659. for (p = uri + 8; *p; p++){
  660. if (*p == '%'){
  661. *r++ = (char)((decode (p [1]) << 4) | decode (p [2]));
  662. p += 2;
  663. } else
  664. *r++ = *p;
  665. flen++;
  666. }
  667. return result;
  668. }
  669. void
  670. g_strdown (gchar *string)
  671. {
  672. g_return_if_fail (string != NULL);
  673. while (*string){
  674. *string = (gchar)tolower (*string);
  675. string++;
  676. }
  677. }
  678. gchar
  679. g_ascii_tolower (gchar c)
  680. {
  681. return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
  682. }
  683. void
  684. g_ascii_strdown_no_alloc (char* dst, const char* src, gsize len)
  685. {
  686. // dst can equal src. no_alloc means this function does no
  687. // allocation; caller may very well.
  688. for (gsize i = 0; i < len; ++i)
  689. dst [i] = g_ascii_tolower (src [i]);
  690. }
  691. gchar *
  692. g_ascii_strdown (const gchar *str, gssize len)
  693. {
  694. char *ret;
  695. g_return_val_if_fail (str != NULL, NULL);
  696. if (len == -1)
  697. len = strlen (str);
  698. ret = g_malloc (len + 1);
  699. g_ascii_strdown_no_alloc (ret, str, len);
  700. ret [len] = 0;
  701. return ret;
  702. }
  703. gchar
  704. g_ascii_toupper (gchar c)
  705. {
  706. return c >= 'a' && c <= 'z' ? c + ('A' - 'a') : c;
  707. }
  708. gchar *
  709. g_ascii_strup (const gchar *str, gssize len)
  710. {
  711. char *ret;
  712. int i;
  713. g_return_val_if_fail (str != NULL, NULL);
  714. if (len == -1)
  715. len = strlen (str);
  716. ret = g_malloc (len + 1);
  717. for (i = 0; i < len; i++)
  718. ret [i] = g_ascii_toupper (str [i]);
  719. ret [i] = 0;
  720. return ret;
  721. }
  722. static
  723. int
  724. g_ascii_charcmp (char c1, char c2)
  725. {
  726. // Do not subtract, to avoid overflow.
  727. // Use unsigned to mimic strcmp, and so
  728. // shorter strings compare as less.
  729. const guchar u1 = (guchar)c1;
  730. const guchar u2 = (guchar)c2;
  731. return (u1 < u2) ? -1 : (u1 > u2) ? 1 : 0;
  732. }
  733. static
  734. int
  735. g_ascii_charcasecmp (char c1, char c2)
  736. {
  737. return g_ascii_charcmp (g_ascii_tolower (c1), g_ascii_tolower (c2));
  738. }
  739. gint
  740. g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n)
  741. {
  742. // Unlike strncmp etc. this function does not stop at nul,
  743. // unless there is a mismatch.
  744. if (s1 == s2)
  745. return 0;
  746. gsize i;
  747. g_return_val_if_fail (s1 != NULL, 0);
  748. g_return_val_if_fail (s2 != NULL, 0);
  749. for (i = 0; i < n; i++) {
  750. const int j = g_ascii_charcasecmp (*s1++, *s2++);
  751. if (j)
  752. return j;
  753. }
  754. return 0;
  755. }
  756. gint
  757. g_ascii_strcasecmp (const gchar *s1, const gchar *s2)
  758. {
  759. if (s1 == s2)
  760. return 0;
  761. g_return_val_if_fail (s1 != NULL, 0);
  762. g_return_val_if_fail (s2 != NULL, 0);
  763. char c1;
  764. while ((c1 = *s1)) {
  765. ++s1;
  766. const int j = g_ascii_charcasecmp (c1, *s2++);
  767. if (j)
  768. return j;
  769. }
  770. return g_ascii_charcmp (0, *s2);
  771. }
  772. gboolean
  773. g_utf16_ascii_equal (const gunichar2 *utf16, size_t ulen, const char *ascii, size_t alen)
  774. {
  775. size_t i;
  776. if (ulen != alen)
  777. return FALSE;
  778. for (i = 0; i < ulen; ++i) {
  779. if (utf16[i] != ascii[i])
  780. return FALSE;
  781. }
  782. return TRUE;
  783. }
  784. gboolean
  785. g_utf16_asciiz_equal (const gunichar2 *utf16, const char *ascii)
  786. // z for zero means null terminated
  787. {
  788. while (1)
  789. {
  790. char a = *ascii++;
  791. gunichar2 u = *utf16++;
  792. if (a != u)
  793. return FALSE;
  794. if (a == 0)
  795. return TRUE;
  796. }
  797. }
  798. void
  799. g_strdelimit (gchar *string, gchar delimiter, gchar new_delimiter)
  800. {
  801. gchar *ptr;
  802. g_return_if_fail (string != NULL);
  803. for (ptr = string; *ptr; ptr++) {
  804. if (delimiter == *ptr)
  805. *ptr = new_delimiter;
  806. }
  807. }
  808. gsize
  809. g_strlcpy (gchar *dest, const gchar *src, gsize dest_size)
  810. {
  811. g_assert (src);
  812. g_assert (dest);
  813. #ifdef HAVE_STRLCPY
  814. return strlcpy (dest, src, dest_size);
  815. #else
  816. gchar *d;
  817. const gchar *s;
  818. gchar c;
  819. gsize len;
  820. len = dest_size;
  821. if (len == 0)
  822. return 0;
  823. s = src;
  824. d = dest;
  825. while (--len) {
  826. c = *s++;
  827. *d++ = c;
  828. if (c == '\0')
  829. return (dest_size - len - 1);
  830. }
  831. /* len is 0 i we get here */
  832. *d = '\0';
  833. /* we need to return the length of src here */
  834. while (*s++) ; /* instead of a plain strlen, we use 's' */
  835. return s - src - 1;
  836. #endif
  837. }
  838. gchar *
  839. g_stpcpy (gchar *dest, const char *src)
  840. {
  841. g_return_val_if_fail (dest != NULL, dest);
  842. g_return_val_if_fail (src != NULL, dest);
  843. #if HAVE_STPCPY
  844. return stpcpy (dest, src);
  845. #else
  846. while (*src)
  847. *dest++ = *src++;
  848. *dest = '\0';
  849. return dest;
  850. #endif
  851. }
  852. static const gchar escaped_dflt [256] = {
  853. 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
  854. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  855. 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  856. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  857. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  858. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
  859. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  860. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  861. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  862. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  863. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  864. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  865. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  866. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  867. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  868. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  869. };
  870. gchar *
  871. g_strescape (const gchar *source, const gchar *exceptions)
  872. {
  873. gchar escaped [256];
  874. const gchar *ptr;
  875. gchar c;
  876. gchar op;
  877. gchar *result;
  878. gchar *res_ptr;
  879. g_return_val_if_fail (source != NULL, NULL);
  880. memcpy (escaped, escaped_dflt, 256);
  881. if (exceptions != NULL) {
  882. for (ptr = exceptions; *ptr; ptr++)
  883. escaped [(int) *ptr] = 0;
  884. }
  885. result = g_malloc (strlen (source) * 4 + 1); /* Worst case: everything octal. */
  886. res_ptr = result;
  887. for (ptr = source; *ptr; ptr++) {
  888. c = *ptr;
  889. op = escaped [(int) c];
  890. if (op == 0) {
  891. *res_ptr++ = c;
  892. } else {
  893. *res_ptr++ = '\\';
  894. if (op != 1) {
  895. *res_ptr++ = op;
  896. } else {
  897. *res_ptr++ = '0' + ((c >> 6) & 3);
  898. *res_ptr++ = '0' + ((c >> 3) & 7);
  899. *res_ptr++ = '0' + (c & 7);
  900. }
  901. }
  902. }
  903. *res_ptr = '\0';
  904. return result;
  905. }
  906. gint
  907. g_ascii_xdigit_value (gchar c)
  908. {
  909. return ((isxdigit (c) == 0) ? -1 :
  910. ((c >= '0' && c <= '9') ? (c - '0') :
  911. ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) :
  912. (c - 'A' + 10))));
  913. }
  914. gchar *
  915. g_strnfill (gsize length, gchar fill_char)
  916. {
  917. gchar *ret = g_new (gchar, length + 1);
  918. memset (ret, fill_char, length);
  919. ret [length] = 0;
  920. return ret;
  921. }
  922. size_t
  923. g_utf16_len (const gunichar2 *a)
  924. {
  925. #ifdef G_OS_WIN32
  926. return wcslen (a);
  927. #else
  928. size_t length = 0;
  929. while (a [length])
  930. ++length;
  931. return length;
  932. #endif
  933. }
  934. gsize
  935. g_strnlen (const char* s, gsize n)
  936. {
  937. gsize i;
  938. for (i = 0; i < n && s [i]; ++i) ;
  939. return i;
  940. }
  941. // This does not link on Xbox One - no lseek or read
  942. #ifndef RUNTIME_IL2CPP
  943. /**
  944. * Loads a chunk of data from the file pointed to by the
  945. * @fd starting at the file offset @offset for @size bytes
  946. * and returns an allocated version of that string, or NULL
  947. * on error.
  948. */
  949. char *
  950. g_str_from_file_region (int fd, guint64 offset, gsize size)
  951. {
  952. char *buffer;
  953. off_t loc;
  954. int status;
  955. do {
  956. loc = lseek (fd, offset, SEEK_SET);
  957. } while (loc == -1 && errno == EINTR);
  958. if (loc == -1)
  959. return NULL;
  960. buffer = (char *)g_malloc (size + 1);
  961. if (buffer == NULL)
  962. return NULL;
  963. buffer [size] = 0;
  964. do {
  965. status = read (fd, buffer, size);
  966. } while (status == -1 && errno == EINTR);
  967. if (status == -1){
  968. g_free (buffer);
  969. return NULL;
  970. }
  971. return buffer;
  972. }
  973. #endif // !RUNTIME_IL2CPP