Re: Прокоментируйте код
От: Dmi_3 Россия  
Дата: 30.11.05 21:53
Оценка: :))) :))) :))) :)
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду.


Я предлягаю в начале добавить
/*
а в конце
*/
Re: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 15:45
Оценка: +8 :)
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него


Если он правильно работает, то лучше его не трогать, пусть работает.
Если он работает не правильно, то лучше его выбросить и переписать все начисто.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Прокоментируйте код
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 30.11.05 14:56
Оценка: :))) :)))
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него


Я с тоской думаю о Бангалорах
Re: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 15:15
Оценка: :))) :)))
Здравствуйте, Tom, Вы писали:

... skipped ...

Где такой обфускатор взял?
Re[4]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 30.11.05 16:25
Оценка: 31 (5)
Здравствуйте, eao197, Вы писали:

[]

E>
E>#define HEXC2INT(c) ((c >= 'A' ? ( c - 'A' ) : ( c - '0' )))
E>


Я пользовался таким кодом:
inline uint8_t hex2bin(unsigned char h, unsigned char l)
{
    h |= 0x20;
    h -= 0x30;
    h -= -(h > 9) & 0x27;
    l |= 0x20;
    l -= 0x30;
    l -= -(l > 9) & 0x27;
    return h << 4 | l;
}


Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.
Re[12]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.12.05 09:35
Оценка: 16 (2) -1
Здравствуйте, _Winnie, Вы писали:

_W>Кстати, по-моему, ветку можно выделить и перенести в Философию программирования.


Дык в чем проблема? Запостил бы свое сообщение туда.

_W>Строки — уступка человеческой сущности. Бинарники рулят.


Не всегда и не везде.

_W>Быстро просмотрел главу, которую ты дал, вот за что там хаят бинарники(возможно, что-то пропустил)


_W>1)разный порядок байт, разное выравнивание структур.

_W>Эта проблема решается проще, чем парсинг текста и гораздо более эффективно.
_W>Переставить местами 4 байта это не несколько делений с остатком на 10 и даже не "0123456789abcdef"[(number >> 24)&0xf]. Не говоря уже постоянных проверках "не является ли следующий символ пробелом или скобокой, а может это такая хитрая escape-последовательность".
_W>Или конвертации utf8 <-> японская Shift_JS(гы-гы-гы).

Проблема разного порядка байт в не в том, что их легко или сложно переставлять. Главная проблема в том, что легко забыть эту перестановку сделать. Например:
std::ofstream counter_file( "counter.dat", std::ios::out | std::ios::binary );
counter_file.write( &counter, sizeof counter ); // Ага, записали на MIPS-ах, прочитали на x86 :)

Для того, чтобы поддерживать двоичную сериализацию данных строго в big endian (либо строго в little endian) приходится делать свои потоки или преобразователи. А затем внимательно следить за тем, чтобы только эти средства и использовались.
Теперь сравниваем с обычным текстовым представлением:
std::ofstream counter_file( "counter.dat" );
counter_file << counter; // A уже пофигу MIPS-ы, SPARC-и, x86 и прочая дребедень.

Если мы сюда же добавим различные размеры int-ов и long-ов на разных платформах, то двоичная сериализация -- это тот еще геморрой. См., например, Универсальный код
Автор: mishin
Дата: 28.11.05
.

А уж если counter -- это структура, то записывать еще просто так вообще нельзя.

Чтоже до написания разбора escape-последовательности, то это вообще тривиальная задача. Но, главное, в ней не нужно знать особенностей платформы, только сам язык C++. И в нормальных escape-последовательностях escape-инг нужен только для небольшого количества символов. Если брать по минимуму: \\, \xXX, \0ooo. Но не сложно и штатный набор из C-шных последовательностей поддержать.

_W>2)расширяемость.

_W>Не имеет никакого отношения к войне "текст vs бинарники". И то и то легко сделать расширяемым, и то и то можно сделать нерасширяемым если руки не оттуда растут.
_W>Ложим в начало бинарных чанков данных { type, size, version } и всё.

Здесь я опять не соглашусь. Сделать расширяемым бинарное представление совсем не просто. Особенно если брать в расчет сохранение компактности. Классические примеры: ASN1 BER (Tag-Length-Value представление), которое было слишком избыточным и на смену которому придумали ASN1 PER (где упаковка ведется на битовом уровне). Можешь на досуге посмотреть в эти стандарты, там есть интересные заморочки по компактизации представлений длины данных. Разбираться с этим не проще, чем с escaping-ом символов. А уж если попытаться вручную поддерживать ASN1 PER extensions, то можно только посочувствовать. Не зря же ASN1 компиляторы стоят дорого.

_W>А вот когда приходит неожиданное требование "хотим держать в текстовых строках line-endings, кавычки, двоеточия и слеши", вот тогда уже текстовому формату может прийти пушной зверёк. Продумать это всё заранее сложнее, чем для бинарного формата. И парсер текста усложняется. Вместо одного device.read(buf, size) — пачка if на каждый символ, "а не escape последовательноть ли это?"


Не серьезно. Просто принимается в качестве формата стандартный C++ный способ записи строковых литералов (без триграфов и, при необходимости, без Unicode-символов) и нет проблем.

_W>Начинаются всякие приколы в стиле "а как мне стереть файл "-rf *" или "**"*-- -\\/ '""><|"" ?", почему буква 'я' воспринимается как конец файла,

_W>проблемы с \r\n vs \n\r vs \n vs \r, надо ли считать Q и q одной буквой или разными, русские буквы Е и Ё — это одно и тоже?

А это вообще к чему относилось?

_W>3)Легко воспринимается человеком.

_W>А нафиг это надо?
_W>Если надо отлаживать — пишутся тулзы для просмотра бинарных данных, их писать не сложнее чем те самые парсеры, даже проще.

И сопровождать их. На каждое изменение формата новую версию.

А на счет нафиг нужно... Вот мне например доводилось перелопачивать многомегабайтные текстовые логи путем организации конвейера из нескольких grep-ов и sort-ов. Одной командной строкой, без какого-либо программирования.

_W>* _Winnie представил, что заголовки ip-пакетов будут ходить в сети в текстовом формате и ужаснулся *.


А это уже передергивание, почти в моем стиле

_W>Это всё выше относилось к проблеме передаче данных между разнымими платформами. Если этого не нужно — то не нужно мучаться даже с паддингами/байтордерами.


Еще как нужно. Не забывай, что есть не только C/C++ но и масса других очень даже приятных языков. Вот запишет твоя C++ная программа свои данные в двоичном формате. И попробуй ты его затем на Ruby или Python-е расколупать. А вот с текстовым представлением никаких проблем.

_W>Отмапили файл в памяти — загрузили уровень игры. Всё.


Что-то у тебя какая-то узкая точка зрения Смотришь на такой глобальный вопрос только с позиции game-dev-а.

Двоичные форматы действительно рулят там, где нужна компактность и максимальная скорость. Например, хранение информации в СУБД или передача данных между устройствами (большого объема данных и с высокой скоростью).

Если же этими показателями можно пренебречь, то текстовый формат может оказаться гораздо удобнее. Как в смысле расширяемости, так и в смысле интероперабельности. Здесь Реймонд прав.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Прокоментируйте код
От: jazzer Россия Skype: enerjazzer
Дата: 06.12.05 08:26
Оценка: :)))
Здравствуйте, Кодёнок, Вы писали:

Кё>Здравствуйте, Tom, Вы писали:


Tom>>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него


Кё>Я думаю о регулярных выражениях, а также водке и бабах


Из интервью с гитаристом Скоттом Хендерсоном:

Q: what's the first thing that comes to mind when you hear each of these chord types?

A: When I hear major chords, I think about titties, but when I hear minor or dominant chords, I think about titties, but when I see titties, I don't think about chords.

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 30.11.05 15:17
Оценка: 19 (2)
On Wed, 30 Nov 2005 15:09:39 -0000, Tom <3627@users.rsdn.ru> wrote:

> ME>Мне понравился вызов alloca() в цикле.

> Это может чем то грозить?

Ты выделяешь память на стэке в цикле. Выделенная alloca() память освобождается только при выходе из ф-ции. Грозит тем, что ты можешь исчерпать стэк.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[2]: Прокоментируйте код
От: Глеб Алексеев  
Дата: 30.11.05 15:01
Оценка: +1 :)
Здравствуйте, korzhik, Вы писали:

K>"Ууу, пошёл готовить кофе."

Скорее водку пить.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re: Прокоментируйте код
От: Кодёнок  
Дата: 06.12.05 07:31
Оценка: +1 :)
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него


Я думаю о регулярных выражениях, а также водке и бабах
Re[14]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 07.12.05 10:46
Оценка: -1 :)
Здравствуйте, _Winnie, Вы писали:

[]

_W>Ты мог бы редактировать многомегабайтный Windows Registry File руками?

_W>Windows могла бы нормально загрузится, если бы ей надо было парсить полгигабайта текста при загрузке?
_W>Сразу принимаю возражения "нефиг держать всё в одном файле, если сделать много маленьких то все будет работать быстро — пример — unix" и соглашаюсь.
_W>Но это ограничение и боль для разработчика. А так — "держим всё вместе и нии<sured>". И читать пачку мелких текстовых файлов медленней, чем один большой бинарный.

_W>На время загрузки OS влияет много факторов, но бинарный Registry — это +1 в копилку Windows.


[]

Здесь можно начать с того, что современным операционным системам registry не нужен, конфиг файлы редактируются в любом редакторе. Виндозе понадобился реестр чтобы обойти ограничения собственной убогой файловой системы (то же можно сказать про многие MS-технологии, как, к примеру, structured storage).
Re[4]: Прокоментируйте код
От: runtime2  
Дата: 02.12.05 20:08
Оценка: 13 (1)
Здравствуйте, eao197, Вы писали:

E>Ну, не знаю. Я так делал:

E>
E>// Выделить из запроса все пары <name=value>.
E>static void
E>extract_all_pairs(
E>    const char * query_string,
E>    param_map_t & result )
E>{
E>    size_t start = 0, cur = 0;

E>    // Извлекаем имя параметра.
E>    while( query_string[ cur ] ) {
E>        std::string param_name;
E>        std::string param_value;

E>        if( '=' == query_string[ cur ] ) {
E>            // Имя параметра закончилось.
E>            // Имя параметра должно содержать хотя бы один символ.
E>            if( start != cur ) {
E>                param_name.assign( &query_string[ start ],
E>                    cur - start );
E>                // Пропускаем '='
E>                ++cur;
E>                start = cur;
E>                // Извлекаем значение параметра.
E>                while( query_string[ cur ] ) {
E>                    if( '&' == query_string[ cur ] )
E>                        break;
E>                    ++cur;
E>                }
E>                // Значение параметра закончилось.
E>                // Значение может быть пустым.
E>                if( start != cur ) {
E>                    param_value.assign( &query_string[ start ],
E>                        cur - start );
E>                }

E>                // Для пропуска '&'
E>                if( '&' == query_string[ cur ] )
E>                    start = cur + 1;

E>                // Извлекли и имя, и значение параметра.
E>                // Изменим кодировку.
E>                url_decode( param_name );
E>                url_decode( param_value );

E>                result.insert( param_map_t::value_type(
E>                    param_name, param_value ) );
E>            }
E>        }
E>        ++cur;
E>    }

E>}

E>


E>Может и здесь какие-нибудь баги найдут.


Я плохо разбираюсь в STL и еще хуже в задачах написания подобного
программного обеспечения. Мне кажется, что вот так можно сделать.

//выделяет из запроса все пары <name=value>
static void extractAllPairs(const char* query_string, param_map_t* result)
{
    std::istringstream is(query_string);
    std::string paramName;//имя параметра
    std::string paramValue;//имя значения
    while(!is.eof())
    {
        std::getline(is, paramName,'=');
        std::getline(is, paramValue,'&');
        if( !paramName.empty() )
        {
            url_decode( paramName );
            url_decode( paramValue );
            result->insert( param_map_t::value_type(
                paramName, paramValue ) );
        }
    }
}


Но я думаю, что я упустил из виду что-то важное. Так?
Re: Прокоментируйте код
От: Alexmoon Украина  
Дата: 30.11.05 16:15
Оценка: 10 (1)
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него

Про выделение памяти на стеке в цикле я уж молчу. И так все понятно.
Ничего сложного в коде нет, но дизайн ........... Такие простые вещи минут за 10 минут ну хоть до такого оптимизируются.

void CGIParamsBase::Parse(const char *cstr, int iLen)
{
    //-----------------------------------------
    char* pNameBegin = const_cast<char*>(cstr);
    char* pNameEnd   = NULL;

    if (*pNameBegin == '&') pNameBegin++;

    pNameEnd = strtok(pNameBegin, "=&");

    if(pNameEnd == NULL) return;

    //-----------------------------------------
    char* pValueBegin = pNameEnd + 1;
    char* pValueEnd   = NULL;
    
    switch(*pNameEnd)
    {
    case '=':
        pValueEnd = strtok(pValueBegin, "&");
        if (pNameEnd - pNameBegin > 2)
                {
                    //.......................
                    ProcessParam(pNameBegin, pNameEnd - pNameBegin, pConverted, iNewLen);
        }
        
        if(pValueEnd == NULL) break;

    case '&':
        Parse(pNameEnd, strlen(pNameEnd));
    }
    
    return;
}


Принимаю укоры лишь по оптимизации дизайна, поскольку писагно на колене за 5 минут в UltraEdit и без проверки.

Tom>
Tom>void CGIParamsBase::Parse(const char *cstr, int iLen)
Tom>{
Tom>    char *str = const_cast<char*>(cstr);
Tom>    char *pNameBegin = str, *pNameEnd, *pValueBegin, *pValueEnd;
Tom>    while (pNameBegin - str < iLen)
Tom>    {
Tom>        if (*pNameBegin == '&')
Tom>            pNameBegin++;
Tom>        pNameEnd = pNameBegin;
Tom>        while (pNameEnd - str < iLen && *pNameEnd != '=' && *pNameEnd != '&')
Tom>            pNameEnd++;
Tom>        if (pNameEnd - str == iLen)
Tom>            break;
Tom>        if (*pNameEnd == '&')
Tom>        {
Tom>            pNameBegin = pNameEnd + 1;
Tom>            continue;
Tom>        }

Tom>        pValueEnd = pValueBegin = pNameEnd + 1;
Tom>        while (pValueEnd - str < iLen && *pValueEnd != '&')
Tom>            pValueEnd++;

Tom>        if (pNameEnd - pNameBegin > 2)
Tom>        {
Tom>            int iSrcLen = pValueEnd - pValueBegin;
Tom>            int iNewLen = 0;
Tom>            const char *pSrc = pValueBegin;
Tom>            char *pConverted = (char *)_alloca(iSrcLen);
Tom>            char *pDest = pConverted;
Tom>            for (; iSrcLen-- > 0; iNewLen++, pDest++, pSrc++)
Tom>            {
Tom>                if ((BYTE)*pSrc <= 0x1f || (BYTE)*pSrc >= 0x7f)
Tom>                    goto Cont;
Tom>                if (*pSrc == '+')
Tom>                    *pDest = ' ';
Tom>                else
Tom>                    if (*pSrc == '%')
Tom>                    {
Tom>                        *pDest = (char)(C2D(pSrc[1]) * 16 + C2D(pSrc[2]));
Tom>                        pSrc += 2;
Tom>                        iSrcLen -= 2;
Tom>                    }
Tom>                    else
Tom>                        *pDest = *pSrc;
Tom>            }
Tom>            ProcessParam(pNameBegin, pNameEnd - pNameBegin, pConverted, iNewLen);
Tom>        }
Tom>Cont:
Tom>        pNameBegin = pValueEnd;
Tom>    }
Tom>}
Tom>
Re[8]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 05.12.05 10:22
Оценка: 4 (1)
Здравствуйте, davenger, Вы писали:

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



>>> ME>Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.


D>...


ME>>На gcc 3/4 с твоим кодом будет branching. Я специально затачивал эту ф-цию чтобы избавиться от branching на gcc в сервере с текстовым протоколом. Обратная ф-ция, также без branching:


D>А дейсвительно ли это дало большой выигрыш в общей производительности сервера? Просто инетересно, сколько %?


Это оптимизировалось в сервере с текстовым протоколом. Парсинг занимал 50% времени обработки запроса. Вклад конкретно этой оптимизации не замерялся, в целом удалось соптимизировать парсинг на ~33%.
Re[16]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 07.12.05 11:17
Оценка: 2 (1)
Здравствуйте, Кодёнок, Вы писали:

Кё>Здравствуйте, MaximE, Вы писали:


ME>>Здесь можно начать с того, что современным операционным системам registry не нужен, конфиг файлы редактируются в любом редакторе.


Кё>У конфига есть проблема слияния изменений, если его двое отредактировали одну версию и сохранили по очереди.


3-way merge.

Расскажи мне лучше как двое отредактируют реестр, а затем его смержат...

ME>>Виндозе понадобился реестр чтобы обойти ограничения собственной убогой файловой системы


Кё>Не знаю такой файловой системы, которая бы позволила эффективно хранить миллион мелких переменных (число, короткая строка).


Хранить в файле. Кроме того, современные fs позволяют прицеплять к файлу пару ключ/значение.

ME>> (то же можно сказать про многие MS-технологии, как, к примеру, structured storage).


Кё>Цель Structured Storage — позволить приложениям иметь документы с поддержкой вложений. Например, документ MS Word включает несколько Excel-таблиц. OLE Structured Storage позволяет работать с самим документом Word как с IStorage, так и с вложенными объектами как с IStorage. При этом сам документ Word может быть вложен, и с вложенными в него таблицами Excel может работать как с самостоятельными документами.


Создаешь fs в файле, монтируешь и забываешь про structured storage как про страшный сон.
Re[2]: Прокоментируйте код
От: Tom Россия http://www.RSDN.ru
Дата: 30.11.05 15:48
Оценка: 1 (1)
E>Если он правильно работает, то лучше его не трогать, пусть работает.
E>Если он работает не правильно, то лучше его выбросить и переписать все начисто.

Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[6]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 30.11.05 17:12
Оценка: 1 (1)
On Wed, 30 Nov 2005 16:33:56 -0000, eao197 <31476@users.rsdn.ru> wrote:

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

>
> ME>Я пользовался таким кодом:
> ME>
> ME>inline uint8_t hex2bin(unsigned char h, unsigned char l)
> ME>{
> ME>    h |= 0x20;
> ME>    h -= 0x30;
> ME>    h -= -(h > 9) & 0x27;
> ME>    l |= 0x20;
> ME>    l -= 0x30;
> ME>    l -= -(l > 9) & 0x27;
> ME>    return h << 4 | l;
> ME>}
> ME>

>
> ME>Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.
>
> Интересно.
>
> Смущают две вещи:
>
> Здесь используются именно unsigned char, а у меня std::string, которая как известно, char. И не обязательно char будет unsigned.

Это не проблема, т.к. стандартное преобразование signed -> unsigned is well defined, в отличие от обратного. Т.е. реально эта ф-ция пользуется с char строками.

> Действительно ли будет разница между твоим кодом и моим при современных оптимизирующих компиляторах?


На gcc 3/4 с твоим кодом будет branching. Я специально затачивал эту ф-цию чтобы избавиться от branching на gcc в сервере с текстовым протоколом. Обратная ф-ция, также без branching:

inline char* bin2hex(uint8_t b, char* p)
{
     unsigned char h = b >> 4;
     *p++ = '0' + h + (-(h > 9) & ('a' - '9' - 1));
     unsigned char l = b & 0xf;
     *p++ = '0' + l + (-(l > 9) & ('a' - '9' - 1));
     return p;
}


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[11]: Прокоментируйте код
От: _Winnie Россия C++.freerun
Дата: 05.12.05 23:34
Оценка: 1 (1)
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, _Winnie, Вы писали:

Кстати, по-моему, ветку можно выделить и перенести в Философию программирования.

Строки — уступка человеческой сущности. Бинарники рулят.

Быстро просмотрел главу, которую ты дал, вот за что там хаят бинарники(возможно, что-то пропустил)

1)разный порядок байт, разное выравнивание структур.
Эта проблема решается проще, чем парсинг текста и гораздо более эффективно.
Переставить местами 4 байта это не несколько делений с остатком на 10 и даже не "0123456789abcdef"[(number >> 24)&0xf]. Не говоря уже постоянных проверках "не является ли следующий символ пробелом или скобокой, а может это такая хитрая escape-последовательность".
Или конвертации utf8 <-> японская Shift_JS(гы-гы-гы).

2)расширяемость.
Не имеет никакого отношения к войне "текст vs бинарники". И то и то легко сделать расширяемым, и то и то можно сделать нерасширяемым если руки не оттуда растут.
Ложим в начало бинарных чанков данных { type, size, version } и всё.
Кстати, все медиа-файлы(jpeg, bmp, mp3, avi) в Windows могут храниться в едином RIFF-формате.
А вот когда приходит неожиданное требование "хотим держать в текстовых строках line-endings, кавычки, двоеточия и слеши", вот тогда уже текстовому формату может прийти пушной зверёк. Продумать это всё заранее сложнее, чем для бинарного формата. И парсер текста усложняется. Вместо одного device.read(buf, size) — пачка if на каждый символ, "а не escape последовательноть ли это?"
Начинаются всякие приколы в стиле "а как мне стереть файл "-rf *" или "**"*-- -\\/ '""><|"" ?", почему буква 'я' воспринимается как конец файла,
проблемы с \r\n vs \n\r vs \n vs \r, надо ли считать Q и q одной буквой или разными, русские буквы Е и Ё — это одно и тоже?

3)Легко воспринимается человеком.
А нафиг это надо?
Если надо отлаживать — пишутся тулзы для просмотра бинарных данных, их писать не сложнее чем те самые парсеры, даже проще. Загружаем в Сишные структуры, работаем с ними Сишным кодом, кидаем пару чекбоксов на форму, даём пользователю красивый trewview с property grid. Но эти тулзы работают только в development-time, их даже не надо оптимизировать.

* _Winnie представил, что заголовки ip-пакетов будут ходить в сети в текстовом формате и ужаснулся *.

Это всё выше относилось к проблеме передаче данных между разнымими платформами. Если этого не нужно — то не нужно мучаться даже с паддингами/байтордерами.
Отмапили файл в памяти — загрузили уровень игры. Всё.

Строки(картинки, фильмы, мультики, музыка) — для человека.
Байты — для программ.
Правильно работающая программа — просто частный случай Undefined Behavior
Прокоментируйте код
От: Tom Россия http://www.RSDN.ru
Дата: 30.11.05 14:47
Оценка: :)
Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него

void CGIParamsBase::Parse(const char *cstr, int iLen)
{
    char *str = const_cast<char*>(cstr);
    char *pNameBegin = str, *pNameEnd, *pValueBegin, *pValueEnd;
    while (pNameBegin - str < iLen)
    {
        if (*pNameBegin == '&')
            pNameBegin++;
        pNameEnd = pNameBegin;
        while (pNameEnd - str < iLen && *pNameEnd != '=' && *pNameEnd != '&')
            pNameEnd++;
        if (pNameEnd - str == iLen)
            break;
        if (*pNameEnd == '&')
        {
            pNameBegin = pNameEnd + 1;
            continue;
        }

        pValueEnd = pValueBegin = pNameEnd + 1;
        while (pValueEnd - str < iLen && *pValueEnd != '&')
            pValueEnd++;

        if (pNameEnd - pNameBegin > 2)
        {
            int iSrcLen = pValueEnd - pValueBegin;
            int iNewLen = 0;
            const char *pSrc = pValueBegin;
            char *pConverted = (char *)_alloca(iSrcLen);
            char *pDest = pConverted;
            for (; iSrcLen-- > 0; iNewLen++, pDest++, pSrc++)
            {
                if ((BYTE)*pSrc <= 0x1f || (BYTE)*pSrc >= 0x7f)
                    goto Cont;
                if (*pSrc == '+')
                    *pDest = ' ';
                else
                    if (*pSrc == '%')
                    {
                        *pDest = (char)(C2D(pSrc[1]) * 16 + C2D(pSrc[2]));
                        pSrc += 2;
                        iSrcLen -= 2;
                    }
                    else
                        *pDest = *pSrc;
            }
            ProcessParam(pNameBegin, pNameEnd - pNameBegin, pConverted, iNewLen);
        }
Cont:
        pNameBegin = pValueEnd;
    }
}
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 14:58
Оценка: +1
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него

Следующее: "Неохота читать..."
Re: Прокоментируйте код
От: srggal Украина  
Дата: 30.11.05 15:15
Оценка: -1
Здравствуйте, Tom, Вы писали:

[]

Явное преимущество php над CGI писаным на дилетантском С++
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: Прокоментируйте код
От: Tom Россия http://www.RSDN.ru
Дата: 30.11.05 15:19
Оценка: :)
А>P.S. Это твой код?
Нет слава богу, я столько не курю
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re: Прокоментируйте код
От: sch  
Дата: 30.11.05 15:37
Оценка: :)
Пара достаточно субъективных замечаний.

1) Венгерская нотация не очень вписывается в алгоритмически-сложный код, ему самое место в прикладных задачах, когда программист пишет большие объемы кода.

(Вообще у меня складывается ощущение, что венгерская нотация несколько перегружена разнообразными префиксами. По моему скромному мнению, вполне достаточно явно записывать то, что переменная является членом класса или указателем, фактически BSD-style конечно выглядит лучше в алгоритмически-сложном коде)

2) Алгоритмическая декомпозиция проведена плохо, код вероятно будет трудно отлаживать и поддерживать. Пару веток вполне можно было бы выделить в отдельные функции, что значительно упростило бы код.
Re[3]: Прокоментируйте код
От: srggal Украина  
Дата: 30.11.05 15:51
Оценка: +1
Здравствуйте, Tom, Вы писали:

E>>Если он правильно работает, то лучше его не трогать, пусть работает.

E>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.

Tom>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда


Purify, etc.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Прокоментируйте код
От: Глеб Алексеев  
Дата: 30.11.05 16:18
Оценка: +1
Здравствуйте, Alexmoon, Вы писали:

A>Принимаю укоры лишь по оптимизации дизайна, поскольку писагно на колене за 5 минут в UltraEdit и без проверки.

Укор №1 Вызовом strtok ты модифицируешь строку, переданную как const char*. Нехорошо.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[5]: Прокоментируйте код
От: srggal Украина  
Дата: 01.12.05 09:29
Оценка: +1
Здравствуйте, Tom, Вы писали:

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


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


E>>>>Если он правильно работает, то лучше его не трогать, пусть работает.

E>>>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.

Tom>>>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда


S>>Purify, etc.

Tom>Нет шансов, падения происходят только под серьёзной нагрузкой, Dev Partner или пурифай, убьёт производительность

А если в связке с какой-нить stress utility?
Как вариант, и это тут обсуждалось — если есть подазрения на этот код — то ИМХО быстрей будет его переписать, чем протестировать
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[7]: Прокоментируйте код
От: davenger  
Дата: 02.12.05 18:12
Оценка: +1
Здравствуйте, MaximE, Вы писали:


>> ME>Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.


...

ME>На gcc 3/4 с твоим кодом будет branching. Я специально затачивал эту ф-цию чтобы избавиться от branching на gcc в сервере с текстовым протоколом. Обратная ф-ция, также без branching:


А дейсвительно ли это дало большой выигрыш в общей производительности сервера? Просто инетересно, сколько %?
Re[10]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 05.12.05 15:25
Оценка: +1
Здравствуйте, _Winnie, Вы писали:

ME>>Это оптимизировалось в сервере с текстовым протоколом. Парсинг занимал 50% времени обработки запроса. Вклад конкретно этой оптимизации не замерялся, в целом удалось соптимизировать парсинг на ~33%.


_W>Надо наверное уже себе в подпись поставить- "бинарники рулят" и "строки — уступка человеческой сущности"


Советую это сделать после прочтения The Art of Unix Programmig. Конкретно главы 5. http://www.faqs.org/docs/artu/textualitychapter.html
Re[15]: Прокоментируйте код
От: Кодёнок  
Дата: 07.12.05 11:09
Оценка: +1
Здравствуйте, MaximE, Вы писали:

ME>Здесь можно начать с того, что современным операционным системам registry не нужен, конфиг файлы редактируются в любом редакторе.


У конфига есть проблема слияния изменений, если его двое отредактировали одну версию и сохранили по очереди.

ME>Виндозе понадобился реестр чтобы обойти ограничения собственной убогой файловой системы


Не знаю такой файловой системы, которая бы позволила эффективно хранить миллион мелких переменных (число, короткая строка).

ME> (то же можно сказать про многие MS-технологии, как, к примеру, structured storage).


