Формат конфигов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.06.05 16:10
Оценка:
Здравствуйте, eao197, Вы писали:

E>Мало уступает, да?


На то есть разные мнения. Есть, напрмер, мнение что малость превосходит. А есть, что сильно...

E>А как тогда на C# сделать такое: А generic-и так могут?
Автор: eao197
Дата: 30.05.05


АВК тебе уже сказал в чем проблема твоего вопроса. Могу повторить еще раз. Изучать тонкости твоих проблем и вникать в горы кода никто не хочет.

Скорее всего твои проблемы связанны с тем, что ты хочешь решать задачи на C# так же как если бы ты решал их на С++. Но это другой язык. Программирование на нем — это классическое ООП + компонентное проеграммирование. Если не задаваться целью решать задачи так же как на С++, то обычно, задачи решаются значительно поще и быстрее.

Если ты действительно хочешь что-то сравнить, то порпробуй ответить на вопрос как на С++ сделать вот это: http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
или как сделать сериализацию на С++ такой же простой как в дотнете.

МС++, о котором иедт речь в данном эссе, это конечно не С++. Это анаптация С++ к дотнету. Разница между ним и Шарпом уже не критична, так как все они позволяют использовать мошь дотнета. Так что о нем разговор особый.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>

29.06.05 12:16: Ветка выделена из темы Has C# lost its point?
Автор: Kisloid
Дата: 19.06.05
— AndrewVK
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 19.06.05 18:43
Оценка:
Здравствуйте, VladD2, Вы писали:

E>>А как тогда на C# сделать такое: А generic-и так могут?
Автор: eao197
Дата: 30.05.05


VD>АВК тебе уже сказал в чем проблема твоего вопроса. Могу повторить еще раз. Изучать тонкости твоих проблем и вникать в горы кода никто не хочет.


А так всегда -- на словах все мудрецы и монстры. А как до реальных решений доходит, то "твои проблемы", "горы кода".
Я помниться когда-то спросил, почему Янус на C++ не был написан. Так я стал сразу одним из тех самых умных, которые никогда ничего не делают. А здесь реальная проблема, которая на C++ решилась без труда и могла бы быть решена еще проще. Но стоило всего лишь поинтересоваться, как ее решить средствами generic-ов, как C#-евангелисты отмазки начали приводить. Здорово (еще бы, это не C# c Python-ом в разработке игр применять). Только проблема в том, что я и так привел минимальный реальный код. В дейсвительности там еще больше навороты на более высоких уровнях есть. И на C++ это все работает и является сопровождаемым.

VD>Скорее всего твои проблемы связанны с тем, что ты хочешь решать задачи на C# так же как если бы ты решал их на С++.


Я не хочу решать задачи на C#. Мне просто интересно, как это могло бы быть.

VD>Если ты действительно хочешь что-то сравнить, то порпробуй ответить на вопрос как на С++ сделать вот это: http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
или как сделать сериализацию на С++ такой же простой как в дотнете.


Ok. Статью посмотрю. Подумаю.
Сериализаций для C++ как собак нерезанных. Сам персонально одной такой занимаюсь -- успешно применяется в production code уже около 2-х лет и нет проблем.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 19.06.05 20:12
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Если ты действительно хочешь что-то сравнить, то порпробуй ответить на вопрос как на С++ сделать вот это: http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
или как сделать сериализацию на С++ такой же простой как в дотнете.


Посмотрел, увидел теже самые тоны кода. Подумал, не понял что должен был ответить.
Ну сделали вы для C# удобное решение с использованием встроенной в платформу поддержки XML сериализации и атрибутами (или как они в .Net-е называются). И что, это должно было продемонстрировать преимущества C# над C++? Ok. Если ты в этом уверен, то пусть в данной конкреной области будет так.

