~ubuntu-branches/ubuntu/trusty/jargoninformatique/trusty

« back to all changes in this revision

Viewing changes to src/save/gstr.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2006-07-06 08:30:02 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060706083002-3cxjutduamkxrrmz
Tags: 1.3.6-0ubuntu1
* New upstream release
* Remove 01_Makefile.dpatch, fixed upstream
* Bump standards version to 3.7.2
* Set debhelper version to >= 5.0.0
* Build-Deps: add libxpm-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/************************************************************
2
 
 * Librairie pour la gestion de chaine de caractères
3
 
 * en C.
4
 
 *
5
 
 * Auteur: Achraf cherti
6
 
 * Email:  achrafcherti@gmail.com
7
 
 ************************************************************
8
 
 * NOTE: les commentaires de ce code source sont
9
 
 *       écrit au format utf8.
10
 
 ************************************************************
11
 
 *==================
12
 
 * Licence:
13
 
 *==================
14
 
 * Cette source est distribuée sous licence
15
 
 * GNU General Public Licence version 2.
16
 
 *
17
 
 * Elle n'est distribuée sans aucune garantie.
18
 
 * Vous avez le droit de la distribuer, 
19
 
 * l'étudier ou l'améliorer tant que le 
20
 
 * code source reste libre et conforme à
21
 
 * la licence GPL.
22
 
 ************************************************************
23
 
 *==================
24
 
 * Historique:
25
 
 *==================
26
 
 * 0.1 (Août 2004):
27
 
 *     * Création de toutes les fonctions de base 
28
 
 *     * Version pas complètement testée
29
 
 * 0.2 (Juillet 2005):
30
 
 *     * Elimination de tous les warning critiques
31
 
 *     * Correction de quelque bugs trouvés grâce à
32
 
 *       certaines programmes qui utilisent gstr.c
33
 
 *       (comme Jargon Informatique)
34
 
 * 0.3 (Août 2005)
35
 
 *     * Relecture de toutes les fonctions une à une
36
 
 *       et réécriture de certaines (pour optimisation)
37
 
 *     * Réécriture de presque tous les commentaires
38
 
 *       incorrectement écrits pour avoir mieux de
39
 
 *       détails sur l'utilisation des fonctions.
40
 
 *     * Changement du nom gs_joker() par gs_wildcard()
41
 
 *     * Correction de certains bugs dans gs_wildcard
42
 
 *     * Réécriture de gs_is_affix() et gs_is_caseaffix()
43
 
 *       gs_indexof() gs_last_indexof().
44
 
 *     * Remplacement dans gs_sdel() strcpy() par
45
 
 *       memmove() plus adaptée à cela et valgrind
46
 
 *       provoque quelques erreurs.
47
 
 *     * Changement de gs_join() pour qu'il alloque
48
 
 *       le tout d'un coup au lieu de faire des realloc
49
 
 *       à chaque fois...
50
 
 *     * Elimination de l'allocation mémoire dans
51
 
 *       gs_split_ex()
52
 
 *     * Correction de tous les malloc/realloc/free
53
 
 *       par des MALLOC/REALLOC/FREE (les defines
54
 
 *       pour faciliter l'intégration avec un
55
 
 *       autre type d'allocations)
56
 
 *     * correction de gs_strcat_r ou dest n'était
57
 
 *       pas désalloqué quand il n'y avait pas assez
58
 
 *       de mémoire.
59
 
 *     * Correction d'un bug dans gs_replace_m() et 
60
 
 *       gs_replace_r() qui n'alloque pas la bonne
61
 
 *       taille.
62
 
 *     * Correction d'un bug dans gs_replace_m()
63
 
 *       qui ne teste pas le NULL dans la bonne
64
 
 *       variable.
65
 
 *     * Petite optimisation dans gs_nstr() au lieu
66
 
 *       de recalculer strlen rech, il la stocke dans
67
 
 *       une variable au début.
68
 
 *     * Optimisation de gs_replace() pour qu'il 
69
 
 *       test le type de remplacement au début...
70
 
 *     * gs_*case, remplacement do{}while par while{}
71
 
 *       car plus adaptée.
72
 
 *     * Correction d'un petit bug dans _gs_substr()
73
 
 *       qui ne retournait pas str + pas de memmove
74
 
 *     * Création de fonction gs_change pour être le
75
 
 *       pilier de gs_change_m et gs_change_r
76
 
 *     * Correction d'un bug dans gs_r_accept() qui 
77
 
 *       ignore le premier caractère lors de la recherche.
78
 
 *     * Correction de gs_r_reject() - même bug de 
79
 
 *       gs_r_accept()
80
 
 *
81
 
 ************************************************************/
82
 
 
83
 
#include <stdlib.h>
84
 
#include <stdio.h>
85
 
#include <string.h>
86
 
 
87
 
#include <ctype.h> // toupper/tolower
88
 
 
89
 
#include "gstr.h"
90
 
 
91
 
/*********************************************
92
 
 * Compare 'str' avec 'joker'.
93
 
 * Permet de mettre un wilcard dans la
94
 
 * chaine joker.
95
 
 * Comme par exemple: *.exe
96
 
 *********************************************/
97
 
//OK
98
 
 
99
 
int gs_wildcard(const char *p, const char *joker)
100
 
{
101
 
        while(*p && *joker) {
102
 
                //test joker *
103
 
                if(*joker=='*') {
104
 
                        //chercher prochain caractère
105
 
                        //dans joker qui est diff '?' et '*'
106
 
                        joker++;
107
 
                        while(*joker=='*' || *joker=='?') joker++;
108
 
 
109
 
                        //cherche le caractère qui égale
110
 
                        //celui demandé par le joker.
111
 
                        while(*p && *p!=*joker) p++;
112
 
 
113
 
                        //pas trouvé?? alors erreur...
114
 
                        //comme par exemple acha = ach*raf
115
 
                        if(*p!=*joker) return 0; 
116
 
 
117
 
                        //si fin mais égalité
118
 
                        if(!*p && !*joker) return -1;
119
 
                }
120
 
 
121
 
                // S'il n'y a pas d'étoile... Il va soit
122
 
                // tester avec un joker '?' soit faire un
123
 
                // vrai test pour voir si le *joker actuel
124
 
                // correspond à *p
125
 
                else if(*joker!='?' && *joker!=*p) return 0;
126
 
 
127
 
                //incrémente les deux... Comme toujours...
128
 
                joker++; p++;
129
 
        }
130
 
 
131
 
        //si l'on finit avant l'autre...
132
 
        if(*p!=*joker) {
133
 
                //si le joker a déjà fini... donc c pas bon.
134
 
                if(!*joker) return 0;
135
 
                //cherche s'il n'y a que des wildcard
136
 
                //à la fin de joker car si c'est le cas
137
 
                //ça veut dire que c'est parfait.
138
 
                //par exemple: gs_wildcard("achra","achra*")
139
 
                //p va finir avant le dernier 'a' de achra
140
 
                //et puis  la fonction va croire que c faux.
141
 
                //mais maintenant après cette boucle il saura
142
 
                //qu'il n'y a "que" des wildcard
143
 
                while(*joker && (*joker=='*' || *joker=='?')) joker++;
144
 
                //si joker est arrivé à la fin!! ça veut dire que c ok
145
 
                if(!*joker) return -1;
146
 
                return 0;
147
 
        }
148
 
        
149
 
        //et sinon... cela veut dire que c'est pas bon :-)
150
 
        return -1;
151
 
}
152
 
 
153
 
/************************************************************
154
 
 * Teste si 'affix' est l'affixe de 'string'.
155
 
 * Si c'est oui, il retourne une valeur différente
156
 
 * de zéro.
157
 
 * 
158
 
 * Attention:
159
 
 * ----------
160
 
 *  string et affix doivent être de vrai pointeurs non NULL.
161
 
 ************************************************************/
162
 
//OK
163
 
int gs_is_affix(const char *string, const char *affix)
164
 
{
165
 
        while(*affix) {
166
 
                if(*string!=*affix) return 0;
167
 
                string++; affix++;
168
 
        }
169
 
        return 1;
170
 
}
171
 
 
172
 
/************************************************************
173
 
 * Teste si 'affix' est l'affixe de 'string'.
174
 
 * Si c'est oui, il retourne une valeur différente
175
 
 * de zéro.
176
 
 *
177
 
 * Ce test est différent de gs_is_affix car il ignore
178
 
 * les majuscules ou minuscules.
179
 
 * 
180
 
 * Attention:
181
 
 * ----------
182
 
 * string et affix doivent être de vrai pointeurs non NULL.
183
 
 ************************************************************/
184
 
//OK
185
 
int gs_is_caseaffix(const char *string, const char *affix)
186
 
{
187
 
        while(*affix) {
188
 
                if(tolower(*string)!=tolower(*affix)) return 0;
189
 
                string++; affix++;
190
 
        }
191
 
        return 1;
192
 
}
193
 
 
194
 
/************************************************************
195
 
 * Recheche dans 'string' si 'rech' existe.
196
 
 * Il retourne l'index de ce qui concorde à 'rech'
197
 
 * dans 'string'.
198
 
 *
199
 
 * isaffix: marche de la même façon que gs_is_affix()
200
 
 ************************************************************/
201
 
//OK
202
 
char *gs_indexof(const char *string, const char *rech, int (*isaffix)(const char *, const char *))
203
 
{
204
 
        if(!isaffix) isaffix=gs_is_affix;
205
 
        while(*string) {
206
 
                if((*isaffix)(string,rech)) return (char *)string;
207
 
                string++;
208
 
        }
209
 
        return NULL; //pas trouvé!
210
 
}
211
 
 
212
 
//OK
213
 
char *gs_last_indexof(const char *string, const char *rech, int (*isaffix)(const char *, const char *))
214
 
{
215
 
        const char *s = string+strlen(string)-strlen(rech);
216
 
        if(!isaffix) isaffix=gs_is_affix;
217
 
 
218
 
        while(s>=string) {
219
 
                if((*isaffix)(s,rech)) return (char *)s;
220
 
                s--;
221
 
        }
222
 
        return NULL;
223
 
}
224
 
 
225
 
/************************************************************
226
 
 * Supprime 'len' caractères depuis la position 'pos'
227
 
 * dans la chaine 'string'.
228
 
 ************************************************************/
229
 
//OK
230
 
char *gs_sdel(char *string, size_t pos, size_t len)
231
 
{
232
 
        size_t slen;
233
 
 
234
 
        //fix les dépassements
235
 
        slen=strlen(string);
236
 
        if(pos>=slen) return string;
237
 
        if(pos+len>=slen) len=slen-pos;
238
 
 
239
 
        //delete...
240
 
        memmove(string+pos,string+pos+len, slen-pos-len+1);
241
 
 
242
 
        return string;
243
 
}
244
 
 
245
 
// Même chose que gs_sdel mais pour un seul caractère
246
 
//OK
247
 
char *gs_cdel(char *string, size_t pos)
248
 
{
249
 
        return gs_sdel(string,pos,1);
250
 
}
251
 
 
252
 
/************************************************************
253
 
 * Cette fonction prend toutes les chaines qui sont
254
 
 * dans 'list' pour les joindre en utilisant 'separator'.
255
 
 *
256
 
 * Par exemple la liste contient:
257
 
 *    * bonjour
258
 
 *    * le
259
 
 *    * monde
260
 
 *
261
 
 * Si on utilise cette fonction avec separator=":"
262
 
 * Alors le résultat (alloqué) sera:
263
 
 *
264
 
 *  "bonjour:le:monde"
265
 
 ************************************************************/
266
 
//OK
267
 
char *gs_join(GS_LIST *list, const char *separator)
268
 
{
269
 
        static size_t i;
270
 
        static char *s;
271
 
        static size_t len_general;
272
 
 
273
 
        //teste si list est vide. très important
274
 
        //pour ce qui est en bas...
275
 
        if(!list->size) return strdup("");
276
 
 
277
 
        //calcul du len général (toutes les chaines de 'list' + separateurs)
278
 
        len_general=strlen(separator)*(list->size-1); //y a toujours un séparateur en moins
279
 
        i=0; 
280
 
        while(i<list->size) { len_general+=strlen(list->ptr[i]); i++; }
281
 
 
282
 
        //allocation du tout...
283
 
        s = (char *)MALLOC(len_general+1);
284
 
        if(!s) return s;
285
 
        *s=0; //vide la chaine
286
 
        
287
 
        //maintenant il va copier le contenu de toutes
288
 
        //les chaines de 'list' + separateur dans s
289
 
        i=1;
290
 
        strcpy(s,list->ptr[0]);
291
 
        while(i<list->size) { strcat(s,separator); strcat(s,list->ptr[i]); i++; }
292
 
        
293
 
        return s;
294
 
        //----
295
 
 
296
 
        //ancienne façon:
297
 
        //j'ai préféré la remplacer pour éviter
298
 
        //la réallcation à chaque fois...
299
 
#if 0
300
 
        for(i=0;i<list->size;i++) {
301
 
                if(i!=0) s=gs_strcat_r(s,separator);
302
 
                s=gs_strcat_r(s,list->ptr[i]);
303
 
                if(!s) return s;
304
 
        }
305
 
#endif
306
 
        return s;
307
 
}
308
 
 
309
 
/************************************************************
310
 
 * Cette fonction découpe 'string' en morceaux en 
311
 
 * utilisant le délimiteur 'delim'
312
 
 *
313
 
 * _strstr(chaine,delim)
314
 
 * =====================
315
 
 * La fonction _strstr() se charge de trouver
316
 
 * 'delim' dans 'chaine'
317
 
 ************************************************************/
318
 
//OK
319
 
GS_LIST *gs_split_ex(const char *string, const char *delim, char *(*_strstr)(const char *,const char *), size_t delim_len)
320
 
{
321
 
        static const char *suivant, *precedent, *cp /*const p*/;
322
 
        char *p;
323
 
        static size_t len;
324
 
 
325
 
        //Création d'une liste
326
 
        GS_LIST *list = gs_list_new();
327
 
        if(!list) return list;
328
 
 
329
 
        //opération de split
330
 
        precedent=string;
331
 
        while((suivant=(*_strstr)(precedent,delim))) {
332
 
                //calcule le len de 'precedent' à 'len'
333
 
                cp=precedent; len=0;
334
 
                while(cp<suivant) { len++; cp++; }
335
 
 
336
 
                //allocation d'une nouvelle chaine
337
 
                p = (char *)MALLOC(len+1); //le 1 du zero
338
 
                if(!p) {
339
 
                        gs_list_free(&list);
340
 
                        return NULL;
341
 
                }
342
 
                strncpy(p,precedent,len);
343
 
                p[len]=0; //le zero de la fin...
344
 
 
345
 
                //ajoute...
346
 
                if(!gs_list_push(list,p)) {
347
 
                        gs_list_free(&list);
348
 
                        return NULL;
349
 
                }
350
 
 
351
 
                precedent=suivant+delim_len;
352
 
        }
353
 
 
354
 
        //si oui alors on l'ajoute!
355
 
        p=strdup(precedent);
356
 
        if(!gs_list_push(list,p)) {
357
 
                gs_list_free(&list);
358
 
                return NULL;
359
 
        }
360
 
 
361
 
        //et enfin, il retourne le résultat!
362
 
        return list;
363
 
}
364
 
 
365
 
GS_LIST *gs_split(const char *string, const char *delim)
366
 
{
367
 
        return gs_split_ex(string,delim,strstr,strlen(delim));
368
 
}
369
 
 
370
 
GS_LIST *gs_csplit(const char *string, const char *delim)
371
 
{
372
 
        return gs_split_ex(string,delim,strpbrk,1);
373
 
}
374
 
 
375
 
/************************************************************
376
 
 * Création d'une nouvelle liste GS_LIST.
377
 
 *
378
 
 * Cette alloque le contenu, mais aussi la variable GS_LIST
379
 
 * (qui est d'ailleurs retournée).
380
 
 *
381
 
 * NOTE:
382
 
 * -----
383
 
 * La liste 'list->ptr' est une char**, elle est compatible
384
 
 * avec les chaines qui finissent avec un zero.
385
 
 * C'est pour cette raison qu'un zero est toujours ajouté
386
 
 * à la fin...
387
 
 ************************************************************/
388
 
//OK
389
 
GS_LIST *gs_list_new()
390
 
{
391
 
        //création d'une liste vide
392
 
        GS_LIST *list = (GS_LIST *)MALLOC(sizeof(GS_LIST));
393
 
        memset(list,0,sizeof(GS_LIST));
394
 
 
395
 
        // créer un élément contenant zero
396
 
        list->ptr=(char **)MALLOC(sizeof(char *));
397
 
        if(!list->ptr) { FREE(list); return NULL; }
398
 
        list->ptr[0]=NULL;
399
 
 
400
 
        //retourne le résultat
401
 
        return list;
402
 
}
403
 
 
404
 
/************************************************************
405
 
 * Ajoute un élément dans la liste 'list'.
406
 
 * 
407
 
 * NOTE: str doit être un pointeur malloc! car gs_list_push
408
 
 *       n'ajoute que le pointeur 'str'
409
 
 *       Utilisez gs_list_push_m() pour avoir une fonction
410
 
 *       qui copie str avec strdup() 
411
 
 *
412
 
 * NOTE: 'list' doit être alloquée avec gs_list_new()
413
 
 *
414
 
 * Retour:
415
 
 * -------
416
 
 * S'il n'y a pas assez de mémoire pour ajouter un
417
 
 * élément dans 'list', cette fonction retourne NULL.
418
 
 * Sinon, elle retourne str.
419
 
 ************************************************************/
420
 
//OK
421
 
char *gs_list_push(GS_LIST *list, char *str)
422
 
{
423
 
        static char **save;
424
 
        if(!str) return str;
425
 
 
426
 
        list->ptr = (char **)REALLOC(save=list->ptr, (sizeof(GS_LIST)*(list->size+1))+1);
427
 
        if(!list->ptr) {
428
 
                list->ptr=save;
429
 
                return NULL;
430
 
        }
431
 
 
432
 
        //mets les valeurs
433
 
        list->ptr[list->size]  = str;
434
 
        list->ptr[list->size+1] = NULL;  // le dernier contiens toujours NULL
435
 
 
436
 
        //exit normalement
437
 
        list->size++;
438
 
        return str;
439
 
}
440
 
 
441
 
/************************************************************
442
 
 * Ajoute une copie malloc de str dans list.
443
 
 * Voir l'explication dans gs_list_push() pour avoir plus
444
 
 * de détails.
445
 
 ************************************************************/
446
 
//OK
447
 
char *gs_list_push_m(GS_LIST *list, const char *str)
448
 
{
449
 
        return gs_list_push(list,strdup(str));
450
 
}
451
 
 
452
 
/************************************************************
453
 
 * Désalloque la liste de strings contenue dans le pointeur
454
 
 * du pointeur 'list'.
455
 
 * 
456
 
 * NOTE: Cette fonction met le pointeur 'list' à 0.
457
 
 ************************************************************/
458
 
// Ok
459
 
void gs_list_free(GS_LIST **list)
460
 
{
461
 
        size_t list_size=(*list)->size,i;
462
 
        //free tous les pointeurs dans la liste
463
 
        i=0;
464
 
        while(i<list_size) {
465
 
                FREE((*list)->ptr[i]);
466
 
                i++;
467
 
        }
468
 
        //free la liste
469
 
        FREE((*list)->ptr);
470
 
        //mets null
471
 
        *list=NULL;
472
 
}
473
 
 
474
 
/************************************************************
475
 
 * Retourne une nouvelle allocation mémoire contenant 
476
 
 * dest+src.
477
 
 *
478
 
 * Note: Si dest/src=0 alors ret NULL
479
 
 * 
480
 
 ************************************************************/
481
 
//OK
482
 
char *gs_strcat_m(const char *dest, const char *src)
483
 
{
484
 
        char *ptr;
485
 
        if(!dest || !src) return NULL;
486
 
        ptr=(char *)MALLOC(strlen(dest)+strlen(src)+1);
487
 
        if(!ptr) return 0;
488
 
        strcpy(ptr,dest);
489
 
        strcat(ptr,src);
490
 
        return ptr;
491
 
}
492
 
 
493
 
/************************************************************
494
 
 * Même chose que gs_strcat_m() mais cette fois-ci c'est
495
 
 * 'dest' qui est realloqué pour contenir dest+src
496
 
 *
497
 
 * ATTENTION:
498
 
 * ----------
499
 
 * Quand il n'y a pas assez de mémoire, il retourne NULL
500
 
 * et free 'dest' automatiquement.
501
 
 * Il ne pas réutiliser dest après un NULL
502
 
 * retourné par cette fonction.
503
 
 *
504
 
 * ATTENTION:
505
 
 * ----------
506
 
 * Si dest ou src sont NULL elle retourne systématiquement
507
 
 * NULL et désallque dest si celui-ci est non NULL.
508
 
 *
509
 
 * Notes:
510
 
 * ------
511
 
 * SI: !dest     ret strdup(src)
512
 
 * SI: !src      ret NULL
513
 
 *
514
 
 * Si pas assez de mémoire retourne
515
 
 * 0 mais le pointeur on doit faire 
516
 
 * free(dest) après (comme realloc)
517
 
 ************************************************************/
518
 
//OK
519
 
char *gs_strcat_r(char *dest, const char *src)
520
 
{
521
 
        static char *save;
522
 
        if(!dest || !src) { free(dest); return NULL; }
523
 
        dest = (char *)REALLOC(save=dest, strlen(dest)+strlen(src)+1);
524
 
        if(!dest) {free(save); return dest;}
525
 
        return strcat(dest,src);
526
 
}
527
 
 
528
 
/************************************************************
529
 
 * Cette fonction remplace le caractère 'src' par 'repl'
530
 
 * dans la chaine 'string'.
531
 
 *
532
 
 * Elle retourne un simple pointeur vers 'string'.
533
 
 ************************************************************/
534
 
//OK
535
 
char *gs_creplace(char *string, char src, char repl)
536
 
{
537
 
        char *save=string;
538
 
        while(*string) {
539
 
                if(*string==src) *string=repl;
540
 
                string++;
541
 
        }
542
 
        return save;
543
 
}
544
 
 
545
 
/************************************************************
546
 
 * Remplacement de 'src' par 'repl' dans
547
 
 * 'str'.
548
 
 *
549
 
 * Valeur de retour:
550
 
 * -----------------
551
 
 * Retourne un nouveau pointeur "malloc"
552
 
 * contenant le résultat (remplacement).
553
 
 *
554
 
 * ATTENTION: !str alors ret NULL.
555
 
 ************************************************************/
556
 
//OK
557
 
char *gs_replace_m(const char *str, const char *src, const char *repl)
558
 
{
559
 
        char *str_m; //string alloqué
560
 
        size_t len;
561
 
 
562
 
        if(!str) return NULL;
563
 
 
564
 
        // calcule le nombre de repl dans src
565
 
        len=gs_nstr(str,src);
566
 
        if(!len) return strdup(str);
567
 
        len=(strlen(str)-(len*strlen(src)))+(len*strlen(repl))+1;
568
 
 
569
 
        // Allocation
570
 
        str_m = (char *)MALLOC(len); // src fois * len2
571
 
        if(!str_m) return NULL;
572
 
 
573
 
        strcpy(str_m,str);
574
 
 
575
 
        return gs_replace(str_m,src,repl);
576
 
}
577
 
 
578
 
/************************************************************
579
 
 * Remplacement de 'src' par 'repl'
580
 
 * 'src' est realloqué et contient
581
 
 * le résultat du remplacement.
582
 
 *
583
 
 * Valeur de retour:
584
 
 * -----------------
585
 
 * La fonc retourne un ptr realloqué de
586
 
 * str contenant le remplacement...
587
 
 *
588
 
 * Si pas assez de mémoire retourne NULL.
589
 
 *
590
 
 * ATTENTION: !str alors ret NULL.
591
 
 *
592
 
 ************************************************************/
