Последние изменения - Поиск:
RSS блога RSS блога

Начало

Блог

Программки

    Google+

Плагины

Программирование

Фото

Контакты

Я в твиттере Я в ЖЖ

TextParser

Скачать исходники

Это класс для разбора текстового файла вида:

Name1
Name2 = "TextValue"
Name3=123.2

Также строка игнорируется, если она начинается со знака ";".

Класс сам определяет тип значения (справа от знака равно), причем можно добавлять свои типы. Вот его заголовочный файл (только существенные моменты):

#pragma once
 #include <STRING>
 #include <FSTREAM>
 #include <ios>
 using std::string;
 using std::fstream;
 using std::ios;


 /*-------------------------------------
 Считаем, что файл может выглядить так:
 ; Комментарий
 Name1 = "11111"
   ; Комментарий
   Name2=123.44
 Name3= 111
 Name4
    Name5 ="1111"
 ---------------------------------------*/


 #define ERR_OPENFILE             1
 #define ERR_TYPE                 2
 #define ERR_NOTCREATE            3
 #define ERR_ENDOFFILE            4

 // Тип значения строки
 enum StringType
 {
    SD_BASE      = -2,
    ST_ERROR   = -1,        // Невозможно определить тип значения
    ST_NAMEONLY = 0,        // нет значения, есть только название
    ST_STRING   = 1,        // Значение - строка
    ST_INT      = 2,        // Значение - целое число
    ST_FLOAT   = 3          // Значение - дробное число
 };

 enum OpenType             // Тип открытого парсера
 {
    OT_NONE = 0,
    OT_READ,
    OT_WRITE
 };

 // Структура для заполнения значением строки
 class StringData
 {
 public:
    string Name;            // Название значения
    StringType Type;        // Тип значения

    // Заполняется одно из этих полей в зависимости от Type
    string strVal;
    int intVal;
    double fVal;
    virtual StringType GetType() { return SD_BASE; };      // Чтобы можно было различать типы
    ...
 };

 class CTextParser
 {
 '''public:
 protected:'
''
    ...

    '''// Чтобы можно было потом добавить еще новые типы
    // Функция возвращает true, если тип узнала'
''
    virtual bool CustomType(string str, StringData *info) { return false; };

    unsigned int m_CurLine;        // Текущая строка
    ...

 public:
    CTextParser();
    virtual ~CTextParser();

    OpenType Create(const char *fname, bool Write, bool Overwrite = false);   // С этого надо начинать
    void Destroy();                                       // А этим кончать (но не обязательно)
    bool GetNextValue(StringData *info);                  // Получить следующую строку (пустые строки пропускает)

    // Функции для записи в файл
    bool Write (string name, string val);
    bool Write (string name, int val);
    bool Write (string name, float val);
    bool Write (string name, double val);
    bool Write (StringData *info);
    bool WriteComment(string str);

    ...
}

Парсер может как читать файл, так и писать в него. Чтобы воспользоваться TextParser, надо создать его экземпляр и вызвать метод Create(). Первый параметр - это имя файла, с которым хотим работать, дальше идет переменная типа bool, которая равна true, если мы хотим писать в файл, и false, если надо обработать файл, то есть пропарсить. А последний параметр указывает надо ли перезаписывать файл при открытии на запись, если файл с таким именем уже существует. Метод возвращает тип OpenType, которые обозначает, как открыли файл, на чтение, на запить, или открыть файл не удалось (тогда возвращается значение OT_NONE.

Вся суть класса заключена в методе GetNextValue. Он возвращает true, если разбор очередной строки прошел удачно, и false в противном случае (возможно файл закончился). Также этот метод заполняет класс типа StringData, который используется как структура. Он объявлен следующим образом:

// Структура для заполнения значением строки
 class StringData
 {
 public:
    string Name;               // Название значения
    StringType Type;           // Тип значения

    // Заполняется одно из этих полей в зависимости от Type
    string strVal;
    int intVal;
    double fVal;
    virtual StringType GetType() { return SD_BASE; };      // Чтобы можно было различать типы
    ...
 };

Этот класс содержит только открымые метода и члены. Член Name содержит имя параметра (то, что стоит слева от знака равно). Член Type определяет тип значения. В исходном варианте (просто класс можно расширять) может принимать следующие значения:

enum StringType
 {
    SD_BASE     = -2,                                  
    ST_ERROR    = -1,      // Невозможно определить тип значения
    ST_NAMEONLY = 0,       // нет значения, есть только название
    ST_STRING   = 1,       // Значение - строка
    ST_INT      = 2,       // Значение - целое число
    ST_FLOAT    = 3        // Значение - дробное число
 };

Ну а с функциями Write там и так все понятно, для их использования надо открыть файл, естественно, на запись.

После использоваться надо вызвать метод Destroy(), но это не обязательно (если только вы не захотите работать с другим файлом), он вызывается в деструкторе.

Класс можно расширять, т.е. добавлять типы, которые изначально не могут быть распознаны. Для этого есть виртуальная функция bool CustomType(string str, StringData *info), которая вызывается каждый раз, когда класс не может распознать тип. Она должна возвратить true, если ей удалось узнать тип, и false в противном случае. Т.о. для того, чтобы добавить новый тип, надо:

  1. В производном классе переопределить функцию CustomType
  2. Сделать потомка от StringData, в который добавить новое поле и флаг, соответствующие новому типу

Вот пример того, как я это сделал для распознавания цветов, которые записаны в виде ARGB (например, 255, 0, 157, 46):

#include "..\PARSER\TextParser.h"

 #define SD_GUITEXTDATA   2

// Означает, что распознанное значение - цвет
 #define ST_COLOR      4              

 // Класс для заполнения парсером - добавился цвет
 class CGuiTextData : public StringData
 {
 public:
    D3DCOLOR Color;
    virtual int GetType()  { return SD_GUITEXTDATA; };
 };

 class CGuiTextParser : public CTextParser  
 {
 public:
    CGuiTextParser();
    virtual ~CGuiTextParser();
    virtual bool CustomType(string str, StringData *info);      // Будет пытаться распознать цвет
 };



Подписаться на комментарии
Автор:
Тема:
 Ваш комментарий
 
 
Введите код 130
 
Править - История - Печать - Последние изменения - Поиск
Последняя редакция от 13.12.2008 10:16