Алаверды привожу код на C++ для парсинга конфигов следующего вида:
{str_data_class    "smsg_2::smpp::a_smpp_transmitter_t::connection_state_monitor"
    {priority 5}
    {font_size 10}
    {if    {== "st_not_connected"}
        {pixmap    "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
        {bkcolor    "magenta"}
    }
    {if {== "st_connected"}
        {bkcolor    "blue"}
    }
    {if {== "st_bind"}
        {pixmap "etc/gemont_1/img/xpm/conn_exists_24x16.xpm" }
        {bkcolor    "green"}
    }
    {if {== "st_shutdown"}
        {bkcolor    "yellow"}
    }
}

{str_data_class    "smsg_2::smpp_smsc::a_smsc_t::m_connection_monitor_data"
    {priority 9}
    {font_size 11}
    {if    {== "st_not_bind"}
        {pixmap    "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
        {bkcolor    "magenta"}
        {sound    "etc/gemont_1/snd/wav/siren.wav"}
        {log_event {level "error"}
            {message "Нет соединения с SMSC"}}
    }
    {if {== "st_bind"}
        {pixmap "etc/gemont_1/img/xpm/conn_exists_24x16.xpm" }
        {bkcolor    "green"}
        {sound    "etc/gemont_1/snd/wav/online.wav"}
        {log_event {level "info"}
            {message "Есть соединение с SMSC"}}
    }
    {if {== "st_shutdown"}
        {bkcolor    "yellow"}
        {sound    "etc/gemont_1/snd/wav/tada.wav"}
    }
}

{str_data_class    "smsg_2::gsm_modem::a_gsm_device_t"
    {priority 9}
    {font_size 11}

    {if    {== "st_not_connected"}
        {pixmap    "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
        {bkcolor    "magenta"}
        {sound    "etc/gemont_1/snd/wav/alarm.wav" }
        {log_event {level "error"}
            {message "Нет соединения с модемом"}}
    }
    {if {== "st_connected"}
        {pixmap "etc/gemont_1/img/xpm/conn_exists_24x16.xpm" }
        {bkcolor    "green"}
        {sound    "etc/gemont_1/snd/wav/online.wav" }
        {log_event {level "info"}
            {message "Есть соединение с модемом"}}
    }
    {if {== "st_not_registered"}
        {pixmap "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
        {bkcolor    "magenta"}
        {sound    "etc/gemont_1/snd/wav/alarm.wav" }
        {log_event {level "info"}
            {message "Модем не зарегистрирован в сети GSM"}}
    }
    {if {== "st_not_authenticated"}
        {pixmap "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
        {bkcolor    "magenta"}
        {sound    "etc/gemont_1/snd/wav/alarm.wav" }
        {log_event {level "info"}
            {message "В файле конфигурации указан неверный PIN, или осталось мало попыток ввода PIN."}}
    }
    {if {== "st_shutdown"}
        {bkcolor    "yellow"}
        {sound    "etc/gemont_1/snd/wav/tada.wav"}
    }
}

{uint_data_class    "smsg_2::smpp_smsc::a_deliver_response_t::m_infos_size_monitor"
    {priority 2}
    {font_size 8}

    {if {> 20}    {bkcolor "yellow"}}
    {if {> 5}    {bkcolor "green"}}
    {if {> 0}    {bkcolor "cyan"}}
}


Реализуется эта кухня следующим образом. Вот описания структур для хранения информации:
//! Коды операций над значениями источников данных.
enum    op_codes_t {
    //! ==
    op_equal,
    //! !=
    op_not_equal,
    //! <
    op_less,
    //! <=
    op_less_equal,
    //! >
    op_greater,
    //! >=
    op_greater_equal,
    //! Неизвестный код операции.
    op_invalid
};

//! Получить код операции по строковому начертанию.
inline op_codes_t
op_code( const std::string & o )
{
    if( "==" == o ) return op_equal;
    if( "!=" == o ) return op_not_equal;
    if( "<" == o ) return op_less;
    if( "<=" == o ) return op_less_equal;
    if( ">" == o ) return op_greater;
    if( ">=" == o ) return op_greater_equal;
    return op_invalid;
}

//
// if_t
//

//! Описание условия и действий, которые нужно выполнить, если
//! это условие выполняется.
template< class T >
struct    if_t
{
    //! Код операции над значением.
    op_codes_t    m_op;
    //! Правый операнд операции сравнения со значением источника данных.
    T    m_right;
    //! Действия, которые нужно выполнить, если условие выполняется.
    actions_t    m_actions;

    //! Конструктор по умолчанию.
    if_t()
    :    m_op( op_invalid )
    {}
    //! Инициализирующий конструктор.
    if_t(
        op_codes_t op,
        const T & right,
        const actions_t & actions )
    :    m_op( op )
    ,    m_right( right )
    ,    m_actions( actions )
    {}

    //! Проверить условие.
    /*! \return true, если условие выполняется. */
    bool
    operator()(
        //! Значение источника данных.
        const T & left ) const
    {
        if( op_equal == m_op ) return ( left == m_right );
        if( op_not_equal == m_op ) return ( left != m_right );
        if( op_less == m_op ) return ( left < m_right );
        if( op_less_equal == m_op ) return ( left <= m_right );
        if( op_greater == m_op ) return ( left > m_right );
        if( op_greater_equal == m_op ) return ( left >= m_right );
        return false;
    }
};

//! Коды состояния источников данных
enum    data_source_status_t {
    //! Источник был зарегистрирован
    e_data_source_reg,
    //! Источник работает в обычном режиме
    e_data_source_work,
    //! Источник был дерегистрирован
    e_data_source_dereg
};

//
// data_class_t
//

//! Описание класса источника данных.
template< class T >
struct    data_class_t
{
    //! Приоритет источников данных этого класса.
    /*! Предположительно, значения в диапазоне 0..9. */
    unsigned char    m_priority;
    //! Величина шрифта в пунктах.
    int    m_font_size;

    //! Список условий, которые нужно проверять.
    std::vector< if_t< T > >    m_conditions;
    //! Действия, которые нужно выполнить, если ни одно
    //! из условий не выполнено.
    actions_t    m_otherwise;

    //! Действия, которые нужно выполнять при регистрации источника данных
    actions_t    m_on_register;
    //! Действия, которые нужно выполнять при дерегистрации источника данных
    actions_t    m_on_deregister;
    //! Конструктор по-умолчанию.
    data_class_t()
    :    m_priority( 0 )
    ,    m_font_size( 0 )
    {}

    //! Определить, какие действия нужно сделать над
    //! данным значением источника данных.
    /*!
        В \a a помещается описание действий, которые
        должны быть выполнены над значением. Если было выполнено
        какое-то условие из m_conditions, то возвращаются действия,
        назначенные для данного условия. В противном случае
        возвращается значение m_otherwise.

        \return Номер условия в m_conditions, которое
            было выполнено (значение >= 0). -1, если
            ни одно из условий в m_conditions не было
            выполнено.
    */
    int
    operator()(
        //! Значение источника данных.
        const T & left,
        //! Приемник описания действий.
        actions_t & a,
        //! Текущее состояние источника данных
        data_source_status_t status = e_data_source_work ) const
    {
        switch( status )
        {
            case e_data_source_work:
                for( int i = 0, i_max = (int)m_conditions.size();
                    i != i_max; ++i )
                {
                    if( m_conditions[ i ]( left ) )
                    {
                        a = m_conditions[ i ].m_actions;
                        return i;
                    }
                }

                a = m_otherwise;
                return -1;

            case e_data_source_reg:
                a = m_on_register;
                return -2;

            case e_data_source_dereg:
                a = m_on_deregister;
                return -3;
            default:
                a = m_otherwise;
                return -1;
        }
    }
};


А вот сам парсинг конфигурационного файла:
//
// tag_op_t
//

/*!
    Класс тега для разбора типа сравнения и величины для
    сравнения.
*/
template< class T >
class    tag_op_t
    :    public cls_2::tag_scalar_t< T >
{
    //! Псевдоним для базового типа.
    typedef cls_2::tag_scalar_t< T >    base_type_t;
    public :
        //! Основной конструктор.
        tag_op_t( cls_2::tag_t & owner )
        :    base_type_t( owner, "op", true )
        {}
        virtual ~tag_op_t()
        {}

        //! Определить, какой тип операции используется.
        virtual bool
        compare_name( const char * name ) const
        {
            op_codes_t op = op_code( name );
            if( op_invalid != op )
            {
                m_op = op;
                return true;
            }
            return false;
        }

        //! Получить значения.
        void
        get( if_t< T > & to ) const
        {
            to.m_op = m_op;
            to.m_right = query_value();
        }

    private :
        //! Тип операции.
        mutable op_codes_t    m_op;
};

//! Заполнить ограничитель значений цветов.
void
fill_color_constraint(
    cls_2::scalar_constraint::one_of_t< std::string > & c )
{
    c.add( "white" );
    c.add( "black" );
    c.add( "red" );
    c.add( "dark_red" );
    c.add( "green" );
    c.add( "dark_green" );
    c.add( "blue" );
    c.add( "dark_blue" );
    c.add( "cyan" );
    c.add( "dark_cyan" );
    c.add( "magenta" );
    c.add( "dark_magenta" );
    c.add( "yellow" );
    c.add( "dakr_yellow" );
    c.add( "gray" );
    c.add( "dark_gray" );
    c.add( "light_gray" );
}

//
// tag_if_t
//

/*!
    Класс для разбора условий.
*/
template< class T >
class    tag_if_t
    :    public cls_2::tag_no_value_t
    {
    //! Псевдоним для базового типа.
    typedef cls_2::tag_no_value_t    base_type_t;
    private :
        //! Условие сравнения.
        tag_op_t< T >    m_op;
        //! Имя графического образа.
        cls_2::tag_scalar_t< std::string >    m_pixmap;
        //! Фоновый цвет.
        cls_2::tag_scalar_t< std::string >    m_bkcolor;
        //! Ограничения на значения цветов.
        cls_2::scalar_constraint::one_of_t< std::string >
            m_bkcolor_constraint;
        //! Звуковой файл для воспроизведения.
        cls_2::tag_scalar_t< std::string >    m_sound;
        //! Событие для log_writter.
        tag_log_event_t    m_log_event;

        //! Список внешних приложений для запуска.
        cls_2::tag_vector_of_tags_t< tag_launch_external_t >
            m_launch_external;

        //! Предикат для std::transform.
        static launch_external_t
        launch_external_getter(
            const tag_launch_external_t & tag )
            {
                return tag.get();
            }

    public :
        tag_if_t(
            const char * name,
            bool is_mandatory )
            :    base_type_t( name, is_mandatory, true )
            ,    m_op( self_tag() )
            ,    m_pixmap( self_tag(), "pixmap", false )
            ,    m_bkcolor( self_tag(), "bkcolor", false )
            ,    m_sound( self_tag(), "sound", false )
            ,    m_log_event( self_tag(), "log_event", false )
            ,    m_launch_external( self_tag(), "launch_external", false )
            {
                fill_color_constraint( m_bkcolor_constraint );
                m_bkcolor.set_constraint( &m_bkcolor_constraint );
            }
        virtual ~tag_if_t()
            {}

        //! Получить значения.
        if_t< T >
        get() const
            {
                if_t< T > to;

                m_op.get( to );
                m_pixmap.query_opt_value( to.m_actions.m_pixmap );
                m_bkcolor.query_opt_value( to.m_actions.m_bkcolor );
                m_sound.query_opt_value( to.m_actions.m_sound );
                if( m_log_event.is_defined() )
                    to.m_actions.m_log_event = m_log_event.get();
                if( m_launch_external.is_defined() )
                    std::transform( m_launch_external.begin(),
                        m_launch_external.end(),
                        std::back_inserter(
                            to.m_actions.m_launch_external ),
                        launch_external_getter );

                return to;
            }
    };

//
// tag_otherwise_t
//

/*!
    Класс для разбора действий по умолчанию.
*/
class    tag_otherwise_t
    :    public cls_2::tag_no_value_t
{
    //! Псевдоним для базового типа.
    typedef cls_2::tag_no_value_t    base_type_t;
    private :
        //! Имя графического образа.
        cls_2::tag_scalar_t< std::string >    m_pixmap;
        //! Фоновый цвет.
        cls_2::tag_scalar_t< std::string >    m_bkcolor;
        //! Ограничения на значения цветов.
        cls_2::scalar_constraint::one_of_t< std::string >
            m_bkcolor_constraint;
        //! Звуковой файл.
        cls_2::tag_scalar_t< std::string >    m_sound;
        //! Событие для log_writter.
        tag_log_event_t    m_log_event;
        //! Список внешних приложений для запуска.
        cls_2::tag_vector_of_tags_t< tag_launch_external_t >
            m_launch_external;

        //! Предикат для std::transform.
        static launch_external_t
        launch_external_getter(
            const tag_launch_external_t & tag )
            {
                return tag.get();
            }

    public :
        tag_otherwise_t( cls_2::tag_t & owner )
            :
                base_type_t( owner, "otherwise", false, true )
            ,    m_pixmap( self_tag(), "pixmap", false )
            ,    m_bkcolor( self_tag(), "bkcolor", false )
            ,    m_sound( self_tag(), "sound", false )
            ,    m_log_event( self_tag(), "log_event", false )
            ,    m_launch_external( self_tag(), "launch_external", false )
            {
                fill_color_constraint( m_bkcolor_constraint );
                m_bkcolor.set_constraint( &m_bkcolor_constraint );
            }
        virtual ~tag_otherwise_t()
            {}

        //! Получить значения.
        void
        get( actions_t & to ) const
            {
                m_pixmap.query_opt_value( to.m_pixmap );
                m_bkcolor.query_opt_value( to.m_bkcolor );
                m_sound.query_opt_value( to.m_sound );
                if( m_log_event.is_defined() )
                    to.m_log_event = m_log_event.get();
                if( m_launch_external.is_defined() )
                    std::transform( m_launch_external.begin(),
                        m_launch_external.end(),
                        std::back_inserter(
                            to.m_launch_external ),
                        launch_external_getter );
            }
};

//
// tag_on_register_t
//

/*!
    Класс для
*/
class    tag_on_register_t
    :    public cls_2::tag_no_value_t
{
    //! Псевдоним для базового типа.
    typedef cls_2::tag_no_value_t    base_type_t;
    private :
        //! Звуковой файл.
        cls_2::tag_scalar_t< std::string >    m_sound;
        //! Событие для log_writter.
        tag_log_event_t    m_log_event;
        //! Список внешних приложений для запуска.
        cls_2::tag_vector_of_tags_t< tag_launch_external_t >
            m_launch_external;

        //! Предикат для std::transform.
        static launch_external_t
        launch_external_getter(
            const tag_launch_external_t & tag )
            {
                return tag.get();
            }

    public :
        tag_on_register_t( cls_2::tag_t & owner )
            :
                base_type_t( owner, "on_register", false, true )
            ,    m_sound( self_tag(), "sound", false )
            ,    m_log_event( self_tag(), "log_event", false )
            ,    m_launch_external( self_tag(), "launch_external", false )
            {}

        virtual ~tag_on_register_t()
            {}

        //! Получить значения.
        void
        get( actions_t & to ) const
            {
                m_sound.query_opt_value( to.m_sound );
                if( m_log_event.is_defined() )
                    to.m_log_event = m_log_event.get();
                if( m_launch_external.is_defined() )
                    std::transform( m_launch_external.begin(),
                        m_launch_external.end(),
                        std::back_inserter(
                            to.m_launch_external ),
                        launch_external_getter );
            }
};

//
// tag_on_deregister_t
//

/*!
    Класс для
*/
class    tag_on_deregister_t
    :    public cls_2::tag_no_value_t
{
    //! Псевдоним для базового типа.
    typedef cls_2::tag_no_value_t    base_type_t;
    private :
        //! Звуковой файл.
        cls_2::tag_scalar_t< std::string >    m_sound;
        //! Событие для log_writter.
        tag_log_event_t    m_log_event;
        //! Список внешних приложений для запуска.
        cls_2::tag_vector_of_tags_t< tag_launch_external_t >
            m_launch_external;

        //! Предикат для std::transform.
        static launch_external_t
        launch_external_getter(
            const tag_launch_external_t & tag )
            {
                return tag.get();
            }

    public :
        tag_on_deregister_t( cls_2::tag_t & owner )
            :
                base_type_t( owner, "on_deregister", false, true )
            ,    m_sound( self_tag(), "sound", false )
            ,    m_log_event( self_tag(), "log_event", false )
            ,    m_launch_external( self_tag(), "launch_external", false )
            {}

        virtual ~tag_on_deregister_t()
            {}

        //! Получить значения.
        void
        get( actions_t & to ) const
            {
                m_sound.query_opt_value( to.m_sound );
                if( m_log_event.is_defined() )
                    to.m_log_event = m_log_event.get();
                if( m_launch_external.is_defined() )
                    std::transform( m_launch_external.begin(),
                        m_launch_external.end(),
                        std::back_inserter(
                            to.m_launch_external ),
                        launch_external_getter );
            }
};

//
// tag_data_class_t
//

/*!
    Класс для разбора описания типа источника данных.
*/
template< class T >
class    tag_data_class_t
    :    public cls_2::tag_scalar_t< std::string >
{
    //! Псевдоним для базового типа.
    typedef cls_2::tag_scalar_t< std::string >    base_type_t;
    private :
        //! Приоритет.
        cls_2::tag_scalar_t< unsigned int >    m_priority;

        //! Ограничения на приоритет.
        cls_2::scalar_constraint::min_max_t<
                unsigned int >
            m_priority_range;

        //! Величина шрифта в пунктах.
        cls_2::tag_scalar_t< int >    m_font_size;

        //! Тип списка тегов-условий.
        typedef cls_2::tag_vector_of_tags_t< tag_if_t< T > >
            tag_conditions_t;

        //! Список условий.
        tag_conditions_t    m_conditions;

        //! Действия по умолчанию.
        tag_otherwise_t    m_otherwise;

        //! Действие, выполняемое при регистрации источника данных
        tag_on_register_t m_on_register;

        //! Действие, выполняемое при дерегистрации источника данных
        tag_on_deregister_t m_on_deregister;


    public :
        //! Основной конструктор.
        tag_data_class_t(
            const char * name,
            bool is_mandatory )
        :
            base_type_t( name, is_mandatory )
        ,    m_priority( self_tag(), "priority", true )
        ,    m_priority_range( 0, 9 )
        ,    m_font_size( self_tag(), "font_size", false )
        ,    m_conditions( self_tag(), "if", false )
        ,    m_otherwise( self_tag() )
        ,    m_on_register( self_tag() )
        ,    m_on_deregister( self_tag() )
        {
            m_priority.set_constraint( &m_priority_range );
        }

        virtual ~tag_data_class_t()
        {}

        //! Получить значения.
        data_class_t< T >
        get() const
        {
            data_class_t< T > to;

            to.m_priority = m_priority.query_value();
            if( m_otherwise.is_defined() )
                m_otherwise.get( to.m_otherwise );
            if( m_on_register.is_defined() )
                m_on_register.get( to.m_on_register );
            if( m_on_deregister.is_defined() )
                m_on_deregister.get( to.m_on_deregister );

            m_font_size.query_opt_value( to.m_font_size );

            for( unsigned int i = 0, i_max = m_conditions.size();
                i != i_max; ++i )
            {
                to.m_conditions.push_back(
                    m_conditions.at( i ).get() );
            }

            return to;
        }
};


Собственно код был написан наспех и с тех пор рефакторингу из-за отсутствия времени не подвергался, поэтому классы tag_on_register_t и tag_on_deregister_t остались реализованными через copy&paste (изначально планировалось, что у них будет разных набор дочерних тегов).

А вот так читаются конфигурационные файлы:
bool
tag_import_data_classes_t::load_data_classes(
    const std::string & file_name,
    uint_data_class_map_t & uint_data_classes,
    str_data_class_map_t & str_data_classes,
    std::string & error_desc )
{
    cls_2::tag_vector_of_tags_t< tag_data_class_t< unsigned int > >
        tag_uint_data_class( "uint_data_class", false );
    cls_2::tag_vector_of_tags_t< tag_data_class_t< std::string > >
        tag_str_data_class( "str_data_class", false );

    cls_2::tag_t * tags[] =
    {
        &tag_uint_data_class,
        &tag_str_data_class
    };

    std::ostringstream error_stream;

    int ret_code = cls_2::std_cpp::parse_file( file_name,
        tags, sizeof( tags ) / sizeof( tags[ 0 ] ), &error_stream );
    if( cls_2::c_ok == ret_code )
    {
        // Разбор прошел успешно. Теперь нужно извлечь значения из тегов.
        std::for_each(
            tag_uint_data_class.begin(),
            tag_uint_data_class.end(),
            data_class_extractor< unsigned int >( uint_data_classes ) );
        std::for_each(
            tag_str_data_class.begin(),
            tag_str_data_class.end(),
            data_class_extractor< std::string >( str_data_classes ) );

        return true;
    }
    else
        error_desc = error_stream.str();

    return false;
}


Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Формат конфигов
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.06.05 09:00
Оценка:
Здравствуйте, eao197, Вы писали:

E>А так всегда -- на словах все мудрецы и монстры. А как до реальных решений доходит, то "твои проблемы", "горы кода".


Умение четко и кратко сформулировать вопрос — это действительно твои проблемы. Многие вопросы остающиеся без ответа отсаются без оного только из-за того, что они слишком запвтаны и противоричивы.

E>Я помниться когда-то спросил, почему Янус на C++ не был написан. Так я стал сразу одним из тех самых умных, которые никогда ничего не делают.


Ты стал одним из тех которые никогда не сделают свою версию Януса. А про то что ты ничего не делаешь никто не говорил.

E> А здесь реальная проблема, которая на C++ решилась без труда и могла бы быть решена еще проще.


Опиши эту проблему. Только проблему, а не решение. И по возможности кратко и понятно.

E> Но стоило всего лишь поинтересоваться, как ее решить средствами generic-ов, как C#-евангелисты отмазки начали приводить.


Тебе замечательно ответил С++-ник. Попробуй воспринять его слова.

E> Здорово (еще бы, это не C# c Python-ом в разработке игр применять). Только проблема в том, что я и так привел минимальный реальный код. В дейсвительности там еще больше навороты на более высоких уровнях есть. И на C++ это все работает и является сопровождаемым.


Я так понимаю, ты не первый год программируешь. Раз так то должен понимать, что ценить нужно не навороты, а стройность и простоту кода. А навороты и дерзкие хаки пусть наворачивают молодые кул-хацкеры.

Лично я когда пишу код на Шарпе не испытываю потребности в замазывании дяр в виде трехэтажных конструкциях. Рефакторю часто. Паттерны разные применяю часто. А вот хаки как-то не нужны.

VD>>Скорее всего твои проблемы связанны с тем, что ты хочешь решать задачи на C# так же как если бы ты решал их на С++.


E>Я не хочу решать задачи на C#. Мне просто интересно, как это могло бы быть.


Проблема в том, что а) я лично не понял что тебе нужно, б) твои проблемы скорее всего являются следствием тараканов заведшихся от С++-мышления. Я открою тебе небольшой сикрет. Я программировал на С++ значительно дольше чем на Шарпе и в первое время, после перехода на Шарпм, тоже пытался писать как на С++. Потом понял неразумность этого и переучился на новый стиль.

E>Ok. Статью посмотрю. Подумаю.

E>Сериализаций для C++ как собак нерезанных.

Ага. И все как одна неудобны В дотнете для того чтобы объект сериализовался достаточно добавить один атрибут. Разные хитрые случаи тоже разруливаются на атрибутах. В общем, другой мир.

E> Сам персонально одной такой занимаюсь -- успешно применяется в production code уже около 2-х лет и нет проблем.


Дошол до первого примера и дальше смотреть не стал. Как всегда куча сложностей на ровном месте. Почитай про BinaryFormatter и про XmlSerializer (в приведенной выше статье). Думаю разницу ты ощутишь сразу.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Формат конфигов
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 20.06.05 09:10
Оценка: 1 (1) +5 :))) :))) :)))
Здравствуйте, eao197, Вы писали:
E>Алаверды привожу код на C++ для парсинга конфигов следующего вида:
E>
E>{str_data_class    "smsg_2::smpp::a_smpp_transmitter_t::connection_state_monitor"
E>    {priority 5}
E>    {font_size 10}
E>    {if    {== "st_not_connected"}
E>        {pixmap    "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
E>        {bkcolor    "magenta"}
E>    }
E> /.../
E>


E>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


Это в подтверждение закона Гринспуна о том, что в каждой программе на С++ есть, пусть слабенький, но интерпритатор лиспа?
http://www.smalltalk.ru | RSDN@Home 1.1.4 beta 7 rev. 447
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[6]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 09:36
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Здравствуйте, eao197, Вы писали:

E>>Алаверды привожу код на C++ для парсинга конфигов следующего вида:
E>>
E>>{str_data_class    "smsg_2::smpp::a_smpp_transmitter_t::connection_state_monitor"
E>>    {priority 5}
E>>    {font_size 10}
E>>    {if    {== "st_not_connected"}
E>>        {pixmap    "etc/gemont_1/img/xpm/red_cross_24x16.xpm" }
E>>        {bkcolor    "magenta"}
E>>    }
E>> /.../
E>>


E>>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


ANS>Это в подтверждение закона Гринспуна о том, что в каждой программе на С++ есть, пусть слабенький, но интерпритатор лиспа?


Нет, на самом деле синтаксис был навеян языком Curl, а уж откуда ноги растут у Curl-а мне было не важно
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 09:56
Оценка: 7 (1)
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, eao197, Вы писали:


E>>А так всегда -- на словах все мудрецы и монстры. А как до реальных решений доходит, то "твои проблемы", "горы кода".


VD>Умение четко и кратко сформулировать вопрос — это действительно твои проблемы. Многие вопросы остающиеся без ответа отсаются без оного только из-за того, что они слишком запвтаны и противоричивы.


Да, такое может быть.

E>> А здесь реальная проблема, которая на C++ решилась без труда и могла бы быть решена еще проще.


VD>Опиши эту проблему. Только проблему, а не решение. И по возможности кратко и понятно.


А зачем? Ответ я от Павла Кузнецова получил. Воспринял и поставил соответствующую оценку.

E>> Здорово (еще бы, это не C# c Python-ом в разработке игр применять). Только проблема в том, что я и так привел минимальный реальный код. В дейсвительности там еще больше навороты на более высоких уровнях есть. И на C++ это все работает и является сопровождаемым.


VD>Я так понимаю, ты не первый год программируешь. Раз так то должен понимать, что ценить нужно не навороты, а стройность и простоту кода. А навороты и дерзкие хаки пусть наворачивают молодые кул-хацкеры.


Стройность и простота -- очень относительные понятия. И во многом зависят от квалификации разработчика. Для продвинутого C++ программиста использование boost::bind гораздо проще и понятнее, чем для начинающего (либо даже для C++ программиста с многолетним опытом, но не работавшем с шаблонами). Поэтому они могут дать совершенно разные оценки одному и тому же коду.

VD>Лично я когда пишу код на Шарпе не испытываю потребности в замазывании дяр в виде трехэтажных конструкциях. Рефакторю часто. Паттерны разные применяю часто. А вот хаки как-то не нужны.


Еще раз повторю -- в том конкретном случае нужно было сделать рефакторинг в базисе, на котором строилось много другого кода и который использовали другие проекты, к которым я даже отношения не имел. Если бы я нарушил совместимость на уровне исходного кода, то во всех этих проектах потребовался бы рефакторинг. И его стоимость бы оказалась гораздо выше полезности той фичи, которую я хотел добавить.

VD>>>Скорее всего твои проблемы связанны с тем, что ты хочешь решать задачи на C# так же как если бы ты решал их на С++.


E>>Я не хочу решать задачи на C#. Мне просто интересно, как это могло бы быть.


VD>Проблема в том, что б) твои проблемы скорее всего являются следствием тараканов заведшихся от С++-мышления. Я открою тебе небольшой сикрет.


Да, это я уже понял. Точно так же, как то, что C++ пытаются оценивать, используя тараканов из C#.

E>> Сам персонально одной такой занимаюсь -- успешно применяется в production code уже около 2-х лет и нет проблем.


VD>Дошол до первого примера и дальше смотреть не стал. Как всегда куча сложностей на ровном месте.


А можно подробнее об этой куче (можно вот в эту ветку: [ANN] ObjESSty &mdash; еще один проект сериализации
Автор: eao197
Дата: 24.01.05
)? Ты, кстати, прочитал, для демонстрации чего был создан этот пример?

VD> Почитай про BinaryFormatter и про XmlSerializer (в приведенной выше статье). Думаю разницу ты ощутишь сразу.


Что-то я там с ходу не увидел, как с помощью BinaryFormatter можно десериализовать объекты, про которые принимающая сторона даже понятия не имеет? Или BinaryFormatter содержит в себе больше возможностей чем ASN1?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Формат конфигов
От: ihatelogins  
Дата: 20.06.05 10:04
Оценка: +3
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, VladD2, Вы писали:


VD>>Если ты действительно хочешь что-то сравнить, то порпробуй ответить на вопрос как на С++ сделать вот это: http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
или как сделать сериализацию на С++ такой же простой как в дотнете.



E>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


Прелесть XML не в том, что требуется меньше закорючек для описания структуры, и не в том, что его проще редактировать вручную, а в том, что он — СТАНДАРТ. С самопальными примочками типа Вашей можете разобраться только Вы. Для неё не сущесвует таких полезных и удобных технологий, как XML Schema (проверка), XSLT (преобразование), XPATH (запросы). Пользователи не смогут воспользоваться внешними высокоуровневыми редакторами этих файлов (а могли бы, если бы была XML схема).

...

Эх, велосипедный спорт пользуется огромной популярностью...
Re[6]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 10:13
Оценка: +1
Здравствуйте, ihatelogins, Вы писали:

I>Здравствуйте, eao197, Вы писали:


E>>Здравствуйте, VladD2, Вы писали:


VD>>>Если ты действительно хочешь что-то сравнить, то порпробуй ответить на вопрос как на С++ сделать вот это: http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
или как сделать сериализацию на С++ такой же простой как в дотнете.



E>>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


I>Прелесть XML не в том, что требуется меньше закорючек для описания структуры, и не в том, что его проще редактировать вручную, а в том, что он — СТАНДАРТ.


Стандарт чего?
Имхо, применение XML для конфигов объемом в 100-200 строк -- это из пушки по воробъям.

I> С самопальными примочками типа Вашей можете разобраться только Вы. Для неё не сущесвует таких полезных и удобных технологий, как XML Schema (проверка), XSLT (преобразование), XPATH (запросы). Пользователи не смогут воспользоваться внешними высокоуровневыми редакторами этих файлов (а могли бы, если бы была XML схема).


Справедливо. Но зачем для конфигурационных файлов XML Schema, XSLT, XPATH и пр. понять не могу.

I>Эх, велосипедный спорт пользуется огромной популярностью...


Да, и я большой его сторонник
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Формат конфигов
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.06.05 10:55
Оценка:
Здравствуйте, eao197, Вы писали:

E>Посмотрел, увидел теже самые тоны кода. Подумал, не понял что должен был ответить.


Видимо не туда смотрел.
Если тебе влом вчитываться в суть статьи могу продемонстрировать упрощенный пример. Вот хэлпер-класс для упрощения сериализации в строку (в хмл-формате):
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

static class MySerializer
{
    public static string Serialize<T>(T obj)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        StringBuilder sb = new StringBuilder();
        XmlWriterSettings settings = new XmlWriterSettings();

        settings.Indent = true;

        using (XmlWriter writer = XmlWriter.Create(sb, settings))
            serializer.Serialize(writer, obj);

        return sb.ToString();
    }

    public static T Deserialize<T>(string data)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));

        using (XmlReader reader = XmlTextReader.Create(new StringReader(data)))
            return (T)serializer.Deserialize(reader);
    }
}