593
 
//OK
594
 
char *gs_replace_r(char *str, const char *src, const char *repl)
595
 
{
596
 
        char *save;
597
 
        size_t len;
598
 
 
599
 
        if(!str) return NULL;
600
 
 
601
 
        len=gs_nstr(str,src);
602
 
        if(!len) return str;
603
 
        len=strlen(str) - (len*strlen(src)) + (len*strlen(repl)) + 1;
604
 
 
605
 
        str = (char *)REALLOC(save=str,len); // src fois * len2 
606
 
        if(!str) {
607
 
                FREE(save);
608
 
                return 0;
609
 
        }
610
 
 
611
 
        return gs_replace(str,src,repl);
612
 
}
613
 
 
614
 
/************************************************************
615
 
 * Calcule le nombre de fois que 'rech'
616
 
 * est trouvée dans 'str'.
617
 
 ************************************************************/
618
 
//OK
619
 
size_t gs_nstr(const char *str, const char *rech)
620
 
{
621
 
        const char *s=str;
622
 
        size_t n=0;
623
 
        size_t len_rech = strlen(rech);
624
 
 
625
 
        while(s) {
626
 
                s=strstr(s,rech);
627
 
                if(s) { 
628
 
                        n++; s+=len_rech;
629
 
                }
630
 
        }
631
 
 
632
 
        return n;
633
 
}
634
 
 
635
 
/************************************************************
636
 
 * remplace 'src' par 'repl' sans aucune 
637
 
 * reallocation...
638
 
 *
639
 
 * Retour:
640
 
 * -------
641
 
 * La fonction un pointeur vers 'str'.
642
 
 *
643
 
 * ATTENTION:
644
 
 * ----------
645
 
 * Il faut être sûre que 'str' peut contenir 
646
 
 * le remplacement de tous les 'src' par les 
647
 
 * 'repl'.
648
 
 ************************************************************/
649
 
//OK OPTI
650
 
char *gs_replace(char *str, const char *src, const char *repl)
651
 
{
652
 
        static size_t len,len2;
653
 
        static int difference;
654
 
        char *save=str;
655
 
 
656
 
        // Mets les infos
657
 
        len=strlen(src);
658
 
        len2=strlen(repl);
659
 
        difference=len-len2;
660
 
 
661
 
        //ici, le type de remplacement quand il ont la même taille
662
 
        if(!difference) {
663
 
                while((str=strstr(str,src))) {
664
 
                        strncpy(str,repl,len2);
665
 
                        str+=len;
666
 
                }
667
 
        }
668
 
        //si str>repl
669
 
        //Donc il met ce qu'il y a dans 'repl' à la place de 'src'
670
 
        //puis il déplace tout ce qui reste remplit le vide laissé
671
 
        //par 'repl' (puisqu'il est petit) par ce qui reste de str.
672
 
        else if(difference>0) {
673
 
                while((str=strstr(str,src))) {
674
 
                        strncpy(str,repl,len2);
675
 
                        str+=len2;
676
 
                        memmove(str,str+difference,strlen(str+difference)+1);//+1=zero
677
 
                }
678
 
        }
679
 
        //si str<repl
680
 
        //Alors il va laisser de la place à repl pour qu'elle
681
 
        //puisse se permettre de s'installer là ou 'str' est logée.
682
 
        else {
683
 
                while((str=strstr(str,src))) {
684
 
                        memmove(str+len2,str+len,strlen(str+len)+1); //+1 = null final
685
 
                        strncpy(str,repl,len2);
686
 
                        str+=len2;
687
 
                }
688
 
        }
689
 
 
690
 
        return save;
691
 
}
692
 
 
693
 
/************************************************************
694
 
 * Cette fonction concertit tous les caractères de 'str'
695
 
 * en minuscule.
696
 
 * Elle retourne le pointeur 'str'.
697
 
 ************************************************************/
698
 
//OK
699
 
char *gs_lcase(char *str)
700
 
{
701
 
        char *save=str;
702
 
        while(*str) {
703
 
                *str=gs_clcase(*str);
704
 
                str++;
705
 
        }
706
 
        return save;
707
 
}
708
 
 
709
 
/************************************************************
710
 
 * Cette fonction concertit tous les caractères de 'str'
711
 
 * en majuscule.
712
 
 * Elle retourne le pointeur 'str'.
713
 
 ************************************************************/
714
 
//OK
715
 
char *gs_ucase(char *str)
716
 
{
717
 
        char *save=str;
718
 
        while(*str) {
719
 
                *str=gs_cucase(*str);
720
 
                str++;
721
 
        }
722
 
        return save;
723
 
}
724
 
 
725
 
//OK
726
 
char gs_clcase(char c)
727
 
{ return (char)tolower(c); }
728
 
char gs_cucase(char c)
729
 
{ return (char)toupper(c); }
730
 
 
731
 