Цель Structured Storage — позволить приложениям иметь документы с поддержкой вложений. Например, документ MS Word включает несколько Excel-таблиц. OLE Structured Storage позволяет работать с самим документом Word как с IStorage, так и с вложенными объектами как с IStorage. При этом сам документ Word может быть вложен, и с вложенными в него таблицами Excel может работать как с самостоятельными документами.

Разве хоть одна файловая система что-то подобное предлагает? Разве это вообще в компетенции файловой системы?
Re[14]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.12.05 12:49
Оценка: +1
Здравствуйте, _Winnie, Вы писали:

_W>Ты мог бы редактировать многомегабайтный Windows Registry File руками?


А мне не нравятся убогие средства поиска информации в Registry через RegEdit.
В Unix-е, к примеру, grep по /etc дает возможности для поиска на порядок мощнее.

_W>Windows могла бы нормально загрузится, если бы ей надо было парсить полгигабайта текста при загрузке?


Интересно, в Linux-а и BSD есть сотни маленьких конфигах в /etc и не жужит.

_W>На время загрузки OS влияет много факторов, но бинарный Registry — это +1 в копилку Windows.


По этому поводу есть разные мнения. И мое не совпадает с твоим.

_W>Лог файлы тоже для людей. Их тоже незападло сделать текстовыми. Даже с красивой HTML-подсветкой.


HTML-подсветка в логе -- это оригинально

_W>Но, вот извините, использовать XML для маршаллинга данных между системами — моветон.


Ну, если говорить вообще про XML, то XML must die! Это сугубо мое мнение. Как обычно, мейнстримом стало не самое удачное с технической точки зрения решения. Но структурированный текст -- это не обязательно XML, мне лично больше нравится lisp-подобный синтаксис, или latex-овый, или YAML.

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

_W>Правильный ответ на эти вопросы — "убейте себя. или юзайте бинарники".


Юзать бинарники имеет смысл, например, если данные нужно подписывать. Подписывание XML -- это вообще интересная затея. Тому, кто до нее додумался нужно либо памятник ставить, либо сбросить этот памятник на голову

А отличный пример текстовых данных для взаимодействия приложений -- конвейер unix-овых команд. Когда выход grep идет на вход sort, а оттуда на вход wc.

_W>Заявления по поводу "на одном компьютере long 32-битный, на другом — 64" я не понимаю.


Жаль.

_W>Наооборот, бинарник заставит задуматься, сколько надо выделить байтов под число.


В большинстве случаев не нужно задумываться. Я в своей библиотеке сериализации из-за незнание про существование ASN1 сделал тривиальное решение -- хранить размерности string и контейнеров в виде четырехбайтовых полей. А затем мне пришлось сделать детальное описание блока сериализованных данных. Я поразился, насколько много лишних нулевых байтов было в данных! А все из-за того, что в реальной жизни размерности строк и контейнеров были очень маленькими -- максимум не больше 4-8Kb. А еще чаще -- меньше ста байт. Даже текстовое представление размерностей было бы компактнее двоичного.

_W>А при записи в текст числа больше 0xff'ff'ff'ff всё пройдет гладко. А вот при чтении — нет.

_W>К текст vs бинарники это опять же отношения не имеет. Проблема не в протоколе, проблема в использовании типа long и что на одном компьютере он оказался больше, чем (1<<32).

Ok. А протоколу то что делать? Ведь long-и как-то нужно передавать.

_W>И я уверен, что твой обработчик из командной строки сломается, если в логе прямо в тексте будет какой-нибудь служебный знак.


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

_W>Насчет решения ежечасных каждодневых задач — как в питоне/руби будет выглядеть


Хреново будет выглядеть я думаю (про Ruby говорю). Поэтому и утверждаю, что обеспечить интероперабельность данных между разными языками в двоичном формате гораздо сложнее, чем в текстовом. Я сейчас пытаюсь прикрутить к своей ObjESSty работу из Ruby и двоичность формата сериализации этому не способствует.

Собственно и следующий твой пример говорит о том же. Пока ты работаешь с одним языком и одним компилятором, бинарность данных не играет роли. Стоить добавить еще один язык (особенно динамический, вроде Python/Ruby/Smalltalk) и бинарность становится проблемой.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[16]: Прокоментируйте код
От: jedi Мухосранск  
Дата: 07.12.05 20:57
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>Не знаю такой файловой системы, которая бы позволила эффективно хранить миллион мелких переменных (число, короткая строка).


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

Для загрузки ОС будет достаточно несколько сотен (тысяч) переменных которые вполне быстро при стартапе прочитаются и распарсятся.
А вместе с тем и другие преимущества отдельных текстовых конфигов остаются.
Re: Прокоментируйте код
От: korzhik Россия  
Дата: 30.11.05 15:00
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него


[...]

"Ууу, пошёл готовить кофе."
Re: Прокоментируйте код
От: Bell Россия  
Дата: 30.11.05 15:03
Оценка:
Здравствуйте, Tom, Вы писали:

Тоска зеленая Разбираться быстро надоело...
Любите книгу — источник знаний (с) М.Горький
Re: Прокоментируйте код
От: MaximE Великобритания  
Дата: 30.11.05 15:06
Оценка:
On Wed, 30 Nov 2005 14:47:04 -0000, Tom <3627@users.rsdn.ru> wrote:

> Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него


Мне понравился вызов alloca() в цикле.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[2]: Прокоментируйте код
От: Tom Россия http://www.RSDN.ru
Дата: 30.11.05 15:09
Оценка:
ME>Мне понравился вызов alloca() в цикле.
Это может чем то грозить?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[3]: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 15:18
Оценка:
Здравствуйте, Tom, Вы писали:

ME>>Мне понравился вызов alloca() в цикле.

Tom>Это может чем то грозить?

Как чем? Переполнением стека.
Где free, кстати?

Да и вобще, зачем нужен С++, если в таком стиле писать?

P.S. Это твой код?
Re: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 15:19
Оценка:
Здравствуйте, Tom, Вы писали:

Мда. Какой то ужас и много хард кода
Re[5]: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 15:20
Оценка:
Здравствуйте, Tom, Вы писали:

А>>P.S. Это твой код?

Tom>Нет слава богу, я столько не курю

Ну слава богу... Ато я уж испугался
Re[4]: Прокоментируйте код
От: MaximE Великобритания  
Дата: 30.11.05 15:24
Оценка:
On Wed, 30 Nov 2005 15:18:19 -0000, Аноним <0@users.rsdn.ru> wrote:

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

>
> ME>>Мне понравился вызов alloca() в цикле.
> Tom>Это может чем то грозить?
>
> Как чем? Переполнением стека.
> Где free, кстати?

Для alloca() не нужен free().

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[6]: Прокоментируйте код
От: Codechanger Россия  
Дата: 30.11.05 15:30
Оценка:
Вах...goto решает, конечно...Мало что осилил... уж очень все запутано...
Re[7]: Прокоментируйте код
От: Codechanger Россия  
Дата: 30.11.05 15:33
Оценка:
А вообще довольно коряво... чую, работает также, как и написано...
Re: Прокоментируйте код
От: srggal Украина  
Дата: 30.11.05 15:49
Оценка:
Здравствуйте, Tom, Вы писали:

[]
Ещё подумалось: возможно yacc/bizon справился бы лучше
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 15:51
Оценка:
Здравствуйте, Tom, Вы писали:

E>>Если он правильно работает, то лучше его не трогать, пусть работает.

E>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.

Tom>Внимание вопрос! Как понять что он работает правильно


unit-тестами?