Пишется один раз.

А вот как выглядит пример сериализации содержимого класса с его использованим:
using System;
using System.Xml.Serialization;
using System.Collections.Generic;

public class Test
{
    public int Age; // Просто поле

    // Далее все на свойствах

    private string _firstName;

    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    private string _lastName;

    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    // Сериализуем коллекцию строк. Тоже все почит в автомате.

    List<string> _addresses = new List<string>();

    // Атрибут XmlArrayItem позволяет задать имя для элементов
    // содержащих конкретные адреса. Если его не указать, то они
    // будут иметь имя "<string>".
    [XmlArrayItem("Address")]
    public List<string> Addresses
    {
        get { return _addresses; }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Test test = new Test();

        test.Age = 31;
        test.FirstName = "Чистяков";
        test.LastName = "Влад";
        test.Addresses.Add("Первый адрес");
        test.Addresses.Add("Второй адрес");

        // Сохраняем состояние в ХМЛ.
        string data = MySerializer.Serialize(test);

        Console.WriteLine("Выводим сериализованные данные:");
        Console.WriteLine(data);

        test = null;

        Console.WriteLine();
        Console.WriteLine("Выводим содержимое объекта состояние "
        + "которого только что считано из строки:");

        // Загружаем состояние...
        test = MySerializer.Deserialize<Test>(data);

        Console.WriteLine("FirstName: " + test.FirstName);
        Console.WriteLine("Address 1: " + test.Addresses[0]);
    }
}