/************************************************************
732
 
 * _gs_substr fait un substring. Cela veut dire que
733
 
 * le string contient ce qu'il y a à la position 'pos'
734
 
 * à la longueur 'len'.
735
 
 *
736
 
 * ATTENTION:
737
 
 * ----------
738
 
 * Elle ne teste pas si pos->len sont dans le string
739
 
 * ce qui fait que si vous appelez cette fonction il 
740
 
 * faut être sûre de cette donnée.
741
 
 ************************************************************/
742
 
//OK
743
 
char *_gs_substr(char *str, int pos, int len)
744
 
{
745
 
        char *s=str+pos;
746
 
        s[len]=0;
747
 
        if(pos) {
748
 
                static size_t n_len;
749
 
                char *p_str=str;
750
 
                //memmove (str,s)
751
 
                for(n_len=len;n_len;n_len--) {
752
 
                        *p_str=*s;
753
 
                        p_str++; s++;
754
 
                }
755
 
                str[len]=0; //le zero de la fin
756
 
        }
757
 
        return str;
758
 
}
759
 
 
760
 
/************************************************************
761
 
 * La même chose que _gs_substr() mais cette fonction est
762
 
 * plus haut-niveau puisqu'elle teste au moins si 'pos'
763
 
 * et 'len' existent dans 'str' et essaye de les ajuster
764
 
 * si c'est possible.
765
 
 *
766
 
 * NOTE:
767
 
 * -----
768
 
 * En plus elle permet de prendre une position de
769
 
 * la fin du string.
770
 
 * Si pos est négatif cela veut dire
771
 
 * pos=len+pos
772
 
 * position depuis la fin!
773
 
 *
774
 
 * p.ex: -1 c le dernier caractère
775
 
 ************************************************************/
776
 
//OK
777
 
char *gs_substr(char *str, int pos, int len)
778
 
{
779
 
        size_t str_size = strlen(str);
780
 
 
781
 
        // positionne "pos"
782
 
        if(pos<0) pos=str_size+pos;
783
 
        if(!len) {*str=0; return str; } //un string vide si pas de len
784
 
 
785
 
        //il teste si len dépasse
786
 
        if(pos+len>str_size) len=str_size-pos;
787
 
 
788
 
        //fait maintenant un substr
789
 
        return _gs_substr(str,pos,len);
790
 
}
791
 
 
792
 
/************************************************************
793
 
 * Retourne le substr du pointeur 'str' en version malloc.
794
 
 ************************************************************/
795
 
// OK
796
 
char *gs_substr_m(char *str, int pos, int len)
797
 
{
798
 
        char *ptr;
799
 
        if(!str) return NULL;
800
 
 
801
 
        ptr = strdup(str);
802
 
        if(!ptr) return NULL;
803
 
 
804
 
        return gs_substr(ptr,pos,len);
805
 
}
806
 
 
807
 
/************************************************************
808
 
 * Change une partie d'un string
809
 
 *
810
 
 * NOTE:
811
 
 * il faut être sûre qu'il y a assez d'espace mém
812
 
 * pour remplacer le 'len' par strlen'value'.
813
 
 ************************************************************/
814
 
//OK
815
 
char *gs_change(char *str, int pos, int len, const char *value)
816
 
{
817
 
        size_t value_len;
818
 
        if(!str) return NULL;
819
 
 
820
 
        value_len = strlen(value);
821
 
 
822
 
        //Le plus simple...
823
 
        if(value_len==len) 
824
 
                memmove(str+pos,value,value_len);
825
 
        else { //sinon!
826
 
                static char *dest;
827
 
                static char *src;
828
 
                
829
 
                src  = str+pos+len;
830
 
                dest = str+pos+value_len;
831
 
 
832
 
                memmove(dest,src,strlen(src)+1);
833
 
                memmove(str+pos,value,value_len);
834
 
        }
835
 
 
836
 
        return str;
837
 
}
838
 
 
839
 
/************************************************************
840
 
 * Change une partie d'un string par une valeur
841
 
 *
842
 
 * Cette version _m retourne le résultat en malloc (ce
843
 
 * qui veut dire que cette fonction ne touche pas à str)
844
 
 ************************************************************/
845
 
//OK
846
 
char *gs_change_m(const char *str, int pos, int len, const char *value)
847
 
{
848
 
        char *p;
849
 
        if(!str) return NULL;
850
 
        p=(char *)malloc(strlen(str)+strlen(value)-len+1);
851
 
        if(!p) return NULL;
852
 
        return gs_change(p,pos,len,value);
853
 
}
854
 
 
855
 
/************************************************************
856
 
 * Changer une partie d'un string en y mettant une valeur.
857
 
 *
858
 
 * si realloc fail. alors free old str
859
 
 * et ret null.
860
 
 ************************************************************/
861
 
//OK
862
 
char *gs_change_r(char *str, int pos, int len, const char *value)
863
 
{
864
 
        if(!str) return NULL;
865
 
        str=(char *)realloc(str,strlen(str)+strlen(value)-len+1);
866
 
        if(!str) return str;
867
 
        return gs_change(str,pos,len,value);
868
 
}
869
 
 
870
 
/************************************************************
871
 
 * Retourne le pointeur vers le premier caractère dans
872
 
 * str qui appartient à 'accept'.
873
 
 ************************************************************/
874
 
//OK
875
 
char *gs_accept(char *str, const char *accept)
876
 
{       
877
 
        while(*str) {
878
 
                if(strchr(accept,*str))
879
 
                        return str;
880
 
                str++;
881
 
        }
882
 
        return NULL;
883
 
}
884
 
 
885
 
/************************************************************
886
 
 * La même chose que gs_accept() mais à l'envert.
887
 
 ************************************************************/
888
 
//OK
889
 
char *gs_r_accept(char *str, const char *accept)
890
 
{
891
 
        char *end;
892
 
 
893
 
        end=str+strlen(str);
894
 
 
895
 
        while(--end>=str) {
896
 
                if(strchr(accept,*end)) return end;
897
 
        }
898
 
 
899
 
        return NULL;
900
 
}
901
 
 
902
 
/************************************************************
903
 
 * Retourne le pointeur vers le premier caractère qui
904
 
 * n'appartient pas à la chaine reject.
905
 
 ************************************************************/
906
 
//OK
907
 
char *gs_reject(char *str, const char *reject)
908
 
{
909
 
        while(*str) {
910
 
                if(!strchr(reject,*str)) return str;
911
 
                str++;
912
 
        }
913
 
        return NULL;
914
 
}
915
 
 
916
 
//OK
917
 
char *gs_r_reject(char *str, const char *reject)
918
 
{
919
 
        char *end=str+strlen(str);
920
 
 
921
 
        while(--end>=str) {
922
 
                if(!strchr(reject,*end)) return end;
923
 
        }
924
 
 
925
 
        return NULL;
926
 
}
927
 
 
928
 
/************************************************************
929
 
 * Supprime l'emsemble des "reject"
930
 
 * de droite et de gauche de la chaine 'str.
931
 
 ************************************************************/
932
 
// OK
933
 
char *gs_c_trim(char *str, const char *reject)
934
 
{ return gs_c_ltrim(gs_c_rtrim(str,reject),reject); }
935
 
 
936
 
/************************************************************
937
 
 * Supprime l'ensemble des "reject" de gauche.
938
 
 ************************************************************/
939
 
//OK
940
 
char *gs_c_ltrim(char *str, const char *reject)
941
 
{
942
 
        char *s = gs_reject(str,reject);
943
 
        if(!s) {
944
 
                *str=0;
945
 
                return str;
946
 
        }
947
 
        if(s==str) return str;
948
 
        //strcpy(str,s);
949
 
        memmove(str,s,strlen(s)+1);
950
 
        return str;
951
 
}
952
 
 
953
 
/************************************************************
954
 
 * Supprime l'ensemble des "reject" de droite.
955
 
 ************************************************************/
956
 
//OK
957
 
char *gs_c_rtrim(char *str, const char *reject)
958
 
{
959
 
        char *s=gs_r_reject(str,reject);
960
 
        if(!s) {
961
 
                *str=0;
962
 
                return str;
963
 
        }
964
 
        s[1]=0;
965
 
        return str;
966
 
}
967
 
 
968
 
#define TRIM_REJECT " \t\v\r\n\f"
969
 
// \t tabulation horizontale
970
 
// \v tabulation verticale
971
 
// \r carriage return
972
 
// \n line feed (saut de ligne)
973
 
// \f form feed (saut de page)
974
 
 
975
 
/************************************************************
976
 
 * Supprime les espaces de gauche.
977
 
 ************************************************************/
978
 
//OK
979
 
char *gs_ltrim(char *str)
980
 
{
981
 
        return gs_c_ltrim(str,TRIM_REJECT);
982
 
}
983
 
 
984
 
/************************************************************
985
 
 * Supprime les espaces de gauche.
986
 
 ************************************************************/
987
 
//OK
988
 
char *gs_rtrim(char *str) 
989
 
{
990
 
        return gs_c_rtrim(str,TRIM_REJECT);
991
 
}
992
 
 
993
 
/************************************************************
994
 
 * Supprime les espaces de gauche et de droite
995
 
 ************************************************************/
996
 
//OK
997
 
char *gs_trim(char *str) 
998
 
{
999
 
        return gs_ltrim(gs_rtrim(str));
1000
 
}
1001
 
 
1002
 
/************************************************************
1003
 
 * realloque la chaine 'str' selon son len.
1004
 
 ************************************************************/
1005
 
//OK
1006
 
char *gs_fix_realloc(char *str)
1007
 
{
1008
 
        if(!str) return 0;
1009
 
        return (char *)REALLOC(str,strlen(str)+1);
1010
 
}
1011