Tom> и не бомбит память иногда


Это действительно вопрос. А что, есть подозрение?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 15:56
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Для alloca() не нужен free().


А точно...
100 лет уже не пользовал alloca
Re[3]: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 15:58
Оценка:
Здравствуйте, Tom, Вы писали:

E>>Если он правильно работает, то лучше его не трогать, пусть работает.

E>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.

Tom>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда


Иногда железно бомбит хотя бы из-за alloca в цикле.
В общем если верно подобрать входные данные, то довольно легко все завалить.
Re[2]: Прокоментируйте код
От: Глеб Алексеев  
Дата: 30.11.05 15:59
Оценка:
Здравствуйте, srggal, Вы писали:

S>Ещё подумалось: возможно yacc/bizon справился бы лучше

из пушки по пернатым друзьям, ИМХО. строку вида name1=val1&name2=val2&name3=%2А можно самому распарсить кодом попроще, чем в оригинале.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[3]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 16:08
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

S>>Ещё подумалось: возможно yacc/bizon справился бы лучше

ГА>из пушки по пернатым друзьям, ИМХО. строку вида name1=val1&name2=val2&name3=%2А можно самому распарсить кодом попроще, чем в оригинале.

Ну, не знаю. Я так делал:
//
// param_map_t
//

//! Словарь значений CGI-параметров.
typedef std::map< std::string, std::string >
    param_map_t;

#define HEXC2INT(c) ((c >= 'A' ? ( c - 'A' ) : ( c - '0' )))

// Преобразовать URL-кодировку в ASCII.
static void
url_decode( std::string & what )
{
    std::string::size_type i = 0;
    while( i != what.length() ) {
        char c = what[ i ];
        if( '+' == c )
            what.replace( i, 1, 1, ' ' );
        else if( '%' == c ) {
            // Расшифровать HEX представление.
            if( i + 2 < what.length() ) {
                char h1 = toupper( what[ i + 1 ] );
                char h2 = toupper( what[ i + 2 ] );
                if( isxdigit( h1 ) && isxdigit( h2 ) ) {
                    // Можно создавать ASCII представление.
                    char r = ( HEXC2INT( h1 ) << 4 ) |
                        HEXC2INT( h2 );
                    what.replace( i, 3, 1, r );
                    // Переменную i не изменяем, т.к. она
                    // указывает на замененный символ.
                }
            }
        }
        ++i;
    }
}

// Выделить из запроса все пары <name=value>.
static void
extract_all_pairs(
    const char * query_string,
    param_map_t & result )
{
    size_t start = 0, cur = 0;

    // Извлекаем имя параметра.
    while( query_string[ cur ] ) {
        std::string param_name;
        std::string param_value;

        if( '=' == query_string[ cur ] ) {
            // Имя параметра закончилось.
            // Имя параметра должно содержать хотя бы один символ.
            if( start != cur ) {
                param_name.assign( &query_string[ start ],
                    cur - start );
                // Пропускаем '='
                ++cur;
                start = cur;
                // Извлекаем значение параметра.
                while( query_string[ cur ] ) {
                    if( '&' == query_string[ cur ] )
                        break;
                    ++cur;
                }
                // Значение параметра закончилось.
                // Значение может быть пустым.
                if( start != cur ) {
                    param_value.assign( &query_string[ start ],
                        cur - start );
                }

                // Для пропуска '&'
                if( '&' == query_string[ cur ] )
                    start = cur + 1;

                // Извлекли и имя, и значение параметра.
                // Изменим кодировку.
                url_decode( param_name );
                url_decode( param_value );

                result.insert( param_map_t::value_type(
                    param_name, param_value ) );
            }
        }
        ++cur;
    }

}

//
// parse_query_string
//

/*
    Процедура разбора значения переменной среды QUERY_STRING
    на множество пар <имя параметра, значение параметра>.
*/
void
parse_query_string( param_map_t & result )
{
    const char * env_value = getenv( "QUERY_STRING" );
    if( env_value ) {
        // Можно осуществлять разбор.

        // Выделяем все пары значений.
        extract_all_pairs( env_value, result );
    }
}


Может и здесь какие-нибудь баги найдут.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Прокоментируйте код
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 30.11.05 16:18
Оценка:
Здравствуйте, srggal, Вы писали:

S>Ещё подумалось: возможно yacc/bizon справился бы лучше


Возможно, что это даже он
Re[4]: Прокоментируйте код
От: srggal Украина  
Дата: 30.11.05 16:24
Оценка:
Здравствуйте, eao197, Вы писали:

[]

ИМХО на примере двух вариантов кода отдаю предпочтение yacc'у
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: Прокоментируйте код
От: Alexmoon Украина  
Дата: 30.11.05 16:32
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, Alexmoon, Вы писали:


A>>Принимаю укоры лишь по оптимизации дизайна, поскольку писагно на колене за 5 минут в UltraEdit и без проверки.

ГА>Укор №1 Вызовом strtok ты модифицируешь строку, переданную как const char*. Нехорошо.

Спасибо. Может и не прилично с моей стороны оправдываться, но не урок а поправка внимательности. Такие вещи как то что не модифицируемые строки передаются по константному указателю, если уж быть совсем корректными, нужно отслеживать на лету. С укором к себе согласен, но думаю что смысл дизайна это не портит. В таком случае я бы посоветовал написать собственную реализацию данной функции, поскольку проще реализации придумать сложно, тем более что у нас поиск одноуровневый, чем морочить голову с возможным модифицированием строки, не говоря уже о копировании, что еще хуже. Для таких вещей это слишком. Это еще раз говорит о том, что const_cast тоже весьма порочная практика, если не уверен в том что делаешь. Тоже в раздел по возможности избегать.
Re[5]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 16:33
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Я пользовался таким кодом:

ME>
ME>inline uint8_t hex2bin(unsigned char h, unsigned char l)
ME>{
ME>    h |= 0x20;
ME>    h -= 0x30;
ME>    h -= -(h > 9) & 0x27;
ME>    l |= 0x20;
ME>    l -= 0x30;
ME>    l -= -(l > 9) & 0x27;
ME>    return h << 4 | l;
ME>}
ME>


ME>Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.


Интересно.

Смущают две вещи:

Здесь используются именно unsigned char, а у меня std::string, которая как известно, char. И не обязательно char будет unsigned.

Действительно ли будет разница между твоим кодом и моим при современных оптимизирующих компиляторах?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Прокоментируйте код
От: Alexmoon Украина  
Дата: 30.11.05 16:44
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>Здравствуйте, Глеб Алексеев, Вы писали:


<skip>

пока писал ответ, то в сразу бросилась в глаза еще одна фактическая ошибка. теоретических пока не вижу.

void CGIParamsBase::Parse(const char *cstr, int iLen)
{
    //-----------------------------------------
    char* pNameBegin = const_cast<char*>(cstr);
    char* pNameEnd   = NULL;

    if (*pNameBegin == '&') pNameBegin++;

    pNameEnd = strtok(pNameBegin, "=&");

    if(pNameEnd == NULL) return;

    //-----------------------------------------
    char* pValueBegin = pNameEnd + 1;
    char* pValueEnd   = NULL;
    
    switch(*pNameEnd)
    {
    case '=':
        pValueEnd = strtok(pValueBegin, "&");
        if (pNameEnd - pNameBegin > 2)
                {
                    //.......................
                    ProcessParam(pNameBegin, pNameEnd - pNameBegin, pConverted, iNewLen);
        }
        
        if(pValueEnd == NULL) break; pNameEnd = pValueEnd + 1;

    case '&':
        Parse(pNameEnd, strlen(pNameEnd));
    }
    
    return;
}
Re[4]: Прокоментируйте код
От: Аноним  
Дата: 30.11.05 16:57
Оценка:
Здравствуйте, индусы, Вы пeсали:

И>Ну, не знаю. Мы так делали:


А вроде в 21 веке живём...

(писал вслепую в браузере, навярняка есть опечатки. но идея, я думаю, понятна )

        using namеspace boost::spirit;
        X = range_p('A', 'F') | range_p('0', '9');
        Char = ('%' >> (X >> X)[BIND(OnHexChar)] | (range_p((char)31, (char)127) - '=' - '&')[BIND(OnChar)]);
        NVPair =  ch_p('+')[BIN(OnPlusSpace)] | ((+Char)[BIND(OnValue)] >> '=' >>(+Char)[BIND(OnValue)])[BIND(OnNVPair)];
        CGI_Request = NVPair >> *( '&' >> NVPair );


Обладатели SUN Pro C++, VC6.0, G++ 2.95, молчать!
Пишу анонимно, так как на меня сейчас навалятся обладатели этих компилятов
Re[5]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 17:05
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>
А>        using namеspace boost::spirit;
А>        X = range_p('A', 'F') | range_p('0', '9');
А>        Char = ('%' >> (X >> X)[BIND(OnHexChar)] | (range_p((char)31, (char)127) - '=' - '&')[BIND(OnChar)]);
А>        NVPair =  ch_p('+')[BIN(OnPlusSpace)] | ((+Char)[BIND(OnValue)] >> '=' >>(+Char)[BIND(OnValue)])[BIND(OnNVPair)];
А>        CGI_Request = NVPair >> *( '&' >> NVPair );
А>


А>Обладатели SUN Pro C++, VC6.0, G++ 2.95, молчать!

А>Пишу анонимно, так как на меня сейчас навалятся обладатели этих компилятов

Да, блин, читабельность просто потрясающая. Не говоря уже о том, что знание boost::spirit совершенно не является обязательным для среднего C++ программиста. Так что сюда нужно еще добавить время, которое мне потребуется на изучение boost::spirit. А заодно и код функций OnChar, OnHexChar, OnPlusSpace, OnValue...

Ты будешь смеятся, но этот код был написан года три назад. И основным требованием к нему было то, что он должен был работать под VC6.0. Заказчик музыку-то заказывает
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Прокоментируйте код
От: Cyberax Марс  
Дата: 30.11.05 17:08
Оценка:
eao197 wrote:

> Да, блин, читабельность просто потрясающая.


Если знать Spirit, то вполне нормально читается. Фактически тот же EBNF

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

> требованием к нему было то, что он должен был работать под VC6.0.
> Заказчик музыку-то заказывает

Spirit (частично) работает под VC6. В частности, этот пример там
работать будет.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[7]: Прокоментируйте код
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 17:16
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Если знать Spirit, то вполне нормально читается. Фактически тот же EBNF


Ага, EBNF, до которого еще Вирт не добрался Вот он бы точно порадовался бы такой читабельности

Пусть уж лучше я прослыву ретроградом, но читабельность этого BNF оставляет желать много, много лучшего. Так что ну его нафиг, вместе с boost::spirit.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: Прокоментируйте код
От: srggal Украина  
Дата: 30.11.05 17:28
Оценка:
Здравствуйте, eao197, Вы писали:

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


C>>Если знать Spirit, то вполне нормально читается. Фактически тот же EBNF


E>Ага, EBNF, до которого еще Вирт не добрался Вот он бы точно порадовался бы такой читабельности


E>Пусть уж лучше я прослыву ретроградом, но читабельность этого BNF оставляет желать много, много лучшего. Так что ну его нафиг, вместе с boost::spirit.


Не согласен

boost::spirit — это хорошо, особенно если придерживаться форматирования которое использует команда boost::spirit.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: Прокоментируйте код
От: Tom Россия http://www.RSDN.ru
Дата: 01.12.05 09:24
Оценка:
Здравствуйте, srggal, Вы писали:

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


E>>>Если он правильно работает, то лучше его не трогать, пусть работает.

E>>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.

Tom>>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда


S>Purify, etc.

Нет шансов, падения происходят только под серьёзной нагрузкой, Dev Partner или пурифай, убьёт производительность
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[9]: Прокоментируйте код
От: _Winnie Россия C++.freerun
Дата: 05.12.05 10:51
Оценка:
ME>Это оптимизировалось в сервере с текстовым протоколом. Парсинг занимал 50% времени обработки запроса. Вклад конкретно этой оптимизации не замерялся, в целом удалось соптимизировать парсинг на ~33%.

Надо наверное уже себе в подпись поставить- "бинарники рулят" и "строки — уступка человеческой сущности"
Правильно работающая программа — просто частный случай Undefined Behavior
Re[13]: Прокоментируйте код
От: _Winnie Россия C++.freerun
Дата: 07.12.05 10:32
Оценка:
Здравствуйте, eao197, Вы писали:


Я ничего не имею против теста, как промежуточного формата, до конвертации его в бинарник. (Пока его не слишком много. Часто слышу стоны "у нас 20 гигабайт XML-файлов, ни одна система контроля версий не работает!!!").
Конфигурационные файлы — они для человека. Их тоже не западло сделать текстовыми.
Тут тоже вопрос.
Ты мог бы редактировать многомегабайтный Windows Registry File руками?
Windows могла бы нормально загрузится, если бы ей надо было парсить полгигабайта текста при загрузке?
Сразу принимаю возражения "нефиг держать всё в одном файле, если сделать много маленьких то все будет работать быстро — пример — unix" и соглашаюсь.
Но это ограничение и боль для разработчика. А так — "держим всё вместе и нии<sured>". И читать пачку мелких текстовых файлов медленней, чем один большой бинарный.

На время загрузки OS влияет много факторов, но бинарный Registry — это +1 в копилку Windows.


Лог файлы тоже для людей. Их тоже незападло сделать текстовыми. Даже с красивой HTML-подсветкой.
Возможно, MS которая держит event-log в бинарном виде и неправа. Информации там немного.
Но зато никаких проблем с юникодом, кавычками, двоеточиями и слешами.

Но, вот извините, использовать XML для маршаллинга данных между системами — моветон. Их никто не видит, кроме хакеров со снифферами. Зато рождает проблемы "распарсить число без бренчинга" (что, кстати, в принципе невозможно. branching есть, но в функции выше — проверять конец файла/строки нужно/конец числа, и на каждый символ должен быть хотя бы один if или по хотя бы по одной итерации while).
Любые крики "посоветуйте быстрый XML парсер" из этой же оперы. (SAX — не панацея(что, если я хочу отсортировать?) и в любом случае медленней на порядки).
Правильный ответ на эти вопросы — "убейте себя. или юзайте бинарники".

Заявления по поводу "на одном компьютере long 32-битный, на другом — 64" я не понимаю.
Наооборот, бинарник заставит задуматься, сколько надо выделить байтов под число.
А при записи в текст числа больше 0xff'ff'ff'ff всё пройдет гладко. А вот при чтении — нет.
К текст vs бинарники это опять же отношения не имеет. Проблема не в протоколе, проблема в использовании типа long и что на одном компьютере он оказался больше, чем (1<<32).