Как видишь практически никаких лишних телодвижений. Код получается чистым и красивым.

E>Ну сделали вы для C# удобное решение с использованием встроенной в платформу поддержки XML сериализации и атрибутами (или как они в .Net-е называются). И что, это должно было продемонстрировать преимущества C# над C++? Ok. Если ты в этом уверен, то пусть в данной конкреной области будет так.


Не. Это демонстрция возможностей компонентного подхода. На С++ без внешнего хранилища метаинформации и без отдельного генератора код подобное сделать не удастся. Любые выкрутасы на шаблонах приведут к куче лишних движений при программировании и все равно окажутся мнее гибкими и более медленными нежели это.

Причем не нужно пытаться сомтреть на этот пример как не некую магию предоставляемую фрэймворком. XmlSerializer — это обыкновенный класс написанный на C#. Просто он задействует самые мощьные фичи дотнета вроде рефлекшона, компиляции в рантайме и динамической загрузки сборок.

E>Алаверды привожу код на C++ для парсинга конфигов следующего вида:

...

Хотел было оставить всю эту гору кода чтобы в конце поставить смайли, но уж очень огромный оверквотинг вышел бы. К тому же это все не смешно. Это грустно.

Фиг с бы с тем, что формат конфига стршен сам по себе. Но такие горы кода для столь простых задачь. Зачем?

