IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Lire un fichier, extraire les infos


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    Cyberdocumentaliste
    Inscrit en
    Janvier 2013
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Cyberdocumentaliste

    Informations forums :
    Inscription : Janvier 2013
    Messages : 79
    Par défaut Lire un fichier, extraire les infos
    Bonjour, j'essaie depuis ce matin d'extraire des données de configuration d'un fichier texte.
    Ce fichier comprend pour tester des identifiants à une base de donnée.

    J'ai donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    	FILE* fichier = NULL;
    	fichier = fopen("config.cnf", "r+");
     
    	char chaine[23] ;
    	char *token;
    	int i = 0;
    	int j = 0;
     
    	char *server;
    	char *user;
    	char *password;
    	char *database;
    	int caractereActuel = 0;
     
    	if (fichier != NULL){
     
    		//fseek(fichier, 1, SEEK_CUR);
     
            do{
                caractereActuel = fgetc(fichier); // On lit le caractère
    			if(caractereActuel == '='){
    			i++;
    				fseek(fichier, 0, SEEK_CUR);
    				fgets(chaine, 20, fichier);
    				switch(i){
    					case 0:
    						server = chaine;
    					break;
    					case 1:
    						user = chaine;
    					break;
    					case 2:
    						password = chaine;
    					break;
    					case 3: 
    						database = chaine;
    					break;
    					default:
    					break;
    				}
    			}
            } while (caractereActuel != EOF); // On continue tant que fgetc n'a pas retourné EOF (fin de fichier)
     
    		printf("%s <br />", server);
    		printf("%s<br />", user);
    		printf("%s<br />", password);
    		printf("%s<br />", database);
     
     
    		fclose(fichier); 
        }

    J'ai essayé de 100 manière différents, a chaque fois c'est le foutoir.
    Mon fichier ressemble a
    ip=localhost
    user=user
    pass=pass
    database=database

    Merci pour votre aide

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 814
    Par défaut
    Il faut faire un automate ... comme la machine à café
    Je te laisse chercher avec ton moteur de recherche WEB préféré, mais en gros:

    Si on élimine les espaces et que l'on garde que des caractères minuscules et les fins de lignes:
    On attend soit un i soit un p soit un u soit un d (à moins que les attributs soient dans un ordre précis)

    Si c'est i, on va attendre successivement un p, un = (sinon erreur) et ensuite jusqu'à la fin de ligne on prend tous les caractères -> on a l'ip
    Si c'est p, on va attendre successivement un a, un s, un s, un = (sinon erreur) et ensuite jusqu'à la fin de ligne on prend tous les caractères -> on a le mot de passe

    Et ainsi de suite

    Édit: un automate c'est une machine à état.
    Mais dans ton cas, la programmation objet n'est pas nécessaire.
    Il faut faire des switch dans des switch

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    pas forcément switch switch.
    le fonctionnement de base serait:
    tant qu'on peut lire une ligne {
        s'il n'y a pas un unique '=', sauter la ligne (avec un message?)
        découper chaque ligne autour du '='
        retirer les espaces extérieurs de chaque morceau. (trim...)
        si le premier morceau correspond à une des clés de définition, extraire la valeur du second morceau.
    }
    à toi de coder les fonctions utiles, et de récupérer sur le net des codes pour trim et split.

    L'automate caractère à caractère n'est pas toujours une bonne idée

  4. #4
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    Citation Envoyé par foetus Voir le message
    Il faut faire un automate ... [...]
    Édit: un automate c'est une machine à état.
    Mais dans ton cas, la programmation objet n'est pas nécessaire.
    Il faut faire des switch dans des switch
    Ça me semble un peu brutal comme méthode pour parser un fichier aussi simplement formaté ...
    Et puis imagine la tête du mec qui reprend le code après

    Sinon l'algorithme de leternel est à peu près ce que j'aurais fait.

  5. #5
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 814
    Par défaut
    Citation Envoyé par leternel Voir le message
    L'automate caractère à caractère n'est pas toujours une bonne idée
    Au moins avec l'automate caractère par caractère, on peut mettre un couple (clef, valeur) sur plusieurs lignes (mais le mieux pour cela c'est d'avoir un caractère fin de ligne)

    Tu oublies de dire (comme moi), qu'en partant du début d'une ligne, il faut mémoriser la position du premier caractère "lettre ou éventuellement chiffre" (CL) et du dernier CL avant l'égal pour le découpage.
    Et de même après l'égal

    Et enfin tu oublies de dire qu'avec ta méthode , il faudra faire des strcmp en "try and retry", avec éventuellement une sélection sur les premiers caractères

    Citation Envoyé par the Hound Voir le message
    Ça me semble un peu brutal comme méthode pour parser un fichier aussi simplement formaté ...
    Et puis imagine la tête du mec qui reprend le code après

    Sinon l'algorithme de leternel est à peu près ce que j'aurais fait.
    ou

    Justement je me demande si tu peux faire le switch sur le caractère courant avant le switch sur l'état, pour compacter l'automate


    Et éventuellement, c'est peut-être du code vite-fait pour dépanner: donc la tronche qu'il a on s'en fiche

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    J'aurai bien donné un peu de code, mais je ne connais que la solution C++ (std::getline et istringstream)
    En C, je ne sais plus comment l'écrire, mais j'imagine qu'avec fgets et les fonctions de recherche dans une chaine, on peut s'en sortir.

  7. #7
    Membre confirmé
    Homme Profil pro
    Cyberdocumentaliste
    Inscrit en
    Janvier 2013
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Cyberdocumentaliste

    Informations forums :
    Inscription : Janvier 2013
    Messages : 79
    Par défaut
    Super, merci.

    je vais me pencher sur l'algo de leternel

    A plus tard pour les nouvelles,

  8. #8
    Membre actif
    Homme Profil pro
    Admin Unix & Dev Sénior
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Brésil

    Informations professionnelles :
    Activité : Admin Unix & Dev Sénior

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Par défaut
    Salut,

    A moins d'être en auto-formation, pourquoi refaire la roue !

    Il existe un snippets C qui contient un code complet et documenté pour ce genre de problème !

    Aller, je mache le travail de recherche snip-c.zip

    @+ et bon dev

  9. #9
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Sauf que visiblement, c'est une question de formation.
    Parce que ce problème est assez simple pour qu'un pratiquant du C professionnel connaisse la réponse.
    (je ne suis qu'amateur en C, mais j'ai une certaine habitude du C++, et les algos sont les mêmes)

    Comme en plus notre règlement nous interdit de donner des réponses toutes faites, c'est dommage.

    @JokerAs:
    N'hésite surtout pas à revenir nous montrer ce que tu as fait, pour qu'on te donne nos avis.

  10. #10
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Salut,

    Si ton fichier de config est toujours du même format, tu peux utiliser le sscanf. Attention: Il faut tester ABSOLUMENT le retour de sscanf qui retourne le nombre de champs trouvés !
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    const char *filename = "test.txt" ;
    FILE *fd = NULL ;
    char chaine[128] = "" ;
     
    char champsTexte[128] = "" ;
     
    // Ouverture du fichier
    if((fd=fopen(filename, "r"))==NULL) {
        fprintf(stderr, "Erreur d'ouverture du fichier %s\n", filename) ;
        return EXIT_FAILURE ;
    }
     
    // Lecture du fichier
    while(fgets(chaine, 128, fd)) {
        // Recherche des mots clefs
        if(sscanf(chaine, "ip = %[^\n]\n", champsTexte)==1)
            printf("champsTexte[ip] = %s\n", champsTexte) ;
        else if(sscanf(chaine, "user = %[^\n]\n", champsTexte)==1)
            printf("champsTexte[user] = %s\n", champsTexte) ;
        else if(sscanf(chaine, "pass = %[^\n]\n", champsTexte)==1)
            printf("champsTexte[pass] = %s\n", champsTexte) ;
        else if(sscanf(chaine, "database = %[^\n]\n", champsTexte)==1)
            printf("champsTexte[database] = %s\n", champsTexte) ;
    }
     
    // Fermeture du fichier
    fclose(fd) ;
    Le format du sscanf "ip = %[^\n]\n" défini qu'il faut mettre tout ce qu'il y a entre le signe '=' sans l'inclure et le retour de chariot '\n' sans l'inclure non plus.

    Bonne continuation.

  11. #11
    Membre actif
    Homme Profil pro
    Admin Unix & Dev Sénior
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Brésil

    Informations professionnelles :
    Activité : Admin Unix & Dev Sénior

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Par défaut
    Citation Envoyé par Elijha Voir le message
    Salut,

    Si ton fichier de config est toujours du même format, tu peux utiliser le sscanf. Attention: Il faut tester ABSOLUMENT le retour de sscanf qui retourne le nombre de champs trouvés !
    Sauf que dans la vrai vie, si le fichier est modifié par un "humain", il faut gérer les espaces autour du '='.

  12. #12
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Citation Envoyé par hartyshow Voir le message
    Sauf que dans la vrai vie, si le fichier est modifié par un "humain", il faut gérer les espaces autour du '='.
    Vrai, mais c'est pour cela que dans le format du sscanf il y a des espaces autour du signe '='.
    Avec ce format, que la chaîne à analyser soit "ip=localhost" ou "ip <beaucoup d'espaces> = <beaucoup d'espaces> localhost" le sscanf ne tiendra pas compte des espaces.
    Par contre, s'il y a des espaces ou autres caractères après/dans le localhost ils seront retournés dans la chaîne du résultat car le format spécifié ci-dessus prend TOUS les caractères jusqu'au retour chariot (sans l'inclure).

    Si l'on voulait qu'un seul "mot" sans espace le format suivant suffirait : " ip = %s" (toujours avec les espaces autour du signe '=').

  13. #13
    Membre confirmé
    Homme Profil pro
    Cyberdocumentaliste
    Inscrit en
    Janvier 2013
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Cyberdocumentaliste

    Informations forums :
    Inscription : Janvier 2013
    Messages : 79
    Par défaut
    merci à tous,

    Réinventer la roue mouai mais réutiliser les codes des autres sans les comprendre, pour moi ça ne sert a rien.
    Je viens d'analyser un peu plus en profondeur sscanf(). C'est vrai que c'est interessant.

    Au début, je lisais caractère par caractère et avec des if ... (je vous laisse imaginer le code).

    Le problème, c'est que je ne savais pas combien de caractère j'allais mettre dans mon tableau. J'utilise par la suite l'API de mysql.

    J'ai tout essayé, libconfig, celle de ssl, je suis même allez jusq'au xml (libxml2). Mais rien. Je ne suis pas un chevronné du C.

    Dans un second temps, j'avais pensé a:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Tant que je peux lire un caractère (
         Si caractère '='
              Récupère la ligne
              Scinde en 2
              Récupère la seconde partie (c'est la le switch)
    )
    Je récupérais bien ce que je voulais, mais l'API de mysql me le rejetait. (l'histoire du tableau a moitié rempli je crois)

    Je vais donc surement lire ligne par ligne et avec sscanf recherche la structure et récupérer le reste. Si il y a des espaces ou autre, tampis. Ce sera la faute de l'utilisateur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sscanf(maLigne, "ip=%[^\n]\n", ip)
    Je n'avais pas pensé aux regex (même je croyais qu'en C, ce n'était pas possible).

    Mais vaut mieux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sscanf(maLigne, "ip=%[^\n]\n", ip)
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sscanf(maLigne, "ip=%s\n", ip)
    Merci

  14. #14
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Citation Envoyé par JokerAs Voir le message
    ...
    Mais vaut mieux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sscanf(maLigne, "ip=%[^\n]\n", ip)
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sscanf(maLigne, "ip=%s\n", ip)
    Merci
    Salut,

    Cela dépend de ce que tu a besoin.
    Sur la ligne ip, si tu as une ip au format xxx.xxx.xxx.xxx et que tu es sur et certain qu'il n'y aura pas d'espaces entre les digits tu peux utiliser le '%s'.
    Pour le user, si c'est un nom composé comme "Jean Bon Neau", il vaut mieux dans ce cas tout prendre avec le format "user = %[^\n]\n".
    Etc...

    Nota 1 : Attention le format de sscanf doit comporter des espaces autour du signe '=' : "ip = %s\n"
    Nota 2 : Toujours tester le retour du sscanf.
    Nota 3 : Pour l'ip tu pourrais même récupérer chaque digit. Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if(sscanf(chaine, "ip = %d.%d.%d.%d\n", &digit1, &digit2, &digit3, &digit4)==4) {
        printf("IP = %d.%d.%d.%d\n", digit1, digit2, digit3, digit4) ;
    }
    Bonne continuation.

  15. #15
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Merci foetus pour cette exemple.

    Si tu penses pouvoir tester plus ce code, tu pourrais le proposer dans les sources C.

  16. #16
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 814
    Par défaut
    @leternel: je dirai que comme c'est un automate, cela devrait fonctionner . À part les allocations et les réallocations
    Maintenant, c'est juste pour montrer une façon et je n'ai pas une batterie de fichiers tests.
    De plus il manque le beau dessin de mon automate

    M.A.J.: corrigé 4-5 trucs (dont des attributs non libérés et des variables qui ne servaient à rien et une fin de fichier inattendue) avec du renommage
    Et aussi, un mode debug gcc main.c parser.c -DDEBUG.

    M.A.J.: Arf Mes états END_CMD, VALUE_IP_4 et WAIT_IP ont les mêmes cas mais ont respectivement "rien à faire", "faire un traitement pendant le changement d'état" et "faire un traitement".
    Ce qui oblige d'écrire 3 fois presque le même code

    Juste parce que certains intervenants me mettent des -1 sans véritable raison, voici ma noble contribution , testé au minimum
    En gros
    • Parser ANSI. J'ai regardé la prise en charge de l'Unicode, mais je ne pense pas que ce soit une priorité.
    • Il y a 4 clefs database, ip, user, et pass, qui doivent être uniques.
    • database, user et pass acceptent comme valeur une chaîne avec seulement les lettres minuscules de l'alphabet
    • ip accepte comme valeur soit IPV4 XXX.XXX.XXX.XXX soit une chaîne comme ci-dessus (c'est un alias comme localhost)
    • Tous les zéros qui sont devant IPV4 sont retirés (ils ne servent à rien) et un test > 256 est fait sur chaque partie
    • On peut écrire clef=valeur sur plusieurs lignes
    • J'ai géré les fins de fichiers Linux LF et celles Windows CRLF


    Temps de réalisation: 3 à 5 Heures (+ 2 Heures de pseudo-tests)


    main.c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include "parser.h"
     
     
    int main() {
        struct Parser parser;
     
        init_parser(&parser);
        load_file(&parser, "file.txt");
        parse_file(&parser);
        print_infos(&parser);
        reset_parser(&parser);
     
        return 0;
    }

    parser.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    #ifndef PARSER_H
    #define PARSER_H
     
    #include<stdlib.h>
    #include<stdio.h>
     
     
    // All states and errors
    typedef enum {
        START_CMD = 0, END_CMD,
    //  key: ip
        IP_1,
    //  key: user
        USER_1, USER_2, USER_3,
    //  key: pass
        PASS_1, PASS_2, PASS_3,
    //  key: database
        DB_1, DB_2, DB_3, DB_4, DB_5, DB_6, DB_7,
    //  the equal sign
        EQUAL,
    //  data: an ip - XX.XX.XX.XX
        WAIT_IP, VALUE_IP_1, VALUE_IP_2, VALUE_IP_3, VALUE_IP_4,
    //  data: a string
        WAIT_STRING, VALUE_STRING,
    //  remove all leading 0 before an ip
        SKIP_ZERO,
    //  to manage CR \r
        WAIT_LF_BEFORE_KEY, WAIT_LF_AFTER_KEY, WAIT_LF_BEFORE_STRING, WAIT_LF_BEFORE_IP, WAIT_LF_END_CMD,
    //  an error
        STATE_ERROR
    } STATE;
     
     
    typedef enum {
        NO_ERROR = 0,
        OPEN_FILE,
        MISSING_KEY,
        NOT_A_KEY,
        IP_NOT_UNIQUE,
        USER_NOT_UNIQUE,
        PASS_NOT_UNIQUE,
        DATABASE_NOT_UNIQUE,
        EQUAL_NOT_FOUND,
        STRING_NOT_FOUND,
        BAD_STRING,
        IP_NOT_FOUND,
        BAD_IP,
        GREATER_255,
        BAD_END_CMD,
        LF_NOT_FOUND,
        UNEXPECTED_EOF,
        ALLOCATING_MEMORY
    } ERROR;
     
     
    typedef enum {
        KEY_NEW = 0,
        KEY_IP,
        KEY_PASS,
        KEY_USER,
        KEY_DATABASE,
    } KEY;
     
     
    // All structs
    struct Data {
        char* user;
        char* pass;
        char* database;
        char* ip_alias;
     
        unsigned short len_user;
        unsigned short len_pass;
        unsigned short len_database;
        unsigned short len_ip_alias;
     
        unsigned short ip_1;
        unsigned short ip_2;
        unsigned short ip_3;
        unsigned short ip_4;
    };
     
     
    struct Parser {
        FILE* file;
     
        struct Data data;
     
    //  Internal states
        unsigned short line;
        unsigned short col;
     
        STATE state;
        ERROR error;
        KEY key;
    };
     
     
    // All functions
    void init_parser(struct Parser* parser);
     
    void load_file(struct Parser* parser, char* filename);
     
    void parse_file(struct Parser* parser);
     
    void print_infos(struct Parser* parser);
     
    void reset_parser(struct Parser* parser);
     
    #endif // PARSER_H

    parser.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    #include "parser_utils.h"
     
     
    // All functions
    void init_parser(struct Parser* parser) {
        if (parser == NULL) { return; }
     
        parser->line = parser->col = 1;
        parser->file = NULL;
     
        parser->state = START_CMD;
        parser->error = NO_ERROR;
        parser->key   = KEY_NEW;
     
        parser->data.user     = parser->data.pass     = parser->data.database     = parser->data.ip_alias     = NULL;
        parser->data.len_user = parser->data.len_pass = parser->data.len_database = parser->data.len_ip_alias = 0;
        parser->data.ip_1 = parser->data.ip_2 = parser->data.ip_3 = parser->data.ip_4 = 0;
    }
     
     
    void load_file(struct Parser* parser, char* filename) {
        if (parser == NULL) { return; }
     
        if (parser->file != NULL) { fclose(parser->file); }
     
        parser->file = fopen(filename, "r+");
     
        if (parser->file == NULL) {
            parser->state = STATE_ERROR;
            parser->error = OPEN_FILE;
        }
    }
     
     
    void parse_file(struct Parser* parser) {
        if ((parser == NULL) || (parser->error != NO_ERROR) || (parser->file == NULL)) { return; }
     
        char one_line[MAX_CHARACTERS];
        memset(one_line, MAX_CHARACTERS, '\0');
     
        unsigned short col = 0, col_start = 0;
        char c = '\0';
     
        while((parser->error == NO_ERROR) && (fgets(one_line, MAX_CHARACTERS, parser->file) != NULL)) {
            col = col_start = 0;
            c = one_line[0];
     
            while((parser->error == NO_ERROR) && (c != '\0') && (col < (MAX_CHARACTERS - 1))) {
    #ifdef DEBUG
                debug_parser(parser, c);
    #endif
     
    //          If an error occurs, parser->col has an additional column
                parser->col++;
     
                switch(parser->state) {
                case START_CMD:
                    switch(c) {
                    case '=':
                        parser->state = STATE_ERROR;
                        parser->error = MISSING_KEY;
                        break;
                    ONE_CASE('i', IP_1)
                    ONE_CASE('u', USER_1)
                    ONE_CASE('p', PASS_1)
                    ONE_CASE('d', DB_1)
                    WAIT(START_CMD, WAIT_LF_BEFORE_KEY, NOT_A_KEY)
                    }
                    break;
     
    //          Key: ip
                KEY_LAST_CHAR(IP_1, 'p', KEY_IP, IP_NOT_UNIQUE)
     
    //          Key: user
                WAIT_ONE_CHAR(USER_1, 's', USER_2,   NOT_A_KEY);
                WAIT_ONE_CHAR(USER_2, 'e', USER_3,   NOT_A_KEY);
                KEY_LAST_CHAR(USER_3, 'r', KEY_USER, USER_NOT_UNIQUE)
     
    //          Key: pass
                WAIT_ONE_CHAR(PASS_1, 'a', PASS_2,   NOT_A_KEY);
                WAIT_ONE_CHAR(PASS_2, 's', PASS_3,   NOT_A_KEY);
                KEY_LAST_CHAR(PASS_3, 's', KEY_PASS, PASS_NOT_UNIQUE)
     
    //          Key: database
                WAIT_ONE_CHAR(DB_1, 'a', DB_2, NOT_A_KEY);
                WAIT_ONE_CHAR(DB_2, 't', DB_3, NOT_A_KEY);
                WAIT_ONE_CHAR(DB_3, 'a', DB_4, NOT_A_KEY);
                WAIT_ONE_CHAR(DB_4, 'b', DB_5, NOT_A_KEY);
                WAIT_ONE_CHAR(DB_5, 'a', DB_6, NOT_A_KEY);
                WAIT_ONE_CHAR(DB_6, 's', DB_7, NOT_A_KEY);
                KEY_LAST_CHAR(DB_7, 'e', KEY_DATABASE, DATABASE_NOT_UNIQUE)
     
                case EQUAL:
                    switch(c) {
                    case '=':
                        switch(parser->key) {
                        case KEY_PASS: case KEY_USER: case KEY_DATABASE: parser->state = WAIT_STRING; break;
                        case KEY_IP: parser->state = WAIT_IP; break;
                        }
                        break;
                    WAIT(EQUAL, WAIT_LF_AFTER_KEY, EQUAL_NOT_FOUND)
                    }
                    break;
     
                case WAIT_STRING:
                    switch(c) {
                    CASE_ALL_LETTERS
                        col_start = col;
                        parser->state = VALUE_STRING;
                        break;
                    WAIT(WAIT_STRING, WAIT_LF_BEFORE_STRING, STRING_NOT_FOUND)
                    }
                    break;
     
                case VALUE_STRING:
                    switch(c) {
                    CASE_ALL_LETTERS
                        break;
                    case ' ':
                        RECOPY_STRING
                        parser->state = END_CMD;
                        break;
                    case '\r':
                        RECOPY_STRING
                        parser->state = WAIT_LF_END_CMD;
                        break;
                    case '\n':
                        RECOPY_STRING
                        parser->state = START_CMD;
                        NEW_LINE
                        break;
                    DEFAULT_ERROR(BAD_STRING)
                    }
                    break;
     
                case WAIT_IP:
                    switch(c) {
                    CASE_ALL_DIGITS
                        parser->state = VALUE_IP_1;
                        parser->data.ip_1 = (c - '0');
                        break;
                    ONE_CASE('0', SKIP_ZERO)
                    CASE_ALL_LETTERS
                        col_start = col;
                        parser->state = VALUE_STRING;
                        break;
                    WAIT(WAIT_IP, WAIT_LF_BEFORE_IP, IP_NOT_FOUND)
                    }
                    break;
     
                case SKIP_ZERO:
                    switch(c) {
                    case '0':
                        break;
                    CASE_ALL_DIGITS
                        parser->state = VALUE_IP_1;
                        parser->data.ip_1 = (c - '0');
                        break;
                    DEFAULT_ERROR(IP_NOT_FOUND)
                    }
                    break;
     
    //          Get IP
                GET_ONE_NUMBER(parser->data.ip_1, VALUE_IP_1, VALUE_IP_2, '.', 0);
                GET_ONE_NUMBER(parser->data.ip_2, VALUE_IP_2, VALUE_IP_3, '.', 0);
                GET_ONE_NUMBER(parser->data.ip_3, VALUE_IP_3, VALUE_IP_4, '.', 0);
                GET_ONE_NUMBER(parser->data.ip_4, VALUE_IP_4, START_CMD, '\n', 1);
     
                case END_CMD:
                    switch(c) {
                    WAIT(START_CMD, WAIT_LF_END_CMD, BAD_END_CMD);
                    }
                    break;
     
                WAIT_NEW_LINE(WAIT_LF_BEFORE_KEY,    START_CMD,   LF_NOT_FOUND);
                WAIT_NEW_LINE(WAIT_LF_AFTER_KEY,     EQUAL,       LF_NOT_FOUND);
                WAIT_NEW_LINE(WAIT_LF_BEFORE_STRING, WAIT_STRING, LF_NOT_FOUND);
                WAIT_NEW_LINE(WAIT_LF_BEFORE_IP,     WAIT_IP,     LF_NOT_FOUND);
                WAIT_NEW_LINE(WAIT_LF_END_CMD,       START_CMD,   LF_NOT_FOUND);
                }
     
                col++;
                c = one_line[col];
            }
     
    //      one_line can contain a part of a line
            RECOPY_STRING
        }
     
        if ((parser->state != STATE_ERROR) && (parser->state != START_CMD) && (parser->state != END_CMD)  &&
            (parser->state != VALUE_IP_4)  && (parser->state != VALUE_STRING)) {
     
            parser->state = STATE_ERROR;
            parser->error = UNEXPECTED_EOF;
        }
     
        fclose(parser->file);
        parser->file = NULL;
    }
     
     
    void print_infos(struct Parser* parser) {
        if (parser->error == NO_ERROR) {
            if ((parser->data.ip_alias != NULL) && (parser->data.len_ip_alias > 1)) {
                printf("ip: %s (%d)\n", parser->data.ip_alias, (parser->data.len_ip_alias - 1));
            } else if (parser->data.ip_1 != 0) {
                printf("ip: %d.%d.%d.%d\n", parser->data.ip_1, parser->data.ip_2, parser->data.ip_3, parser->data.ip_4);
            }
     
            if ((parser->data.user != NULL) && (parser->data.len_user > 1)) {
                printf("user: %s (%d)\n", parser->data.user, (parser->data.len_user - 1));
            }
     
            if ((parser->data.pass != NULL) && (parser->data.len_pass > 1)) {
                printf("pass: %s (%d)\n", parser->data.pass, (parser->data.len_pass - 1));
            }
     
            if ((parser->data.database != NULL) && (parser->data.len_database > 1)) {
                printf("database: %s (%d)\n", parser->data.database, (parser->data.len_database - 1));
            }
        } else {
            parser->col--;
     
            switch(parser->error) {
            case OPEN_FILE:           printf("Error - Cannot open input file\n"); break;
            case ALLOCATING_MEMORY:   printf("Error - (e)allocating memory\n");  break;
            case UNEXPECTED_EOF:      printf("Error - Unexpected end of file\n"); break;
            case MISSING_KEY:         printf("L%d, C%d: Error - Missing key\n", parser->line, parser->col); break;
            case NOT_A_KEY:           printf("L%d, C%d: Error - This is not a key\n", parser->line, parser->col); break;
            case IP_NOT_UNIQUE:       printf("L%d, C%d: Error - Key ip already exists\n", parser->line, parser->col); break;
            case USER_NOT_UNIQUE:     printf("L%d, C%d: Error - Key user already exists\n", parser->line, parser->col); break;
            case PASS_NOT_UNIQUE:     printf("L%d, C%d: Error - Key pass already exists\n", parser->line, parser->col); break;
            case DATABASE_NOT_UNIQUE: printf("L%d, C%d: Error - Key database already exists\n", parser->line, parser->col); break;
            case EQUAL_NOT_FOUND:     printf("L%d, C%d: Error - Expected equal sign not found\n", parser->line, parser->col); break;
            case STRING_NOT_FOUND:    printf("L%d, C%d: Error - Expected string not found\n", parser->line, parser->col); break;
            case BAD_STRING:          printf("L%d, C%d: Error - String miswritten\n", parser->line, parser->col); break;
            case IP_NOT_FOUND:        printf("L%d, C%d: Error - Expected ip not found\n", parser->line, parser->col); break;
            case BAD_IP:              printf("L%d, C%d: Error - IP miswritten\n", parser->line, parser->col); break;
            case GREATER_255:         printf("L%d, C%d: Error - IP number > 255\n", parser->line, parser->col); break;
            case BAD_END_CMD:         printf("L%d, C%d: Error - Waiting spaces or one end of command\n", parser->line, parser->col); break;
            case LF_NOT_FOUND:        printf("L%d, C%d: Error - Expected end of line not found\n", parser->line, parser->col); break;
            }
        }
    }
     
     
    void reset_parser(struct Parser* parser) {
        if (parser == NULL) { return; }
     
        if (parser->data.user != NULL)     { DLOG( ("free user\n") ); free(parser->data.user); }
        if (parser->data.pass != NULL)     { DLOG( ("free pass\n") ); free(parser->data.pass); }
        if (parser->data.database != NULL) { DLOG( ("free database\n") ); free(parser->data.database); }
        if (parser->data.ip_alias != NULL) { DLOG( ("free ip_alias\n") ); free(parser->data.ip_alias); }
     
        if (parser->file != NULL) { fclose(parser->file); }
     
        init_parser(parser);
    }
     
     
    // All private functions
    char check_key_is_unique(struct Parser* parser) {
        if (parser == NULL)  { return 0; }
     
        char ret = 0;
     
        switch(parser->key) {
        case KEY_IP:
            if ((parser->data.ip_1 == 0) && (parser->data.ip_alias == NULL)) {
                ret = 1;
            }
            break;
        case KEY_USER:
            if (parser->data.user == NULL) { ret = 1; }
            break;
        case KEY_PASS:
            if (parser->data.pass == NULL) { ret = 1; }
            break;
        case KEY_DATABASE:
            if (parser->data.database == NULL) { ret = 1; }
            break;
        }
     
        return ret;
    }
     
     
    void debug_parser(struct Parser* parser, char current_c) {
        printf("%3d, %3d: ", parser->line, parser->col);
     
        char print_c = 1, print_key = 0;
     
        switch(parser->state) {
        case START_CMD:    printf("START_CMD    - "); print_key = 1; break;
        case END_CMD:      printf("END_CMD      - "); break;
        case IP_1:         printf("IP_1         - "); break;
        case USER_1:       printf("USER_1       - "); break;
        case USER_2:       printf("USER_2       - "); break;
        case USER_3:       printf("USER_3       - "); break;
        case PASS_1:       printf("PASS_1       - "); break;
        case PASS_2:       printf("PASS_2       - "); break;
        case PASS_3:       printf("PASS_3       - "); break;
        case DB_1:         printf("DB_1         - "); break;
        case DB_2:         printf("DB_2         - "); break;
        case DB_3:         printf("DB_3         - "); break;
        case DB_4:         printf("DB_4         - "); break;
        case DB_5:         printf("DB_5         - "); break;
        case DB_6:         printf("DB_6         - "); break;
        case DB_7:         printf("DB_7         - "); break;
        case EQUAL:        printf("EQUAL        - "); print_key = 1; break;
        case WAIT_IP:      printf("WAIT_IP      - "); break;
        case VALUE_IP_1:   printf("VALUE_IP_1   - "); break;
        case VALUE_IP_2:   printf("VALUE_IP_2   - "); break;
        case VALUE_IP_3:   printf("VALUE_IP_3   - "); break;
        case VALUE_IP_4:   printf("VALUE_IP_4   - "); break;
        case SKIP_ZERO:    printf("SKIP_ZERO    - "); break;
        case WAIT_STRING:  printf("WAIT_STRING  - "); break;
        case VALUE_STRING: printf("VALUE_STRING - "); break;
        case STATE_ERROR:  printf("STATE_ERROR  - "); break;
        case WAIT_LF_BEFORE_KEY:    printf("WAIT_LF_BEFORE_KEY");    print_c = 0; break;
        case WAIT_LF_AFTER_KEY:     printf("WAIT_LF_AFTER_KEY");     print_c = 0; break;
        case WAIT_LF_BEFORE_STRING: printf("WAIT_LF_BEFORE_STRING"); print_c = 0; break;
        case WAIT_LF_BEFORE_IP:     printf("WAIT_LF_BEFORE_IP");     print_c = 0; break;
        case WAIT_LF_END_CMD:       printf("WAIT_LF_END_CMD");       print_c = 0; break;
        }
     
        if (print_c) {
            switch(current_c)  {
            case '\n': printf("EOL");   break;
            case '\r': printf("CR");    break;
            case ' ':  printf("SPACE"); break;
            default:   printf("%c", current_c); break;
            }
        }
     
        if (print_key) {
            printf(" - ");
            PRINT_KEY(parser);
        }
     
        printf("\n");
    }

    parser_utils.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    #ifndef PARSER_UTILS_H
    #define PARSER_UTILS_H
     
    #include<string.h>
     
    #include "parser.h"
     
     
    // Const
    #define MAX_CHARACTERS 128
     
     
    // All private functions
    char check_key_is_unique(struct Parser* parser);
     
    void debug_parser(struct Parser* parser, char current_c);
     
    #define PRINT_KEY(parser) \
        switch(parser->key) { \
        case KEY_NEW:      printf("KEY_NEW");      break; \
        case KEY_IP:       printf("KEY_IP");       break; \
        case KEY_PASS:     printf("KEY_PASS");     break; \
        case KEY_USER:     printf("KEY_USER");     break; \
        case KEY_DATABASE: printf("KEY_DATABASE"); break; \
        }
     
     
    // All marcros
     
    #define CASE_ALL_LETTERS \
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': \
        case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
     
     
    // 1 - 9, except 0
    #define CASE_ALL_DIGITS \
        case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
     
     
    #ifdef DEBUG
    #define DLOG( X ) printf X;
    #else
    #define DLOG( X )
    #endif
     
     
    #define DEFAULT_ERROR(default_error) \
        default: \
            parser->state = STATE_ERROR; \
            parser->error = default_error; \
            break;
     
     
    #define EXTEND_ATTRIBUTE(attribute, its_len) \
        if (attribute == NULL) { \
            its_len = (col - col_start + 1); \
            DLOG( ("EXTEND_ATTRIBUTE: malloc %d\n", its_len) ) \
            attribute = (char*) malloc(its_len * sizeof(char)); \
            memcpy(attribute, (one_line + col_start), (its_len - 1)); \
            attribute[its_len - 1] = '\0'; \
        } else { \
            char* tmp_str  = NULL; \
            short last_len = its_len; \
     \
            its_len += (col - col_start); \
            tmp_str = (char*) realloc(attribute, its_len * sizeof(char)); \
     \
            if (tmp_str != NULL) { \
                DLOG( ("EXTEND_ATTRIBUTE: realloc %d (%d -> %d)\n", (col - col_start), last_len, its_len) ) \
                attribute = tmp_str; \
                memcpy((attribute + last_len - 1), (one_line + col_start), (col - col_start)); \
               attribute[its_len - 1] = '\0'; \
            } else { \
                free(attribute); \
                its_len = 0; \
                parser->state = STATE_ERROR; \
                parser->error = ALLOCATING_MEMORY; \
            } \
        }
     
     
    #define GET_ONE_NUMBER(ip_number, current_state, next_state, last_car, is_last) \
        case current_state: \
            switch(c) { \
            case '0': CASE_ALL_DIGITS \
                ip_number = (ip_number * 10 + (c - '0')); \
     \
                if (ip_number > 255) { \
                    parser->state = STATE_ERROR; \
                    parser->error = GREATER_255; \
                } \
                break; \
            case last_car: \
                parser->state = next_state; \
     \
                if (last_car == '\n') { NEW_LINE } \
                break; \
            case ' ': \
                if (is_last) { \
                    parser->state = END_CMD; \
                } else { \
                    parser->state = STATE_ERROR; \
                    parser->error = BAD_IP; \
                } \
                break; \
            case '\r': \
                if (is_last) { \
                    parser->state = WAIT_LF_END_CMD; \
                } else { \
                    parser->state = STATE_ERROR; \
                    parser->error = BAD_IP; \
                } \
                break; \
            DEFAULT_ERROR(BAD_IP) \
            } \
            break;
     
     
    #define KEY_LAST_CHAR(one_state, last_c, current_key, key_error) \
        case one_state: \
            switch(c) { \
            case last_c: \
                parser->key = current_key; \
     \
                if ( check_key_is_unique(parser) ) { \
                    parser->state = EQUAL; \
                } else { \
                    parser->state = STATE_ERROR; \
                    parser->error = key_error; \
                } \
                break; \
            DEFAULT_ERROR(NOT_A_KEY) \
            } \
            break;
     
     
    // /!\: Should change parser->state before calling NEW_LINE
    #define NEW_LINE \
        if (parser->state == START_CMD) { parser->key = KEY_NEW; } \
        parser->line++; \
        parser->col = 1;
     
     
    #define ONE_CASE(one_c, next_state) \
        case one_c: \
            parser->state = next_state; \
            break;
     
     
    // /!\: Should change parser->state after calling this macro
    #define RECOPY_STRING \
        if ((parser->state == VALUE_STRING) && ((col - col_start) > 0)) { \
            switch(parser->key) { \
            case KEY_IP: \
                EXTEND_ATTRIBUTE(parser->data.ip_alias, parser->data.len_ip_alias) \
                break; \
            case KEY_PASS: \
                EXTEND_ATTRIBUTE(parser->data.pass, parser->data.len_pass) \
                break; \
            case KEY_USER: \
                EXTEND_ATTRIBUTE(parser->data.user, parser->data.len_user) \
                break; \
            case KEY_DATABASE: \
                EXTEND_ATTRIBUTE(parser->data.database, parser->data.len_database) \
                break; \
            } \
        }
     
     
    #define WAIT(new_line_state, wait_LF, parser_error) \
        case ' ': \
            break; \
        case '\r': \
            parser->state = wait_LF; \
            break; \
        case '\n': \
            parser->state = new_line_state; \
            NEW_LINE \
            break; \
        DEFAULT_ERROR(parser_error)
     
     
    #define WAIT_ONE_CHAR(current_state, waiting_c, next_state, parser_error) \
        case current_state: \
            switch(c) { \
            case waiting_c: \
                parser->state = next_state; \
                break; \
            DEFAULT_ERROR(parser_error) \
            } \
            break;
     
     
    #define WAIT_NEW_LINE(current_state, new_line_state, parser_error) \
        case current_state: \
            switch(c) { \
            case '\n': \
                parser->state = new_line_state; \
                NEW_LINE \
                break; \
            DEFAULT_ERROR(parser_error) \
            } \
            break;
     
     
    #endif // PARSER_UTILS_H

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Extraire les infos d'un tag ID3
    Par patkiller dans le forum Langages de programmation
    Réponses: 12
    Dernier message: 22/02/2025, 01h24
  2. lire un fichier , extraire des paire de mots
    Par étoile de mer dans le forum Débuter
    Réponses: 14
    Dernier message: 30/09/2008, 16h22
  3. Lire un fichier depuis les ressources
    Par Silverstone dans le forum C++
    Réponses: 1
    Dernier message: 02/11/2007, 19h57
  4. [VBA-E]Extraire les infos des cellules
    Par boosty dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 11/04/2006, 10h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo