On Wed, 30 Nov 2005 14:47:04 -0000, Tom <3627@users.rsdn.ru> wrote:
> Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него
On Wed, 30 Nov 2005 15:18:19 -0000, Аноним <0@users.rsdn.ru> wrote:
> Здравствуйте, Tom, Вы писали: > > ME>>Мне понравился вызов alloca() в цикле. > Tom>Это может чем то грозить? > > Как чем? Переполнением стека. > Где free, кстати?
1) Венгерская нотация не очень вписывается в алгоритмически-сложный код, ему самое место в прикладных задачах, когда программист пишет большие объемы кода.
(Вообще у меня складывается ощущение, что венгерская нотация несколько перегружена разнообразными префиксами. По моему скромному мнению, вполне достаточно явно записывать то, что переменная является членом класса или указателем, фактически BSD-style конечно выглядит лучше в алгоритмически-сложном коде)
2) Алгоритмическая декомпозиция проведена плохо, код вероятно будет трудно отлаживать и поддерживать. Пару веток вполне можно было бы выделить в отдельные функции, что значительно упростило бы код.
E>Если он правильно работает, то лучше его не трогать, пусть работает. E>Если он работает не правильно, то лучше его выбросить и переписать все начисто.
Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда
Здравствуйте, Tom, Вы писали:
E>>Если он правильно работает, то лучше его не трогать, пусть работает. E>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.
Tom>Внимание вопрос! Как понять что он работает правильно
unit-тестами?
Tom> и не бомбит память иногда
Это действительно вопрос. А что, есть подозрение?
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Tom, Вы писали:
E>>Если он правильно работает, то лучше его не трогать, пусть работает. E>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.
Tom>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда
Purify, etc.
... << RSDN@Home 1.1.4 stable rev. 510>>
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 в цикле.
В общем если верно подобрать входные данные, то довольно легко все завалить.
Здравствуйте, srggal, Вы писали:
S>Ещё подумалось: возможно yacc/bizon справился бы лучше
из пушки по пернатым друзьям, ИМХО. строку вида name1=val1&name2=val2&name3=%2А можно самому распарсить кодом попроще, чем в оригинале.
Здравствуйте, Глеб Алексеев, Вы писали:
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++.
Здравствуйте, Tom, Вы писали:
Tom>Принимаются любые коментарии к след. коду. Просто что вы думаете взглянув на него
Про выделение памяти на стеке в цикле я уж молчу. И так все понятно.
Ничего сложного в коде нет, но дизайн ........... Такие простые вещи минут за 10 минут ну хоть до такого оптимизируются.
Здравствуйте, Alexmoon, Вы писали:
A>Принимаю укоры лишь по оптимизации дизайна, поскольку писагно на колене за 5 минут в UltraEdit и без проверки.
Укор №1 Вызовом strtok ты модифицируешь строку, переданную как const char*. Нехорошо.
Здравствуйте, Глеб Алексеев, Вы писали:
ГА>Здравствуйте, Alexmoon, Вы писали:
A>>Принимаю укоры лишь по оптимизации дизайна, поскольку писагно на колене за 5 минут в UltraEdit и без проверки. ГА>Укор №1 Вызовом strtok ты модифицируешь строку, переданную как const char*. Нехорошо.
Спасибо. Может и не прилично с моей стороны оправдываться, но не урок а поправка внимательности. Такие вещи как то что не модифицируемые строки передаются по константному указателю, если уж быть совсем корректными, нужно отслеживать на лету. С укором к себе согласен, но думаю что смысл дизайна это не портит. В таком случае я бы посоветовал написать собственную реализацию данной функции, поскольку проще реализации придумать сложно, тем более что у нас поиск одноуровневый, чем морочить голову с возможным модифицированием строки, не говоря уже о копировании, что еще хуже. Для таких вещей это слишком. Это еще раз говорит о том, что const_cast тоже весьма порочная практика, если не уверен в том что делаешь. Тоже в раздел по возможности избегать.
А>Обладатели 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++.
eao197 wrote:
> Да, блин, читабельность просто потрясающая.
Если знать Spirit, то вполне нормально читается. Фактически тот же EBNF
> Ты будешь смеятся, но этот код был написан года три назад. И основным > требованием к нему было то, что он должен был работать под VC6.0. > Заказчик музыку-то заказывает
Spirit (частично) работает под VC6. В частности, этот пример там
работать будет.
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;
}
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Cyberax, Вы писали:
C>>Если знать Spirit, то вполне нормально читается. Фактически тот же EBNF
E>Ага, EBNF, до которого еще Вирт не добрался Вот он бы точно порадовался бы такой читабельности
E>Пусть уж лучше я прослыву ретроградом, но читабельность этого BNF оставляет желать много, много лучшего. Так что ну его нафиг, вместе с boost::spirit.
Не согласен
boost::spirit — это хорошо, особенно если придерживаться форматирования которое использует команда boost::spirit.
Здравствуйте, srggal, Вы писали:
S>Здравствуйте, Tom, Вы писали:
E>>>Если он правильно работает, то лучше его не трогать, пусть работает. E>>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.
Tom>>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда
S>Purify, etc.
Нет шансов, падения происходят только под серьёзной нагрузкой, Dev Partner или пурифай, убьёт производительность
Здравствуйте, Tom, Вы писали:
Tom>Здравствуйте, srggal, Вы писали:
S>>Здравствуйте, Tom, Вы писали:
E>>>>Если он правильно работает, то лучше его не трогать, пусть работает. E>>>>Если он работает не правильно, то лучше его выбросить и переписать все начисто.
Tom>>>Внимание вопрос! Как понять что он работает правильно и не бомбит память иногда
S>>Purify, etc. Tom>Нет шансов, падения происходят только под серьёзной нагрузкой, Dev Partner или пурифай, убьёт производительность
А если в связке с какой-нить stress utility?
Как вариант, и это тут обсуждалось — если есть подазрения на этот код — то ИМХО быстрей будет его переписать, чем протестировать
>> ME>Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.
...
ME>На gcc 3/4 с твоим кодом будет branching. Я специально затачивал эту ф-цию чтобы избавиться от branching на gcc в сервере с текстовым протоколом. Обратная ф-ция, также без branching:
А дейсвительно ли это дало большой выигрыш в общей производительности сервера? Просто инетересно, сколько %?
Здравствуйте, davenger, Вы писали:
D>Здравствуйте, MaximE, Вы писали:
>>> ME>Специально заоптимизирован чтобы не было условных переходов в сгенеренном коде.
D>...
ME>>На gcc 3/4 с твоим кодом будет branching. Я специально затачивал эту ф-цию чтобы избавиться от branching на gcc в сервере с текстовым протоколом. Обратная ф-ция, также без branching:
D>А дейсвительно ли это дало большой выигрыш в общей производительности сервера? Просто инетересно, сколько %?
Это оптимизировалось в сервере с текстовым протоколом. Парсинг занимал 50% времени обработки запроса. Вклад конкретно этой оптимизации не замерялся, в целом удалось соптимизировать парсинг на ~33%.
ME>Это оптимизировалось в сервере с текстовым протоколом. Парсинг занимал 50% времени обработки запроса. Вклад конкретно этой оптимизации не замерялся, в целом удалось соптимизировать парсинг на ~33%.
Надо наверное уже себе в подпись поставить- "бинарники рулят" и "строки — уступка человеческой сущности"
Правильно работающая программа — просто частный случай Undefined Behavior
Здравствуйте, _Winnie, Вы писали:
ME>>Это оптимизировалось в сервере с текстовым протоколом. Парсинг занимал 50% времени обработки запроса. Вклад конкретно этой оптимизации не замерялся, в целом удалось соптимизировать парсинг на ~33%.
_W>Надо наверное уже себе в подпись поставить- "бинарники рулят" и "строки — уступка человеческой сущности"
Здравствуйте, 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, Вы писали:
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.
Здравствуйте, _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-ов на разных платформах, то двоичная сериализация -- это тот еще геморрой. См., например, Универсальный код
А уж если 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++.
Я ничего не имею против теста, как промежуточного формата, до конвертации его в бинарник. (Пока его не слишком много. Часто слышу стоны "у нас 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, описал формат руками по информации из книжки.
Обрати внимание, я не использую никаких библиотек. Я использую только описание формата файла из <windows.h> или свои struct.
Я предпочитаю для работы .h файл + бинарник, чем xml + мегабайт докуметации, который объясняет что где какой тег означает. Если хранить в xml что-то отличное от "древовидно-размеченный текст с аттрибутами", то всё равно необоходим дополнительный парсинг.
шуточная Winnie::Serialization не приспособлена к разным endianess, но её легко приспособить. Просто изъять из неё понятие POD-типа и массивов POD-типов, исключая unsigned char. И честно прописать функцию сериализации uint32_t/uint32_least_t/ (с разными #ifdef для платформ).
PS. Бомбочку вроде повесил, что надо в Философию. Модераторы, вы где?
Правильно работающая программа — просто частный случай Undefined Behavior
[]
_W>Ты мог бы редактировать многомегабайтный Windows Registry File руками? _W>Windows могла бы нормально загрузится, если бы ей надо было парсить полгигабайта текста при загрузке? _W>Сразу принимаю возражения "нефиг держать всё в одном файле, если сделать много маленьких то все будет работать быстро — пример — unix" и соглашаюсь. _W>Но это ограничение и боль для разработчика. А так — "держим всё вместе и нии<sured>". И читать пачку мелких текстовых файлов медленней, чем один большой бинарный.
_W>На время загрузки OS влияет много факторов, но бинарный Registry — это +1 в копилку Windows.
[]
Здесь можно начать с того, что современным операционным системам registry не нужен, конфиг файлы редактируются в любом редакторе. Виндозе понадобился реестр чтобы обойти ограничения собственной убогой файловой системы (то же можно сказать про многие MS-технологии, как, к примеру, structured storage).
Здравствуйте, MaximE, Вы писали:
ME>Здесь можно начать с того, что современным операционным системам registry не нужен, конфиг файлы редактируются в любом редакторе.
У конфига есть проблема слияния изменений, если его двое отредактировали одну версию и сохранили по очереди.
ME>Виндозе понадобился реестр чтобы обойти ограничения собственной убогой файловой системы
Не знаю такой файловой системы, которая бы позволила эффективно хранить миллион мелких переменных (число, короткая строка).
ME> (то же можно сказать про многие MS-технологии, как, к примеру, structured storage).
Цель Structured Storage — позволить приложениям иметь документы с поддержкой вложений. Например, документ MS Word включает несколько Excel-таблиц. OLE Structured Storage позволяет работать с самим документом Word как с IStorage, так и с вложенными объектами как с IStorage. При этом сам документ Word может быть вложен, и с вложенными в него таблицами Excel может работать как с самостоятельными документами.
Разве хоть одна файловая система что-то подобное предлагает? Разве это вообще в компетенции файловой системы?
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, 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 как про страшный сон.
Здравствуйте, 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) — это пережиток прошлого, и они скоро исчезнут? Что-то сомневаюсь.
Здравствуйте, _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++.
Здравствуйте, eao197, Вы писали:
_W>>Лог файлы тоже для людей. Их тоже незападло сделать текстовыми. Даже с красивой HTML-подсветкой.
E>HTML-подсветка в логе -- это оригинально
I HaveThisPattern. Это позволяет писать в лог картинки. И на входе в каждую функцию стоит линк на возврат (и наоборот).
С другой стороны, когда HTML-лог под 15 мегабайт, а картинок в нём много, то любой браузер на нём практически дохнет. И начинаешь хотеть, чтобы он был бинарным.
Здравствуйте, Кодёнок, Вы писали:
Кё>Не знаю такой файловой системы, которая бы позволила эффективно хранить миллион мелких переменных (число, короткая строка).
Весь цимус как раз в том, что при хранении в отдельных файлах не будет миллион мелких переменных .
Ведь миллион появляется именно потому что весь хлам в реестр складывается ..
Для загрузки ОС будет достаточно несколько сотен (тысяч) переменных которые вполне быстро при стартапе прочитаются и распарсятся.
А вместе с тем и другие преимущества отдельных текстовых конфигов остаются.