E>Собственно код был написан наспех и с тех пор рефакторингу из-за отсутствия времени не подвергался, поэтому классы tag_on_register_t и tag_on_deregister_t остались реализованными через copy&paste (изначально планировалось, что у них будет разных набор дочерних тегов).


Прочитать эту гору кода я лично не в состоянии. (время жалко) Так что заметить подобные мелочи просто не смог. Но ты привел замечательный пример того сколько кода нужно надалбливать на С++ чтобы решить примитивные задачи.

Как я понимаю твой код не умеет впихивать информацию в объекты и читать ее из них. Попробуй ради хохмы добавить такую возможность.

E>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


Гы-гы. Это типичный пример заката слонца вручную. Если уж разрабатывался свой формат файла, да еще с зачатками языка программировани, то нужно было просто описать его грамтику в BNF/EBNF нотации и скормить любому генератору парсеров. Уверяю тебя, что даже н С++ объем кода сократился бы до пары страниц. Что до твоего формата, то извини, но это тоже велосипед. Этот формат придется изучать. А что до простоты правки... дык ХМЛ то можно править редакторами поддреживающими схемы. При этом убдет и комплит и подсветка. Твой же формат прдется править как плоский текст. Так что что удобнее еще не известно.

Если же ты попыташься внимательно прочесть статью на которую я давал ссылку, то ты увидишь, что благодоря развитой компонентной модели в дотнете можно относительно малой кровью реализовать и качественное ГУИ для редактирования данных хранящихся непосредственно в объекте. Причем код будет универсальный и ему можно будет подсовывать любой объект размеченный специальными атрибутами. В стаье этого нет, но эта схема, в Янусе, на сегодня ко всему прочему поддерживает многоязычную поддржку.