Тест — для людей, для компов — бинарники :P.
Альтернатива — всё бинарники, для людей — GUI. Для программистов — всякие .pdb, .h, .xml которые описывают раскладку бинарных данных.

И я уверен, что твой обработчик из командной строки сломается, если в логе прямо в тексте будет какой-нибудь служебный знак.
А может, он уже был сломан, а ты просто этого не заметил, и какое-то сообщение разделилось на два сообщения.
(Допускаю, что не прав, что таких знаков быть не может/формат лога это просто не допускает/ты написал "one-line-perl-program " которая правильно обработала все seq-последовательности).


Насчет решения ежечасных каждодневых задач — как в питоне/руби будет выглядеть

//писал в браузере, подглядывая в MSDN, могут быть опечатки/баги.
BITMAPFILEHEADER bmp_file_header;
BITMAPINFOHEADER bmp_header;
fread(&bmp_file_header, 1, sizeof(bmp_file_header));
fread(&bmp_header, 1, sizeof(bmp_header));

assert(bmp_header.biBitCount == 24);
assert(bmp_header.biCompression == BI_RGB);
assert(bmp_header.biPlanes == 1);

std::vector<byte> image_data(bmp_header.biWidth*bmp_header.biHeight*3);
fread(&image_data[0], 1, image.size(), bmp_file);
//работаю с картинкой.



А вот реальный копипаст из моего далёго C++ Builder детства. Здесь я даже не малодушничаю, не использую WAVERFORMATEX windows.h, описал формат руками по информации из книжки.

#pragma option push -a1 
struct FmtBlock
{
  uint16 compress_code; //1
  uint16 channel_num;
  int32 discr;
  int32 byte_per_sec;
  uint16 align;
  uint16 kvant_bits;
  //short extra;
};


struct WaveHead
{
  Label riff;
  int rifflen;
  Label wave;
  Label fmt;
  int fmtlen; //16
  FmtBlock fmtblock;
  int soundlen;
};

#pragma option pop

class Wave
{
  private:
    ....
  public:
    std::valarray<short> data;
    int len;
    int n_channels;
    //int bperkvant;
    int discr;
    ....
    void Save(char *filename);
};

void Wave::Save(char *filename)
{
  File wfile(filename, "wb");
  int bpr= 16; //bits per record
  FmtBlock fmt=
  {
    1,
    n_channels,
    discr,
    (bpr/8)*n_channels*discr,
    (bpr/8)*n_channels,
    bpr
  };
  uint32 data_size=len*n_channels*(bpr/8);
  uint32 riff_size=
    +data_size
    +4 //RIFF
    +4
    +4 //WAVE
    +4 //ftm
    +4
    +sizeof(fmt) //16
    +4 //data
    +4;
  wfile.Write("RIFF",4);
  wfile.Write(riff_size);
  wfile.Write("WAVE",4);
  wfile.Write("fmt ",4);
  uint32 fmt_size=sizeof(fmt);
  wfile.Write(fmt_size);
  wfile.Write(fmt);
  wfile.Write("data", 4);
  wfile.Write(data_size);
  wfile.Write(&data[0], len*n_channels);
}


Удобно. Быстро.

Обрати внимание, я не использую никаких библиотек. Я использую только описание формата файла из <windows.h> или свои struct.
Я предпочитаю для работы .h файл + бинарник, чем xml + мегабайт докуметации, который объясняет что где какой тег означает. Если хранить в xml что-то отличное от "древовидно-размеченный текст с аттрибутами", то всё равно необоходим дополнительный парсинг.

шуточная Winnie::Serialization не приспособлена к разным endianess, но её легко приспособить. Просто изъять из неё понятие POD-типа и массивов POD-типов, исключая unsigned char. И честно прописать функцию сериализации uint32_t/uint32_least_t/ (с разными #ifdef для платформ).

PS. Бомбочку вроде повесил, что надо в Философию. Модераторы, вы где?
Правильно работающая программа — просто частный случай Undefined Behavior
Re[17]: Прокоментируйте код
От: Кодёнок  
Дата: 07.12.05 11:48
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>>>Здесь можно начать с того, что современным операционным системам registry не нужен, конфиг файлы редактируются в любом редакторе.

Кё>>У конфига есть проблема слияния изменений, если его двое отредактировали одну версию и сохранили по очереди.
ME>3-way merge.

Именно, GUI-диалог редактирования настроек должен уметь делать merge. Проблема кстати не с потолка взята, а обнаружилась недавно как баг в программе, которая как раз вынуждена работать с конфигом. И решаю я её именно через 3-way merge, чтобы выглядит явно извращением.

ME>Расскажи мне лучше как двое отредактируют реестр, а затем его смержат...


Реестр не редактируют — с ним работают через API. Вместо переписывания конфига целиком, оба пользователя изменят только те значения, по которым пользователь покликал. Независмые значения можно изменить одновременно, одно и то же значений — по принципу "кто последний, тот и папа". Чтобы получить этот механизм на конфигах, надо прикручивать к ним merge. Если учесть, что единый формат текстовых конфигов пока еще только благое пожелание — черт знает что будет. В *nix эта проблема просто никак не нерешена, насколько мне известно, т.к. возникает не часто. Тем не менее, это иллюстрация.

Кё>>Не знаю такой файловой системы, которая бы позволила эффективно хранить миллион мелких переменных (число, короткая строка).

ME>Хранить в файле.

И в чем тогда разница с реестром, который тоже в файле хранится?

ME>Кроме того, современные fs позволяют прицеплять к файлу пару ключ/значение.


Какие это FS?

Кё>>Цель Structured Storage — позволить приложениям иметь документы с поддержкой вложений. Например, документ MS Word включает несколько Excel-таблиц. OLE Structured Storage позволяет работать с самим документом Word как с IStorage, так и с вложенными объектами как с IStorage. При этом сам документ Word может быть вложен, и с вложенными в него таблицами Excel может работать как с самостоятельными документами.


ME>Создаешь fs в файле, монтируешь и забываешь про structured storage как про страшный сон.


А потом монтируешь файл в этой vfs в другой каталог с помощью другой vfs и так далее? И это работает без прав root'a? А все необходимые модули vfs в ядре уже загружены, или уже можно монтировать vfs без привлечения модулей ядра?

А существующая куча проектов на freshmeat для работы с различными видами архивов/форматов (ZIP, TAR, AAF) — это пережиток прошлого, и они скоро исчезнут? Что-то сомневаюсь.
Re: Прокоментируйте код
От: ddanila Россия  
Дата: 07.12.05 12:53
Оценка:
Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него

Думаю просто о девушках. Причём вполне конкретных.
Re[15]: Прокоментируйте код
От: Centaur Россия  
Дата: 07.12.05 16:26
Оценка:
Здравствуйте, eao197, Вы писали:

_W>>Лог файлы тоже для людей. Их тоже незападло сделать текстовыми. Даже с красивой HTML-подсветкой.


E>HTML-подсветка в логе -- это оригинально


I HaveThisPattern. Это позволяет писать в лог картинки. И на входе в каждую функцию стоит линк на возврат (и наоборот).

С другой стороны, когда HTML-лог под 15 мегабайт, а картинок в нём много, то любой браузер на нём практически дохнет. И начинаешь хотеть, чтобы он был бинарным.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.