PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/grisbi-0.8.8/src/utils_str.c

#
C | 1070 lines | 624 code | 172 blank | 274 comment | 138 complexity | 6dc4ab82e5ea5a58b33355c2ceccd79e MD5 | raw file
Possible License(s): GPL-2.0
  1. /* ************************************************************************** */
  2. /* utils_str.c */
  3. /* */
  4. /* Copyright (C) 2000-2008 Cedric Auger (cedric@grisbi.org) */
  5. /* 2003-2008 Benjamin Drieu (bdrieu@april.org) */
  6. /* 2008-2010 Pierre Biava (grisbi@pierre.biava.name) */
  7. /* http://www.grisbi.org */
  8. /* */
  9. /* This program is free software; you can redistribute it and/or modify */
  10. /* it under the terms of the GNU General Public License as published by */
  11. /* the Free Software Foundation; either version 2 of the License, or */
  12. /* (at your option) any later version. */
  13. /* */
  14. /* This program is distributed in the hope that it will be useful, */
  15. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  16. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  17. /* GNU General Public License for more details. */
  18. /* */
  19. /* You should have received a copy of the GNU General Public License */
  20. /* along with this program; if not, write to the Free Software */
  21. /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  22. /* */
  23. /* ************************************************************************** */
  24. #ifdef HAVE_CONFIG_H
  25. #include <config.h>
  26. #endif
  27. #include "include.h"
  28. #include <stdlib.h>
  29. /*START_INCLUDE*/
  30. #include "utils_str.h"
  31. #include "gsb_data_report.h"
  32. #include "gsb_data_currency.h"
  33. /*END_INCLUDE*/
  34. /*START_STATIC*/
  35. static gchar *gsb_string_supprime_joker ( const gchar *chaine );
  36. static gchar * gsb_string_truncate_n ( gchar * string, int n, gboolean hard_trunc );
  37. /*END_STATIC*/
  38. /*START_EXTERN*/
  39. extern gsb_real error_real;
  40. /*END_EXTERN*/
  41. /**
  42. * @brief convert an integer into a gchar based string
  43. *
  44. *
  45. * @param integer integer to convert
  46. *
  47. * @return a newly allocated string
  48. *
  49. * @caveats You have to unallocate the returned string when you no more use it to save memory
  50. *
  51. * @todo: check usage of this function which a cause of memory leak
  52. *
  53. * */
  54. gchar *utils_str_itoa ( gint integer )
  55. {
  56. div_t result_div;
  57. gchar *chaine;
  58. gint i = 0;
  59. gint num;
  60. chaine = g_malloc0 ( 11*sizeof (gchar) );
  61. num = abs(integer);
  62. /* Construct the result in the reverse order from right to left, then reverse it. */
  63. do
  64. {
  65. result_div = div ( num, 10 );
  66. chaine[i] = result_div.rem + '0';
  67. i++;
  68. }
  69. while ( ( num = result_div.quot ));
  70. /* Add the sign at the end of the string just before to reverse it to avoid
  71. to have to insert it at the begin just after... */
  72. if (integer < 0)
  73. {
  74. chaine[i++] = '-';
  75. }
  76. chaine[i] = 0;
  77. g_strreverse ( chaine );
  78. return ( chaine );
  79. }
  80. /**
  81. * used for now only while loading a file before the 0.6.0 version
  82. * reduce the exponant IN THE STRING of the amount because before the 0.6.0
  83. * all the gdouble where saved with an exponent very big
  84. * ie : in the file we have "12.340000"
  85. * and that fonction return "12.34" wich will be nicely imported
  86. * with gsb_data_transaction_set_amount_from_string
  87. *
  88. * \param amount_string
  89. * \param exponent the exponent we want at the end (normally always 2, but if ever...)
  90. *
  91. * \return a newly allocated string with only 'exponent' digits after the separator (need to be freed). This function returns NULL if the amount_string parameter is NULL.
  92. * */
  93. gchar *utils_str_reduce_exponant_from_string ( const gchar *amount_string,
  94. gint exponent )
  95. {
  96. gchar *return_string;
  97. gchar *p;
  98. gchar *mon_decimal_point;
  99. gunichar decimal_point = (gunichar )-2;
  100. struct lconv *conv = localeconv ( );
  101. if ( !amount_string )
  102. return NULL;
  103. mon_decimal_point = g_locale_to_utf8 ( conv->mon_decimal_point,
  104. -1, NULL, NULL, NULL );
  105. if ( mon_decimal_point )
  106. decimal_point = g_utf8_get_char_validated ( mon_decimal_point, -1 );
  107. return_string = my_strdup ( amount_string );
  108. if ( ( p = g_utf8_strrchr ( (const gchar *) return_string, -1, '.' ) ) )
  109. {
  110. if ( g_unichar_isdefined ( decimal_point )
  111. &&
  112. g_utf8_strchr ( p, 1, decimal_point ) == NULL )
  113. {
  114. gchar **tab;
  115. tab = g_strsplit ( return_string, ".", 2 );
  116. return_string = g_strjoinv ( mon_decimal_point, tab );
  117. g_strfreev ( tab );
  118. p = g_utf8_strrchr ( (const gchar *) return_string, -1,
  119. decimal_point );
  120. }
  121. }
  122. else if ( ( p = g_utf8_strrchr ( (const gchar *) return_string, -1, ',' ) ) )
  123. {
  124. if ( g_unichar_isdefined ( decimal_point )
  125. &&
  126. g_utf8_strchr ( p, 1, decimal_point ) == NULL )
  127. {
  128. gchar **tab;
  129. tab = g_strsplit ( return_string, ",", 2 );
  130. return_string = g_strjoinv ( mon_decimal_point, tab );
  131. g_strfreev ( tab );
  132. p = g_utf8_strrchr ( (const gchar *) return_string, -1,
  133. decimal_point );
  134. }
  135. }
  136. else
  137. return NULL;
  138. p[exponent + 1] = '\0';
  139. return return_string;
  140. }
  141. /**
  142. * locates the decimal dot
  143. *
  144. *
  145. *
  146. * */
  147. gchar *utils_str_localise_decimal_point_from_string ( const gchar *string )
  148. {
  149. gchar *ptr_1, *ptr_2;
  150. gchar *new_str;
  151. gchar *mon_decimal_point;
  152. gchar *mon_separateur;
  153. gchar **tab;
  154. mon_decimal_point = gsb_real_get_decimal_point ( );
  155. mon_separateur = gsb_real_get_thousands_sep ( );
  156. if ( ( ptr_1 = g_strstr_len ( string, -1, "," ) )
  157. &&
  158. ( ptr_2 = g_strrstr ( string, "." ) ) )
  159. {
  160. if ( ( ptr_2 - string ) > ( ptr_1 - string ) )
  161. tab = g_strsplit ( string, ",", 0 );
  162. else
  163. tab = g_strsplit ( string, ".", 0 );
  164. new_str = g_strjoinv ( "", tab );
  165. g_strfreev ( tab );
  166. }
  167. else
  168. new_str = g_strdup ( string );
  169. if ( mon_decimal_point && g_strstr_len ( new_str, -1, mon_decimal_point ) == NULL )
  170. {
  171. tab = g_strsplit_set ( new_str, ".,", 0 );
  172. g_free ( new_str );
  173. new_str = g_strjoinv ( mon_decimal_point, tab );
  174. g_strfreev ( tab );
  175. }
  176. if ( mon_decimal_point )
  177. g_free ( mon_decimal_point );
  178. if ( mon_separateur && g_strstr_len ( new_str, -1, mon_separateur ) )
  179. {
  180. tab = g_strsplit ( new_str, mon_separateur, 0 );
  181. g_free ( new_str );
  182. new_str = g_strjoinv ( "", tab );
  183. g_strfreev ( tab );
  184. }
  185. if ( mon_separateur )
  186. g_free ( mon_separateur );
  187. return new_str;
  188. }
  189. /**
  190. * @brief Secured version of atoi
  191. *
  192. * Encapsulated call of atoi which may crash when it is call with a NULL pointer.
  193. *
  194. * @param chaine pointer to the buffer containing the string to convert
  195. *
  196. * @return the converted string as interger
  197. * @retval 0 when the pointer is NULL or the string empty.
  198. *
  199. * */
  200. G_MODULE_EXPORT gint utils_str_atoi ( const gchar *chaine )
  201. {
  202. if ((chaine )&&(*chaine))
  203. {
  204. return ( atoi ( chaine ));
  205. }
  206. else
  207. {
  208. return ( 0 );
  209. }
  210. }
  211. /**
  212. *
  213. *
  214. *
  215. *
  216. * */
  217. G_MODULE_EXPORT gchar * latin2utf8 ( const gchar * inchar)
  218. {
  219. return g_locale_from_utf8 ( inchar, -1, NULL, NULL, NULL );
  220. }
  221. /**
  222. * do the same as g_strdelimit but new_delimiters can containes several characters or none
  223. * ex my_strdelimit ("a-b", "-", "123") returns a123b
  224. * my_strdelimit ("a-b", "-", "") returns ab
  225. *
  226. * \param string the string we want to modify
  227. * \param delimiters the characters we need to change to new_delimiters
  228. * \param new_delimiters the replacements characters for delimiters
  229. *
  230. * \return a newly allocated string or NULL
  231. * */
  232. gchar *my_strdelimit ( const gchar *string,
  233. const gchar *delimiters,
  234. const gchar *new_delimiters )
  235. {
  236. gchar **tab_str;
  237. gchar *retour;
  238. if ( !( string
  239. &&
  240. delimiters
  241. &&
  242. new_delimiters ))
  243. return my_strdup (string);
  244. tab_str = g_strsplit_set ( string,
  245. delimiters,
  246. 0 );
  247. retour = g_strjoinv ( new_delimiters,
  248. tab_str );
  249. g_strfreev ( tab_str );
  250. return ( retour );
  251. }
  252. /**
  253. * compare 2 chaines sensitive que ce soit utf8 ou ascii
  254. *
  255. *
  256. *
  257. * */
  258. gint my_strcmp ( gchar *string_1, gchar *string_2 )
  259. {
  260. if (!string_1 && string_2)
  261. return 1;
  262. if (string_1 && !string_2)
  263. return -1;
  264. if ( g_utf8_validate ( string_1, -1, NULL )
  265. &&
  266. g_utf8_validate ( string_2, -1, NULL ))
  267. {
  268. gint retour;
  269. gchar *new_1, *new_2;
  270. new_1 = g_utf8_collate_key ( string_1, -1 );
  271. new_2 = g_utf8_collate_key ( string_2, -1 );
  272. retour = strcmp ( new_1, new_2 );
  273. g_free ( new_1 );
  274. g_free ( new_2 );
  275. return ( retour );
  276. }
  277. else
  278. return ( strcmp ( string_1, string_2 ) );
  279. return 0;
  280. }
  281. /**
  282. * compare 2 strings unsensitive
  283. * if a string is NULL, it will go after the non NULL
  284. *
  285. * \param string_1
  286. * \param string_2
  287. *
  288. * \return -1 string_1 before string_2 (or string_2 NULL) ; 0 if same or NULL everyone ; +1 if string_1 after string_2 (or string_1 NULL)
  289. * */
  290. gint my_strcasecmp ( const gchar *string_1, const gchar *string_2 )
  291. {
  292. if (!string_1 && string_2)
  293. return 1;
  294. if (string_1 && !string_2)
  295. return -1;
  296. if ( string_1 && string_2 )
  297. {
  298. if ( g_utf8_validate ( string_1, -1, NULL )
  299. &&
  300. g_utf8_validate ( string_2, -1, NULL ))
  301. {
  302. gint retour;
  303. gchar *new_1, *new_2;
  304. new_1 = g_utf8_collate_key ( g_utf8_casefold ( string_1,-1 ),
  305. -1 );
  306. new_2 = g_utf8_collate_key ( g_utf8_casefold ( string_2,-1 ),
  307. -1 );
  308. retour = strcmp ( new_1,
  309. new_2 );
  310. g_free ( new_1 );
  311. g_free ( new_2 );
  312. return ( retour );
  313. }
  314. else
  315. return ( g_ascii_strcasecmp ( string_1, string_2 ) );
  316. }
  317. return 0;
  318. }
  319. /**
  320. * compare 2 chaines case-insensitive que ce soit utf8 ou ascii
  321. *
  322. *
  323. *
  324. * */
  325. gint my_strncasecmp ( gchar *string_1,
  326. gchar *string_2,
  327. gint longueur )
  328. {
  329. if (!string_1 && string_2)
  330. return 1;
  331. if (string_1 && !string_2)
  332. return -1;
  333. if ( string_1 && string_2 )
  334. {
  335. if ( g_utf8_validate ( string_1, -1, NULL )
  336. &&
  337. g_utf8_validate ( string_2, -1, NULL ))
  338. {
  339. gint retour;
  340. gchar *new_1, *new_2;
  341. new_1 = g_utf8_casefold ( string_1,longueur );
  342. new_2 = g_utf8_casefold ( string_2,longueur );
  343. retour = g_utf8_collate ( new_1, new_2);
  344. g_free ( new_1 );
  345. g_free ( new_2 );
  346. return ( retour );
  347. }
  348. else
  349. return ( g_ascii_strncasecmp ( string_1, string_2, longueur ) );
  350. }
  351. return 0;
  352. }
  353. /**
  354. * Protect the my_strdup function if the string is NULL
  355. *
  356. * If the length of string is 0 (ie ""), return NULL. That is just
  357. * nonsense, but it has been done that way and disabling it would
  358. * certainly cause side effects. [benj]
  359. *
  360. * \param string the string to be dupped
  361. *
  362. * \return a newly allocated string (which is a copy of that string)
  363. * or NULL if the parameter is NULL or an empty string.
  364. * */
  365. G_MODULE_EXPORT gchar *my_strdup ( const gchar *string )
  366. {
  367. if ( string && strlen (string) )
  368. return g_strdup (string);
  369. else
  370. return NULL;
  371. }
  372. /**
  373. * check if the string is maximum to the length
  374. * if bigger, limit it and set ... at the end
  375. *
  376. * \param string the string to check
  377. * \param length the limit length we want
  378. *
  379. * \return a dupplicate version of the string with max length character (must to be freed)
  380. * */
  381. gchar *limit_string ( gchar *string,
  382. gint length )
  383. {
  384. gchar *string_return;
  385. gchar *tmpstr;
  386. gint i;
  387. if ( !string )
  388. return NULL;
  389. if ( g_utf8_strlen ( string, -1 ) <= length )
  390. return my_strdup (string);
  391. string_return = my_strdup ( string );
  392. tmpstr = string_return;
  393. for (i=0 ; i<(length-3) ; i++)
  394. tmpstr = g_utf8_next_char (tmpstr);
  395. tmpstr[0] = '.';
  396. tmpstr = g_utf8_next_char (tmpstr);
  397. tmpstr[0] = '.';
  398. tmpstr = g_utf8_next_char (tmpstr);
  399. tmpstr[0] = '.';
  400. tmpstr = g_utf8_next_char (tmpstr);
  401. tmpstr[0] = 0;
  402. return string_return;
  403. }
  404. /**
  405. * return a gslist of integer from a string which the elements are separated
  406. * by the separator
  407. *
  408. * \param string the string we want to change to a list
  409. * \param delimiter the string which is the separator in the list
  410. *
  411. * \return a g_slist or NULL
  412. * */
  413. GSList *gsb_string_get_int_list_from_string ( const gchar *string,
  414. gchar *delimiter )
  415. {
  416. GSList *list_tmp;
  417. gchar **tab;
  418. gint i=0;
  419. if ( !string
  420. ||
  421. !delimiter
  422. ||
  423. !strlen (string)
  424. ||
  425. !strlen (delimiter))
  426. return NULL;
  427. tab = g_strsplit ( string,
  428. delimiter,
  429. 0 );
  430. list_tmp = NULL;
  431. while ( tab[i] )
  432. {
  433. list_tmp = g_slist_append ( list_tmp,
  434. GINT_TO_POINTER ( atoi (tab[i])));
  435. i++;
  436. }
  437. g_strfreev ( tab );
  438. return list_tmp;
  439. }
  440. /**
  441. * return a gslist of strings from a string which the elements are separated
  442. * by the separator
  443. * (same as gsb_string_get_int_list_from_string but with strings)
  444. *
  445. * \param string the string we want to change to a list
  446. * \param delimiter the string which is the separator in the list
  447. *
  448. * \return a g_slist or NULL
  449. * */
  450. GSList *gsb_string_get_string_list_from_string ( const gchar *string,
  451. gchar *delimiter )
  452. {
  453. GSList *list_tmp;
  454. gchar **tab;
  455. gint i=0;
  456. if ( !string
  457. ||
  458. !delimiter
  459. ||
  460. !strlen (string)
  461. ||
  462. !strlen (delimiter))
  463. return NULL;
  464. tab = g_strsplit ( string,
  465. delimiter,
  466. 0 );
  467. list_tmp = NULL;
  468. while ( tab[i] )
  469. {
  470. list_tmp = g_slist_append ( list_tmp,
  471. my_strdup (tab[i]));
  472. i++;
  473. }
  474. g_strfreev ( tab );
  475. return list_tmp;
  476. }
  477. /**
  478. * return a gslist of struct_categ_budget_sel
  479. * from a string as no_categ/no_sub_categ/no_sub_categ/no_sub_categ-no_categ/no_sub_categ...
  480. * (or idem with budget)
  481. *
  482. * \param string the string we want to change to a list
  483. *
  484. * \return a g_slist or NULL
  485. * */
  486. GSList *gsb_string_get_categ_budget_struct_list_from_string ( const gchar *string )
  487. {
  488. GSList *list_tmp = NULL;
  489. gchar **tab;
  490. gint i=0;
  491. if ( !string
  492. ||
  493. !strlen (string))
  494. return NULL;
  495. tab = g_strsplit ( string,
  496. "-",
  497. 0 );
  498. while ( tab[i] )
  499. {
  500. struct_categ_budget_sel *categ_budget_struct = NULL;
  501. gchar **sub_tab;
  502. gint j=0;
  503. sub_tab = g_strsplit (tab[i], "/", 0);
  504. while (sub_tab[j])
  505. {
  506. if (!categ_budget_struct)
  507. {
  508. /* no categ_budget_struct created, so we are on the category */
  509. categ_budget_struct = g_malloc0 (sizeof (struct_categ_budget_sel));
  510. categ_budget_struct -> div_number = utils_str_atoi(sub_tab[j]);
  511. }
  512. else
  513. {
  514. /* categ_budget_struct is created, so we are on sub-category */
  515. categ_budget_struct -> sub_div_numbers = g_slist_append (categ_budget_struct -> sub_div_numbers,
  516. GINT_TO_POINTER (utils_str_atoi (sub_tab[j])));
  517. }
  518. j++;
  519. }
  520. g_strfreev (sub_tab);
  521. list_tmp = g_slist_append (list_tmp, categ_budget_struct);
  522. i++;
  523. }
  524. g_strfreev ( tab );
  525. return list_tmp;
  526. }
  527. /**
  528. * Return a newly created strings, truncating original. It should be
  529. * truncated at the end of the word containing the 20th letter.
  530. *
  531. * \param string String to truncate.
  532. *
  533. * \return A newly-created string.
  534. */
  535. gchar * gsb_string_truncate ( gchar * string )
  536. {
  537. return gsb_string_truncate_n ( string, 20, FALSE );
  538. }
  539. /**
  540. * Return a newly created strings, truncating original. It should be
  541. * truncated at the end of the word containing the nth letter.
  542. *
  543. * \param string String to truncate
  544. * \param n Max lenght to truncate at.
  545. * \param hard_trunc Cut in the middle of a word if needed.
  546. *
  547. * \return A newly-created string.
  548. */
  549. gchar * gsb_string_truncate_n ( gchar * string, int n, gboolean hard_trunc )
  550. {
  551. gchar* result;
  552. gchar * tmp = string, * trunc;
  553. if ( ! string )
  554. return NULL;
  555. if ( strlen(string) < n )
  556. return my_strdup ( string );
  557. tmp = string + n;
  558. if ( ! hard_trunc && ! ( tmp = strchr ( tmp, ' ' ) ) )
  559. {
  560. /* We do not risk splitting the string in the middle of a
  561. UTF-8 accent ... the end is probably near btw. */
  562. return my_strdup ( string );
  563. }
  564. else
  565. {
  566. while ( ! isascii(*tmp) && *tmp )
  567. tmp++;
  568. trunc = g_strndup ( string, ( tmp - string ) );
  569. result = g_strconcat ( trunc, "...", NULL );
  570. g_free(trunc);
  571. return result;
  572. }
  573. }
  574. /**
  575. * remplace la chaine old_str par new_str dans str
  576. *
  577. */
  578. gchar * gsb_string_remplace_string ( gchar *str, gchar *old_str, gchar *new_str )
  579. {
  580. gchar *ptr_debut;
  581. gint long_old, str_len;
  582. gchar *chaine, *ret, *tail;
  583. ptr_debut = g_strstr_len ( str, -1, old_str);
  584. if ( ptr_debut == NULL )
  585. return g_strdup ( str );
  586. str_len = strlen ( str );
  587. long_old = strlen ( old_str );
  588. chaine = g_strndup ( str, (ptr_debut - str) );
  589. tail = ptr_debut + long_old;
  590. if ( tail >= str + str_len )
  591. ret = g_strconcat ( chaine, new_str, NULL );
  592. else
  593. ret = g_strconcat ( chaine, new_str, tail, NULL );
  594. g_free ( chaine );
  595. return ret;
  596. }
  597. /**
  598. * recherche des mots séparés par des jokers "%*" dans une chaine
  599. *
  600. * \param haystack
  601. * \param needle
  602. *
  603. * \return TRUE si trouvé FALSE autrement
  604. */
  605. gboolean gsb_string_is_trouve ( const gchar *payee_name, const gchar *needle )
  606. {
  607. gchar **tab_str;
  608. gchar *tmpstr;
  609. gint i;
  610. gboolean is_prefix = FALSE, is_suffix = FALSE;
  611. if ( g_strstr_len ( needle, -1, "%" ) == NULL &&
  612. g_strstr_len ( needle, -1, "*" ) == NULL )
  613. {
  614. if ( my_strcasecmp ( payee_name, needle ) == 0 )
  615. return TRUE;
  616. else
  617. return FALSE;
  618. }
  619. if ( g_str_has_prefix ( needle, "%" ) == FALSE &&
  620. g_str_has_prefix ( needle, "*" ) == FALSE )
  621. is_prefix = TRUE;
  622. if ( g_str_has_suffix ( needle, "%" ) == FALSE &&
  623. g_str_has_suffix ( needle, "*" ) == FALSE )
  624. is_suffix = TRUE;
  625. if ( is_prefix && is_suffix )
  626. {
  627. tab_str = g_strsplit_set ( needle, "%*", 0 );
  628. is_prefix = g_str_has_prefix ( payee_name, tab_str[0] );
  629. is_suffix = g_str_has_suffix ( payee_name, tab_str[1] );
  630. if ( is_prefix && is_suffix )
  631. return TRUE;
  632. else
  633. return FALSE;
  634. }
  635. else if ( is_prefix && ! is_suffix )
  636. {
  637. tmpstr = gsb_string_supprime_joker ( needle );
  638. is_prefix = g_str_has_prefix (payee_name, tmpstr);
  639. g_free (tmpstr);
  640. return is_prefix;
  641. }
  642. else if ( is_suffix && ! is_prefix )
  643. {
  644. tmpstr = gsb_string_supprime_joker ( needle );
  645. is_suffix = g_str_has_suffix (payee_name, tmpstr);
  646. g_free (tmpstr);
  647. return is_suffix;
  648. }
  649. tab_str = g_strsplit_set ( needle, "%*", 0 );
  650. for (i = 0; tab_str[i] != NULL; i++)
  651. {
  652. if ( tab_str[i] && strlen (tab_str[i]) > 0)
  653. {
  654. if ( g_strstr_len (payee_name, -1, tab_str[i]))
  655. {
  656. g_strfreev ( tab_str );
  657. return TRUE;
  658. }
  659. }
  660. }
  661. g_strfreev ( tab_str );
  662. return FALSE;
  663. }
  664. /**
  665. * remplace les jokers "%*" par une chaine
  666. *
  667. * \param str
  668. * \param new_str
  669. *
  670. * \return chaine avec chaine de remplacement
  671. */
  672. gchar * gsb_string_remplace_joker ( const gchar *chaine, gchar *new_str )
  673. {
  674. gchar **tab_str;
  675. tab_str = g_strsplit_set ( chaine, "%*", 0 );
  676. return g_strjoinv ( new_str, tab_str );
  677. }
  678. /**
  679. *supprime les jokers "%*" dans une chaine
  680. *
  681. * \param chaine
  682. *
  683. * \return chaine sans joker
  684. */
  685. gchar *gsb_string_supprime_joker ( const gchar *chaine )
  686. {
  687. gchar **tab_str;
  688. tab_str = g_strsplit_set ( chaine, "%*", 0 );
  689. return g_strjoinv ( "", tab_str );
  690. }
  691. /*
  692. * extrait un nombre d'une chaine
  693. *
  694. * \param chaine
  695. *
  696. * \return guint
  697. */
  698. gchar *gsb_string_extract_int ( const gchar *chaine )
  699. {
  700. gchar *ptr;
  701. gchar *tmpstr;
  702. gunichar ch;
  703. gint i = 0;
  704. gint long_nbre = 64;
  705. tmpstr = g_malloc0 ( long_nbre * sizeof (gchar) );
  706. ptr = g_strdup ( chaine );
  707. while ( g_utf8_strlen (ptr, -1) > 0 )
  708. {
  709. ch = g_utf8_get_char_validated (ptr, -1);
  710. if ( g_unichar_isdefined ( ch ) && g_ascii_isdigit ( ch ) )
  711. {
  712. if ( i == long_nbre )
  713. break;
  714. tmpstr[i] = ptr[0];
  715. i++;
  716. }
  717. ptr = g_utf8_next_char (ptr);
  718. }
  719. return tmpstr;
  720. }
  721. /**
  722. * uniformisation des CR+LF dans les fichiers importés
  723. *
  724. * \param chaine
  725. *
  726. * \return chaine au format unix
  727. */
  728. gchar *gsb_string_uniform_new_line ( const gchar *chaine, gint nbre_char )
  729. {
  730. gchar **tab_str;
  731. if ( chaine == NULL )
  732. return NULL;
  733. if ( g_strstr_len ( chaine, nbre_char, "\r\n" ) )
  734. {
  735. tab_str = g_strsplit_set ( chaine, "\r", 0 );
  736. return g_strjoinv ( "", tab_str );
  737. }
  738. else if ( g_strstr_len ( chaine, nbre_char, "\r" )
  739. &&
  740. !g_strstr_len ( chaine, nbre_char, "\n" ) )
  741. {
  742. tab_str = g_strsplit_set ( chaine, "\r", 0 );
  743. return g_strjoinv ( "\n", tab_str );
  744. }
  745. else if ( g_strstr_len ( chaine, nbre_char, "\n" ) )
  746. return g_strdup ( chaine );
  747. else
  748. return NULL;
  749. }
  750. /**
  751. *
  752. *
  753. *
  754. *
  755. * */
  756. gchar *utils_str_dtostr ( gdouble number, gint nbre_decimal, gboolean canonical )
  757. {
  758. gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
  759. gchar *str_number;
  760. gchar *decimal;
  761. gchar *format;
  762. gint nbre_char;
  763. decimal = utils_str_itoa ( nbre_decimal );
  764. format = g_strconcat ( "%.", decimal, "f", NULL );
  765. nbre_char = g_sprintf ( buffer, format, number );
  766. g_free ( decimal );
  767. g_free ( format );
  768. if ( nbre_char > G_ASCII_DTOSTR_BUF_SIZE )
  769. return NULL;
  770. str_number = g_strndup ( buffer, nbre_char );
  771. if ( canonical && g_strrstr ( str_number, "," ) )
  772. str_number = my_strdelimit ( str_number, ",", "." );
  773. return str_number;
  774. }
  775. /**
  776. * fonction de conversion de char ŕ double pour chaine avec un . comme séparateur décimal
  777. * et pas de séparateur de milliers
  778. *
  779. *
  780. * */
  781. gdouble utils_str_safe_strtod ( const gchar *str_number, gchar **endptr )
  782. {
  783. gdouble number;
  784. if ( str_number == NULL )
  785. return 0.0;
  786. number = g_ascii_strtod ( str_number, endptr);
  787. return number;
  788. }
  789. /**
  790. * fonction de conversion de char ŕ double pour chaine en tenant compte du séparateur décimal
  791. * et du séparateur de milliers configurés dans les préférences.
  792. *
  793. *
  794. *
  795. * */
  796. gdouble utils_str_strtod ( const gchar *str_number, gchar **endptr )
  797. {
  798. gdouble number;
  799. gsb_real real;
  800. if ( str_number == NULL )
  801. return 0.0;
  802. real = gsb_real_get_from_string ( str_number );
  803. number = gsb_real_real_to_double ( real );
  804. return number;
  805. }
  806. /**
  807. *
  808. *
  809. *
  810. *
  811. * */
  812. gint utils_str_get_nbre_motifs ( const gchar *chaine, const gchar *motif )
  813. {
  814. gchar **tab_str;
  815. gint nbre_motifs = 0;
  816. if ( chaine == NULL || motif == NULL )
  817. return -1;
  818. tab_str = g_strsplit ( chaine, motif, 0 );
  819. nbre_motifs = g_strv_length ( tab_str ) -1;
  820. g_strfreev ( tab_str );
  821. return nbre_motifs;
  822. }
  823. /**
  824. * adapte l'utilisation de : en fonction de la langue de l'utilisateur
  825. *
  826. *
  827. *
  828. * */
  829. gchar *utils_str_incremente_number_from_str ( const gchar *str_number, gint increment )
  830. {
  831. gchar *new_str_number;
  832. gchar *prefix = NULL;
  833. gint number = 0;
  834. gint i = 0;
  835. if ( str_number && strlen ( str_number ) > 0 )
  836. {
  837. while ( str_number[i] == '0' )
  838. {
  839. i++;
  840. }
  841. if ( i > 0 )
  842. prefix = g_strndup ( str_number, i );
  843. number = utils_str_atoi ( str_number );
  844. }
  845. number += increment;
  846. new_str_number = utils_str_itoa ( number );
  847. if ( prefix && strlen ( prefix ) > 0 )
  848. {
  849. new_str_number = g_strconcat ( prefix, new_str_number, NULL );
  850. g_free ( prefix );
  851. }
  852. return new_str_number;
  853. }
  854. /**
  855. * Return the real in a formatted string with an optional currency
  856. * symbol, according to the locale regarding decimal separator,
  857. * thousands separator and positive or negative sign.
  858. *
  859. * \param number Number to format.
  860. * \param currency_number the currency we want to adapt the number, 0 for no adaptation
  861. * \param show_symbol TRUE to add the currency symbol in the string
  862. *
  863. * \return A newly allocated string of the number (this
  864. * function will never return NULL)
  865. */
  866. gchar *gsb_real_get_string_with_currency ( gsb_real number,
  867. gint currency_number,
  868. gboolean show_symbol )
  869. {
  870. struct lconv *conv = localeconv ();
  871. gint floating_point;
  872. const gchar *currency_symbol = (currency_number && show_symbol)
  873. ? gsb_data_currency_get_code_or_isocode (currency_number)
  874. : NULL;
  875. /* First of all if number = 0 I return 0 with the symbol of the currency if necessary */
  876. if (number.mantissa == 0)
  877. {
  878. if (currency_symbol && conv -> p_cs_precedes)
  879. return g_strdup_printf ( "%s %s", currency_symbol, "0" );
  880. else if (currency_symbol && ! conv -> p_cs_precedes)
  881. return g_strdup_printf ( "%s %s", "0", currency_symbol );
  882. else
  883. return g_strdup ("0");
  884. }
  885. else if ( (number.exponent < 0)
  886. || (number.exponent > EXPONENT_MAX )
  887. || (number.mantissa == error_real.mantissa) )
  888. return g_strdup ( ERROR_REAL_STRING );
  889. /* first we need to adapt the exponent to the currency */
  890. /* if the exponent of the real is not the same of the currency, need to adapt it */
  891. floating_point = gsb_data_currency_get_floating_point ( currency_number );
  892. if ( currency_number && number.exponent != floating_point )
  893. number = gsb_real_adjust_exponent ( number, floating_point );
  894. return gsb_real_raw_format_string ( number, conv, currency_symbol );
  895. }
  896. /* Local Variables: */
  897. /* c-basic-offset: 4 */
  898. /* End: */