Все это конечно можно написать на С++, но это будет не один человекогод. И так почти в каждой области. Именно по этому мы (разработчики Януса) смело заявляем, что повторить Янус на С++ на объщественных началах практически невозможно.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Формат конфигов
От: Cyberax Марс  
Дата: 20.06.05 11:32
Оценка:
VladD2 wrote:

> Не.


Да.

> Это демонстрция возможностей компонентного подхода. На С++ без

> внешнего хранилища метаинформации и без отдельного генератора код
> подобное сделать не удастся. Любые выкрутасы на шаблонах приведут к
> куче лишних движений при программировании и все равно окажутся мнее
> гибкими и более медленными нежели это.

http://boost.org/libs/serialization/doc/index.html , в частности
http://boost.org/libs/serialization/doc/tutorial.html#simplecase

Был бы в С++ нормальный compile-time reflection — все стало бы еще
намного проще.

> Все это конечно можно написать на С++, но это будет не один

> человекогод. И так почти в каждой области. Именно по этому мы
> (разработчики Януса) смело заявляем, что повторить Янус на С++ на
> объщественных началах практически невозможно.

Берем Thunderbird и пишем к ней расширение для RSDN. На С++

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 11:51
Оценка: +1
Здравствуйте, VladD2, Вы писали:

<...код поскипан...>
VD>Как видишь практически никаких лишних телодвижений. Код получается чистым и красивым.

Влад, ты сам, вероятно, мало читаешь то, что пишут опоненты, поэтому и других в этих грехах обвиняешь?
Код получается нормальным. Почти как в boost::serialization

Если серьезно, то я признаю, что в C# удобно делать сериализацию в XML. Так ведь для языка, который появился в расцвет XML-я это и не удивительно, не так ли?

E>>Ну сделали вы для C# удобное решение с использованием встроенной в платформу поддержки XML сериализации и атрибутами (или как они в .Net-е называются). И что, это должно было продемонстрировать преимущества C# над C++? Ok. Если ты в этом уверен, то пусть в данной конкреной области будет так.


VD>Не. Это демонстрция возможностей компонентного подхода. На С++ без внешнего хранилища метаинформации и без отдельного генератора код подобное сделать не удастся. Любые выкрутасы на шаблонах приведут к куче лишних движений при программировании и все равно окажутся мнее гибкими и более медленными нежели это.


Ой-ли? Не убедительно. Лично я останусь при своем мнении.

E>>Алаверды привожу код на C++ для парсинга конфигов следующего вида:

VD>...

VD>Хотел было оставить всю эту гору кода чтобы в конце поставить смайли, но уж очень огромный оверквотинг вышел бы. К тому же это все не смешно. Это грустно.


VD>Фиг с бы с тем, что формат конфига стршен сам по себе.


Это дело вкуса. По мне, так гораздо страшнее было бы работать с конфигом вида:
<uint_data_class>
    <name value="smsg_2::smpp::a_smpp_transmitter_t::connection_state_monitor" />
    <priority value="5" />
    <font_size value="10" />
        
    <if>
        <equal_to value="st_not_connected" />
        <pixmap value="etc/gemont_1/img/xpm/red_cross_24x16.xpm" />
        <bkcolor value="magenta" />
    </if>
    
    <if>
        <equal_to value="st_connected" />
        <bkcolor value="blue" />
    </if>
    <if>
        <equal_to value="st_bind" />
        <pixmap value="etc/gemont_1/img/xpm/conn_exists_24x16.xpm" />
        <bkcolor    value="green" />
    </if>
    <if>
        <equal_to value="st_shutdown" />
        <bkcolor    value="yellow" />
    </if>
</uint_data_class>


Неужели это выглядит более читабельными и понятным?

Кроме того, вот пример конфига для DRBD:
# Our web share
resource drbd0 {

  net {
     sync-group=0
  }

  on node1 {
    device=/dev/nb0
    disk=/dev/sda1
  }

  on node2 {
    device=/dev/nb0
    disk=/dev/sda1
  }

}

# Our MySQL share
resource drbd1 {
  net {
    sync-group=1
  }

  on node1 {
    device=/dev/nb1
    disk=/dev/sda2
  }

  on node2 {
    device=/dev/nb1
    disk=/dev/sda2
  }

}


Неужели бы он выиграл бы от XML-формата?

VD>Но такие горы кода для столь простых задачь. Зачем?


Ну я в свое время насмотрелся (на Java и C++), как хранят конфиги в XML а затем извлекают из них значения. Если используется DOM-модель, то после нескольких строчек обращения к парсингу шла масса строк с поиском и извлечением значений из DOM-элементов. А если использовалась SAX-модель, то код все равно получался таким же, как у меня, только нужно было еще корректно из строк в int-ы преобразовывать.

VD>Как я понимаю твой код не умеет впихивать информацию в объекты и читать ее из них. Попробуй ради хохмы добавить такую возможность.


Вот именно -- ради хохмы. А в реальности мне такая фишка пока не потребовалась.

E>>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


VD>Гы-гы. Это типичный пример заката слонца вручную. Если уж разрабатывался свой формат файла, да еще с зачатками языка программировани, то нужно было просто описать его грамтику в BNF/EBNF нотации и скормить любому генератору парсеров.


Там нет зачатков языка программирования. Просто похожие конструкции.
Кроме того, у граматик и парсеров есть большие проблемы с раширяемостью. Вот потребуется в тег {pixmap} еще один подтег добавить, и придется граматику править. И еще не понятно, насколько проще это окажется, особенно если граматика получится сильно контекстно-чувствительная.

VD>Если же ты попыташься внимательно прочесть статью на которую я давал ссылку, то ты увидишь, что благодоря развитой компонентной модели в дотнете можно относительно малой кровью реализовать и качественное ГУИ для редактирования данных хранящихся непосредственно в объекте. Причем код будет универсальный и ему можно будет подсовывать любой объект размеченный специальными атрибутами. В стаье этого нет, но эта схема, в Янусе, на сегодня ко всему прочему поддерживает многоязычную поддржку.


Влад, я прочел статью.
Но оценить всю видимую тобой прелесть я не могу. Вероятно в силу того, что занимаюсь другими вещами.

VD>Именно по этому мы (разработчики Януса) смело заявляем, что повторить Янус на С++ на объщественных началах практически невозможно.


Имхо, тебе пора перестать использовать в качестве доказательства крутости C# тот факт, что на C++ нет аналога Януса. На C# нет аналога GNOME или KDE, почему бы не сказать, что на C# эти проекты нереализуемы?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: Формат конфигов
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.06.05 11:52
Оценка:
Здравствуйте, Cyberax, Вы писали:

>> Не.


C>Да.


Шутку понял. Смешно.

>> Это демонстрция возможностей компонентного подхода. На С++ без

>> внешнего хранилища метаинформации и без отдельного генератора код
>> подобное сделать не удастся. Любые выкрутасы на шаблонах приведут к
>> куче лишних движений при программировании и все равно окажутся мнее
>> гибкими и более медленными нежели это.

C>http://boost.org/libs/serialization/doc/index.html , в частности

C>http://boost.org/libs/serialization/doc/tutorial.html#simplecase

Да, хорошая демонстрация очередного заката солнца вручную. Ради хохмы приведу аналог вот этого:
class gps_position
{
private:
    friend class boost::serialization::access;
    // When the class Archive corresponds to an output archive, the
    // & operator is defined similar to <<.  Likewise, when the class Archive
    // is a type of input archive the & operator is defined similar to >>.
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;
public:
    gps_position(){};
    gps_position(int d, int m, float s) :
        degrees(d), minutes(m), seconds(s)
    {}
};

на Шарпе:
[Serializable]
class gps_position
{
    private int degrees;
    private int minutes;
    private float seconds;
};



C>Был бы в С++ нормальный compile-time reflection — все стало бы еще

C>намного проще.

Был бы у бабушки хрен...

>> Все это конечно можно написать на С++, но это будет не один

>> человекогод. И так почти в каждой области. Именно по этому мы
>> (разработчики Януса) смело заявляем, что повторить Янус на С++ на
>> объщественных началах практически невозможно.

C>Берем Thunderbird и пишем к ней расширение для RSDN. На С++


Ага... языком.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Формат конфигов
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.06.05 12:15
Оценка:
Здравствуйте, eao197, Вы писали:

E>Справедливо. Но зачем для конфигурационных файлов XML Schema, XSLT, XPATH и пр. понять не могу.


Ну что ж — тогда могу просоветовать попробовать любой современный IDE, понимающий XML-Schema.
... << RSDN@Home 1.2.0 alpha rev. 497>>
AVK Blog
Re[8]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 12:32
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, eao197, Вы писали:


E>>Справедливо. Но зачем для конфигурационных файлов XML Schema, XSLT, XPATH и пр. понять не могу.


AVK>Ну что ж — тогда могу просоветовать попробовать любой современный IDE, понимающий XML-Schema.


А уж IDE-то здесь к чему?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[9]: Формат конфигов
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.06.05 12:43
Оценка: :))
Здравствуйте, eao197, Вы писали:

E>>>Справедливо. Но зачем для конфигурационных файлов XML Schema, XSLT, XPATH и пр. понять не могу.


AVK>>Ну что ж — тогда могу просоветовать попробовать любой современный IDE, понимающий XML-Schema.


E>А уж IDE-то здесь к чему?


Попробуй — узнаешь
... << RSDN@Home 1.2.0 alpha rev. 497>>
AVK Blog
Re[10]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 12:56
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, eao197, Вы писали:


E>>>>Справедливо. Но зачем для конфигурационных файлов XML Schema, XSLT, XPATH и пр. понять не могу.


AVK>>>Ну что ж — тогда могу просоветовать попробовать любой современный IDE, понимающий XML-Schema.


E>>А уж IDE-то здесь к чему?


AVK>Попробуй — узнаешь



Хотя бы для какого языка программирования эта IDE должна быть?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[11]: Формат конфигов
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.06.05 13:25
Оценка:
Здравствуйте, eao197, Вы писали:

E>

E>Хотя бы для какого языка программирования эта IDE должна быть?

Для любого. Подойдет VS2003-2005, IDEA.
... << RSDN@Home 1.2.0 alpha rev. 497>>
AVK Blog
Re[7]: Формат конфигов
От: ihatelogins  
Дата: 20.06.05 13:31
Оценка: 1 (1) +1
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, ihatelogins, Вы писали:


I>>Здравствуйте, eao197, Вы писали:


E>>>Здравствуйте, VladD2, Вы писали:


VD>>>>Если ты действительно хочешь что-то сравнить, то порпробуй ответить на вопрос как на С++ сделать вот это: http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
или как сделать сериализацию на С++ такой же простой как в дотнете.



E>>>Имхо, на C++ без существенных издержек и накладных расходов был реализован разбор сложных конфигурационных файлов. Причем не XML формата, а более удобного для редактирования вручную.


I>>Прелесть XML не в том, что требуется меньше закорючек для описания структуры, и не в том, что его проще редактировать вручную, а в том, что он — СТАНДАРТ.


E>Стандарт чего?


Стандарт описания структурированной информации.

E>Имхо, применение XML для конфигов объемом в 100-200 строк -- это из пушки по воробъям.


Использование XML оправдано даже для config-файлов в 1 строку. Размер файла значения не имеет.

I>> С самопальными примочками типа Вашей можете разобраться только Вы. Для неё не сущесвует таких полезных и удобных технологий, как XML Schema (проверка), XSLT (преобразование), XPATH (запросы). Пользователи не смогут воспользоваться внешними высокоуровневыми редакторами этих файлов (а могли бы, если бы была XML схема).


E>Справедливо. Но зачем для конфигурационных файлов XML Schema, XSLT, XPATH и пр. понять не могу.


XML Schema — для проверки корректности структуры.

XSLT в HTML может быть удобен для визуального отображения config-файла.

XPath можеь быть использован для быстрого получения конкретных настроек в config-файле в сторонних приложениях.

Как видите, всё логично, и, САМОЕ ГЛАВНОЕ, стандартизованно. Проще разрабатывать СЕЙЧАС, легче (дешевле, быстрее) поддерживать в будущем.
Re[12]: Формат конфигов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.06.05 13:49
Оценка: :)
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, eao197, Вы писали:


E>>

E>>Хотя бы для какого языка программирования эта IDE должна быть?

AVK>Для любого. Подойдет VS2003-2005, IDEA.


С такими выражениями стоило бы быть поосторожнее. VS2003 -- это C++, C#, VB (или что-то еще)? IDEA -- это Java.
Но под понятие "любой" подойдут так же языки Perl, Python, Ruby, Smalltalk, Oberon, Ada, Modula-2, Eiffel, Prolog, Lisp (все, что сразу удалось вспомнить) и еще куча языков.

Так что-же я должен увидеть?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.