Re[25]: boost - вон из профессии
От: Kluev  
Дата: 17.06.08 06:21
Оценка: +1 -1
Здравствуйте, landerhigh, Вы писали:

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


K>>качество кода это субьективный критерий. обективный критерий — это, например, производительность и по этому критерию моя функция в 45 лучше.

L>Производительность — дело десятое. Программы нынче пишутся не для компьютеров, а для программистов, не слышал? Твой код в большинстве контор не пройдет ревью, по крайней мере в качестве универсального решения, и по этому критерию он в бесконечное число раз хуже.

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

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


Об этом я и говрил, буст подходит для кусков кода которые все равно как писать. т.к. качество реализации оставляет желать лучшего

K>>Так можно вообще до абсурда дойти. Одну функцию используем с селоктом, а другую с файлами.

K>>Решение должно быть одно. Качественное и максимально быстрое. А буст не проходит по этим элементарным критериям.
L>Твое решение на качественное, извини, не тянет — оно подходит для твоего конкретного случая в вакууме и совершенно не расширяется ни на что другое. Буст или stringstream проходят по универсальности.
iostream — это вообще ошибка природы. он работает несиметрично (запихни в него строку "vasya pupkin" и попробуй потом прочесть, на входе одна строка на выходе две) и годится только для примитивного кода в стиле "все равно как написано"

L>Сделал велосипед для своего конкретного случая, устраивает по производительности — молодец. Только это не значит, что другой, более универсальный микроскоп плох только потому, что не подошел для твоих конкретных гвоздей.


Мне гораздо важнее качество реализации, чем универсальность интерфейса. Т.к. нет вообще никаких проблем чтобы сделать интерфейсную обертку по своим нуждам.
Re[26]: Читай что пишешь, что ли...
От: jazzer Россия Skype: enerjazzer
Дата: 17.06.08 06:23
Оценка:
Здравствуйте, Erop, Вы писали:

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


L>>>>Что толку от офигенно быстрого парсера, если 99% времени программа висит на select(), например?

E>Такой вывод я сделал из твоих же слов, которые я выделил полужирным шрифтом...
E>IMHO, если твоя прога занимается тем, что ждёт, пока основную работу сделает БД, то С++ тебе нафиг не упёрся. Для таких задач есть намного более эффективные средства разработки...

а если программа должна на этот select() как можно быстрее реагировать? Откуда сведения про базу данных?

маршрутизатор, например, 99% времени сидит и ждет, пока его кто-то не торкнет.
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[27]: Читай что пишешь, что ли...
От: Erop Россия  
Дата: 17.06.08 06:44
Оценка: 6 (1) +1
Здравствуйте, jazzer, Вы писали:

J>маршрутизатор, например, 99% времени сидит и ждет, пока его кто-то не торкнет.

Тогда ему должно быть не пофиг на качество реализации, однако. Я не согласен с Клюевым, что boost -- это абсолютное зло, которое должно быть предано забвению. Но согласем что во многих тамошних библиотеках плохой дизайн. Всё слишком переусложненно, и через "универсальный интерфейм реализации" сделано.
В частности, я согласен, что преобразование между текстом и числами надо делать не так, как в бусте сделано, а как-то так, как Клюев пишет.
То есть должны быть какие-то быстрые и эффекивные парсеры/распечатчики, с универсальным интерфейсом, и должен быть удобный интерфейс к этому низкому уровню. А не такой левой ногой, через правое ухо...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[28]: Читай что пишешь, что ли...
От: jazzer Россия Skype: enerjazzer
Дата: 17.06.08 06:55
Оценка: 1 (1) +1
Здравствуйте, Erop, Вы писали:

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


J>>маршрутизатор, например, 99% времени сидит и ждет, пока его кто-то не торкнет.

E>Тогда ему должно быть не пофиг на качество реализации, однако.
Ну так ты вспомни, что он писал и с чем ты споришь.
Он говорил, что ему в его задаче пофиг на качество и скорость парсинга, потмоу что он этим занимается парсингом толкьо при старте при чтении из конфига.
Но из этого не следует, ему пофиг на скорость всего остального, и тем более из этого не следует, что С++ не для его задач, как говоришь ты.

К слову, у меня точно такая же ситуация, ибо сервера.
И в основном цикле работа идет на низком уровне, потому что счет идет на микросекунды.
А вот при парсинге конфигов при старте boost::spirit и boost::lexical_cast работают со свистом, только в путь, и код крайне простой и читабельный.
И если я там начну выжимать микросекунды самописными велосипедами — начальство меня не поймет.

E>Я не согласен с Клюевым, что boost -- это абсолютное зло, которое должно быть предано забвению. Но согласем что во многих тамошних библиотеках плохой дизайн. Всё слишком переусложненно, и через "универсальный интерфейм реализации" сделано.

E>В частности, я согласен, что преобразование между текстом и числами надо делать не так, как в бусте сделано, а как-то так, как Клюев пишет.
И кто тебе (или Клюеву) мешает сделать порох непромокаемым?
Буст, вообще-то — опенсорсная библиотека.
Нашел багу — закинь патч, и все будут довольны.
Гораздо конструктивнее и полезнее для сообщества, чем тупо материться на форуме.

E>То есть должны быть какие-то быстрые и эффекивные парсеры/распечатчики, с универсальным интерфейсом, и должен быть удобный интерфейс к этому низкому уровню. А не такой левой ногой, через правое ухо...


см. выше.
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[29]: Читай что пишешь, что ли...
От: Erop Россия  
Дата: 17.06.08 07:03
Оценка: +2
Здравствуйте, jazzer, Вы писали:

J>И кто тебе (или Клюеву) мешает сделать порох непромокаемым?

Идеология... В смысле и я и Клюев и много кто ещё давным-давно пользуются непромокаемым порохом, а вовсе и не бустом. А когда высказывают фи, то в ответ ругань

J>Буст, вообще-то — опенсорсная библиотека.

J>Нашел багу — закинь патч, и все будут довольны.
J>Гораздо конструктивнее и полезнее для сообщества, чем тупо материться на форуме.
Ну вот Клюев опубликовал сорцы парсера. И что мы видим? Пишут про ревью и goto...
Как будто код из буста ревью пройдёт

E>>То есть должны быть какие-то быстрые и эффекивные парсеры/распечатчики, с универсальным интерфейсом, и должен быть удобный интерфейс к этому низкому уровню. А не такой левой ногой, через правое ухо...

J>см. выше.
см. там же.
Всё уже написано давно и опубликовано даже. Другое дело, что буст это не хорошая библиотека, а красивая и прикольная. А что прикольного в решении Клюева большинству народа не понять, IMHO. Кроме того, в таком решении ещё и нет ничего нового. Только и всего.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Вообще не понимаю, о чем разговор...
От: degor Россия  
Дата: 17.06.08 09:15
Оценка: 6 (1) :)
как можно всерьез обсуждать кусок кода, который даже собрать без геморроя нельзя? тем более такой кусок, который жрет числа вида -.A и не давится?
Re[2]: Вообще не понимаю, о чем разговор...
От: Kluev  
Дата: 17.06.08 09:34
Оценка:
Здравствуйте, degor, Вы писали:

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


Вполне можно. Ты же сам понимаешь, что велосипеды доделываются согласно потребностям, а этот код без проблем отпарзил гигабайты данных за несколько лет
и оттестирован на всех возможных use case в реальных условиях.
Re[33]: boost - вон из профессии
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.06.08 09:51
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Я вообще о сомнительной ценности выкатывания библиотек по-одиночке, если они связаны между собой.

J>Гораздо удобнее, если кто-то берет все последние версии, тестирует их на совместимость и корректность, и выкладывает единым пакетом.

J>Иначе будет как с Линуксом (безотносительно C++), когда разные программы требуют разные версии одной и той же библиотеки, и если ты случайно установишь такую библиотеку (в моем случае это libc.6, не какая-нибудь экзотика) в общую local/lib, то у тебя вдруг половина программ начинает молча падать, и если не знать заранее, в чем дело, можно очень долго просидеть и провтыкать.


J>Посмотри на pkgsrc, например — у них релизы раз в квартал, и гарантировано, что все, что в составе идет, соберется и будет работать вместе без проблем. Вот это — правильное решение проблемы, имхо, и буст, кстати, тоже стремится сделать ежеквартальные релизы (правда, пока не получается — рук не хватает).


J>А репозитории типа CPAN — они хороши для стабильных библиотек, которые уже и не меняются особо (типа Regex.Common)


Ну смотри, есть два сценария работы:

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

2. Есть единое собрание библиотек (в виде того же Boost-а), в котором зависимостей как таковых нет. Соответственно, выдергивание одной какой-то библиотеки с необходимыми зависимостями -- является задачей и ответственностью того, программиста, который на это решился.

Теперь смотрим на эти два сценария. Первый позволяет создавать единые сборки, подвергающиеся тчательному централизованному тестированию -- да. Ничего не мешает организовать где-нибудь зеркало, на котором лежат конкретные версии конкретных проектов и известно, что они протестированы совместно. Кому нужен именно такой сервис -- может спокойно брать подобный дистрибутив и нет проблем. Это напоминает Linux-овые дистрибутивы с какой-нибудь системой пакетов (вроде RPM): выходит очередная Fedora с некоторыми версиями пакетов. Но, при желании, какой-нибудь пакет можно будет заменить на более новую версию, не дожидаясь выхода очередной Fedora.

Так же первый сценарий позволяет распространять свой проект только со ссылками на другие подпроекты. Например, нужны моему проекту pcre, botan и boost::shared_ptr -- я прописываю о себя ссылки на них. Пользователь может скачать только то, что ему нужно.

А вот во втором сценарии, как мне распространять boost::shared_ptr со своей библиотекой? Либо заставлять пользователя самому качать boost (сколько там сейчас десятков мегабайт?), либо я с помощью bcp выдераю shared_ptr со товарищи из моей версии boost-а и архивирую выдернутые исходники вместе со своей библиотекой. А потом выходит новый boost и что мне делать? Выдергивать оттуда shared_ptr опять? Или вообще ничего не делать?

Манифесты подобные ситуации разруливают гораздо проще. Если моей библиотеке нужен boost::shared_ptr, то я могу прописать в манифесте:
project 'my_super_puper_lib' do |prj|
  prj.version '2.0.6', :compatible_with => '2.0'
  prj.subproject 'boost::shared_ptr', :version => '>= 1.33'
  ...
end

Если какая-нибудь очередная версия Boost-а поддерживает для shared_ptr из Boost 1.33, то там будет в свойствах проекта прописано:
project 'boost::shared_ptr' do |prj|
  prj.version '1.35', :compatible_with => '1.33'
  ...

Получается, что пользователь сможет использовать мою my_super_puper_lib как с Boost 1.33, так и с Boost 1.35. Причем я ничего со своей библиотекой не распространяю и не навязываю пользователю конкретную версию Boost-а. Не хочет человек по каким-то причинам использовать Boost 1.35 -- пусть работает с Boost 1.33 (или наоборот).

А если выходит какой-нибудь Boost 1.37, в котором shared_ptr совместим только с Boost 1.35:
project 'boost::shared_ptr' do |prj|
  prj.version '1.37', :compatible_with => '1.35'
  ...

то тут все -- my_super_puper_lib не сможет с таким Boost-ом работать и инструмент для разруливания зависимостей об этом ругнется. Тут пользователь моей библиотеки может меня пнуть и сказать: "Какого этого самого, мил человек, ты ждешь? Boost 1.37 уже на дворе, а ты все еще за 1.33 цепляешься". Только тогда я вспомню о том, что Boost как-то развивается, качну себе новую версию, портирую под нее свою библиотеку и пропишу в ней:
project 'my_super_puper_lib' do |prj|
  prj.version '2.0.7', :compatible_with => '2.0'
  prj.subproject 'boost::shared_ptr', :version => '>= 1.35'
  ...
end


Причем еще одно достоинство первого сценария: он будет работать даже для маленьких библиотек, количество пользователей которых исчисляется десятками человек, а количество загрузок -- не более сотни в год.

С помощью такой системы, странные велосипеды вроде библиотек egg или fsm, которые проходили peer review в Boost-е и набирали всего лишь около десятка отзывов, смогут спокойно жить и развиваться, бользуясь единой системой дистрибуции. Только вот в общем хранилище Boost-а их не будет, как не прошедших review, соответственно не будет для них централизованного тестирования.

Так какой сценарий тебе больше нравится?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: offtop, parse double
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.06.08 10:10
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Для ОСОБО внимательных я привел 2 имплементации одна принимает std::string другая указатель на строку и ее длина char* size.


Но при этом имея две реализации, вы передали строковый литерал туда, где ожидается std::string.
Если есть API, который принимает const std::string &, а при использовании ему подсовывают const char * (в виде таких вот литералов), то расходы на конструирование и уничтожение std::string-ов могут принимать очень серьезные размеры.

M>Если знаешь как передать std::string без его создания , поделись плз.


А во многих случаях не нужен std::string. Я подсмотрел хорошее решение в библиотеке PCRE -- там есть класс StringPiece, разработанный для C++ной обертки PCRE в Google. Я сделал из него для себя вариант. Он не такой функциональный, как Google-овский, зато у него есть шаблонные конструкторы специально для строковых литералов.

В некоторых случаях у меня замена const std::string & на const string_piece_t & ускоряло код в два раза.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Вообще не понимаю, о чем разговор...
От: degor Россия  
Дата: 17.06.08 10:24
Оценка: 10 (2)
Здравствуйте, Kluev, Вы писали:

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


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


K>Вполне можно. Ты же сам понимаешь, что велосипеды доделываются согласно потребностям, а этот код без проблем отпарзил гигабайты данных за несколько лет

K>и оттестирован на всех возможных use case в реальных условиях.

дружище, научись, наконец, понимать прочитанное. ты сделал заявку на мегабыстрый велосипед, и сравнил его с crt и бустом. при этом у широких масс нет возможности (без геморроя) изучить твое решение. ни с точки зрения правильности, ни с точки зрения производительности.

вот тебе use case: "-.A". мегавелосипед возвращает num_parse_ok,а должен возвращать num_parse_syntax.

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

но давайте будем честными перед собой, strtod() делает гораздо больше работы, чем твой велосипед. он использует локаль, проверяет специальные случаи, да и strlen() ему приходится делать в каждом цикле, а ты делаешь это только раз. и что-то я сомневаюсь, что гигабайты данных состоят сплошь из строк одного размера.

и о методике. возьми чиселки подлиннее, например, символов из 30, и увидишь, что преимущество велосипеда над crt уже не столь велико.
Re[7]: offtop, parse double
От: jazzer Россия Skype: enerjazzer
Дата: 17.06.08 10:28
Оценка:
Здравствуйте, Erop, Вы писали:

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


J>>Правда? Это какой же такой волшебный "фейлдизайн" не дал апачу сделать строки с подсчетом ссылок?


E>Например то, что неконстантный operator[] позволяет модифицировать строку...

и что, поэтому в апачевской либе его нет?
или его нет в каких-то еще строковых либах?
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[5]: offtop, parse double
От: Sergey Россия  
Дата: 17.06.08 11:06
Оценка:
eao197 пишет:

> M>Для ОСОБО внимательных я привел 2 имплементации одна принимает

> std::string другая указатель на строку и ее длина char* size.
>
> Но при этом имея две реализации, вы передали строковый литерал туда, где
> ожидается std::string.
> Если есть API, который принимает const std::string &, а при
> использовании ему подсовывают const char * (в виде таких вот литералов),
> то расходы на конструирование и уничтожение std::string-ов могут
> принимать очень серьезные размеры.
>
> M>Если знаешь как передать std::string без его создания , поделись плз.
>
> А во многих случаях не нужен std::string. Я подсмотрел хорошее решение в
> библиотеке PCRE <http://www.pcre.org> -- там есть класс StringPiece,
> разработанный для C++ной обертки PCRE в Google. Я сделал из него для
> себя вариант <http://files.rsdn.ru/31476/string_piece.hpp.html&gt;. Он не
> такой функциональный, как Google-овский, зато у него есть шаблонные
> конструкторы специально для строковых литералов.
>
> В некоторых случаях у меня замена const std::string & на const
> string_piece_t & ускоряло код в два раза.

О, а у меня почти такой же есть, из тех же соображений Только я на
паре указателей сделал, а не на указатель + длина.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[6]: offtop, parse double
От: jazzer Россия Skype: enerjazzer
Дата: 17.06.08 11:07
Оценка: +2 :)
Здравствуйте, Sergey, Вы писали:

>> В некоторых случаях у меня замена const std::string & на const

>> string_piece_t & ускоряло код в два раза.

S>О, а у меня почти такой же есть, из тех же соображений Только я на

S>паре указателей сделал, а не на указатель + длина.

я думаю, у каждого такой же есть.
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[7]: offtop, parse double
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.06.08 11:18
Оценка: +2
Здравствуйте, jazzer, Вы писали:

>>> В некоторых случаях у меня замена const std::string & на const

>>> string_piece_t & ускоряло код в два раза.

S>>О, а у меня почти такой же есть, из тех же соображений Только я на

S>>паре указателей сделал, а не на указатель + длина.

J>я думаю, у каждого такой же есть.


Возникает вопрос: почему же его нет ни в стандартной библиотеке, ни в tr1, ни в boost-е? Или где-нибудь есть?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: offtop, parse double
От: Sergey Россия  
Дата: 17.06.08 11:24
Оценка:
jazzer пишет:

>> > В некоторых случаях у меня замена const std::string & на const

>> > string_piece_t & ускоряло код в два раза.
>
> S>О, а у меня почти такой же есть, из тех же соображений Только я на
> S>паре указателей сделал, а не на указатель + длина.
>
> я думаю, у каждого такой же есть.

Возникает вопрос — а чего ж его до сих пор нет в стандарте? Ну и еще
несколько вопросов —
а) где брать шаблонные реализации strtol сотоварищи
б) какого черта до сих пор никто не умеет export template. Для таких
простейших случаев — пригождалось бы идеально.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[8]: offtop, parse double
От: jazzer Россия Skype: enerjazzer
Дата: 17.06.08 11:25
Оценка:
Здравствуйте, eao197, Вы писали:

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


>>>> В некоторых случаях у меня замена const std::string & на const

>>>> string_piece_t & ускоряло код в два раза.

S>>>О, а у меня почти такой же есть, из тех же соображений Только я на

S>>>паре указателей сделал, а не на указатель + длина.

J>>я думаю, у каждого такой же есть.


E>Возникает вопрос: почему же его нет ни в стандартной библиотеке, ни в tr1, ни в boost-е? Или где-нибудь есть?


ну, для начала, есть std::pair<const char*, const char*> и std::pair<const char*, std::size_t>, по вкусу.

а вот что еще должно быть (в сымсле, какие методы) — это вопрос открытый, потому что всем нужно разное.
У меня в разных проектах соответствующий класс имел разный набор методов, просто потому что нужно разное.

Еще есть boost::range, который выглядит как последовательность, и принимает пару итераторов. (напоминаю, что указатели сами по себе являются итераторами).
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[9]: offtop, parse double
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.06.08 11:32
Оценка: +1
Здравствуйте, jazzer, Вы писали:

E>>Возникает вопрос: почему же его нет ни в стандартной библиотеке, ни в tr1, ни в boost-е? Или где-нибудь есть?


J>ну, для начала, есть std::pair<const char*, const char*> и std::pair<const char*, std::size_t>, по вкусу.


J>а вот что еще должно быть (в сымсле, какие методы) — это вопрос открытый, потому что всем нужно разное.

J>У меня в разных проектах соответствующий класс имел разный набор методов, просто потому что нужно разное.

Вообще-то std::pair<const char*, const char*> -- это вовсе не аналог string_piece. Так как в случае string_piece прокатывают вот такие вещи:
void some_function( const string_piece_t & str ) { ... }

const char * s1 = "bla-bla-bla";
const std::string s2 = "bla-bla-bla";

some_function( s1 );
some_function( s2 );
some_function( "bla-bla-bla" );

Если заставить some_function получать std::pair, то все аргументы для some_function придется передавать ручками.

Соответственно, нужно иметь в string_piece какое-то подмножество методов из std::string (хотя бы итераторы). Ну и чтобы другие вещи в std понимали string_piece (например, конструкторы fstream, operator<< для iostreams).


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Вообще не понимаю, о чем разговор...
От: Kluev  
Дата: 17.06.08 11:52
Оценка:
Здравствуйте, degor, Вы писали:

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


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


D>вот тебе use case: "-.A". мегавелосипед возвращает num_parse_ok,а должен возвращать num_parse_syntax.

этот use case не встречается там где он используется, хотя я не отрицаю, что это ошибка.

D>но давайте будем честными перед собой, strtod() делает гораздо больше работы, чем твой велосипед. он использует локаль, проверяет специальные случаи, да и strlen() ему приходится делать в каждом цикле, а ты делаешь это только раз. и что-то я сомневаюсь, что гигабайты данных состоят сплошь из строк одного размера.


D>и о методике. возьми чиселки подлиннее, например, символов из 30, и увидишь, что преимущество велосипеда над crt уже не столь велико.

к скорости strtod у меня нет претензий. неюзабельной ее делает strlen из-за которого невозможно парзить текст большими кусками.
так же я померял на больших строках разница в 2.5 раза получается.

вот обновленный универсальный велосипед для ascii-unicode-iterator и работающий как с диапазонами строк так и с сишными строками.
errcode = parse_real(value, str_begin, RangeTerm<const char*>(str_end));
errcode = parse_real(value, str, ZeroTerm());



#pragma once

#include <float.h>

//==================================================================
template <class T>
    class NumberTraits;

//==================================================================
template <>
    class NumberTraits<double>
{
public:
    static int
        is_finite(double v)
    {
        return _finite(v);
    }
};

//==================================================================
template <class Iter>
struct RangeTerm
{
    Iter    end;

    RangeTerm(Iter e)
        : end (e)
    {
    }

    bool operator ()(Iter it)
    {
        return it == end;
    }
};

struct ZeroTerm
{
    template <class Iter>
        bool operator ()(Iter it)
    {
        return 0 == *it;
    }
};

enum
{
    NUM_PARSE_OK = 0,
    NUM_PARSE_EOF,
    NUM_PARSE_SYNTAX,
    NUM_PARSE_OVERFLOW,
};

template <class V, class Iter, class Term> int
    parse_real(V &res, Iter &p, Term eof)
{
    typedef NumberTraits<V> NT;

    V val       = 0;
    V sign      = 1;
    int esign   = 1;
    V ep;
    int    fdigits = 0;        
    bool has_ip = false;
    bool has_fp = false;

// skip space chars
    while (!eof(p))
    {
        if (' ' == *p || (*p > 0x8 && *p < 0xE))
            ++p;
        else
            goto space_ok;
    }
// eof here
    return NUM_PARSE_EOF;

space_ok: // +-.digit
    if (*p >= '0' && *p <= '9')
        goto ip_parse;

    if ('-' == *p)
        { sign = -1; goto sign_ok; }
    if ('+' == *p)
        goto sign_ok;

    if ('.' == *p)
        goto dot_ok;

    return NUM_PARSE_SYNTAX;

sign_ok: // .digit
    if (eof(++p))
        return NUM_PARSE_EOF;

    if (*p >= '0' && *p <= '9')
        goto ip_parse;

    if ('.' == *p)
        goto dot_ok;

    return NUM_PARSE_SYNTAX;

ip_parse:
    has_ip = true;
    val    = *p - '0';
    ++p;
    while(!eof(p))
    {
        if (*p >= '0' && *p <= '9')
        {
            val = val*10 + *p - '0';
            ++p;
        }
        else
            goto ip_ok;
    }
// eof here
    res = val*sign;
    return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;

ip_ok: //.eEdD
    if ('.' == *p)
        goto dot_ok;

    if ('e' == *p || 'E' == *p || 'd' == *p || 'D' == *p)
        goto ep_ok;

    if (!has_ip)
        return NUM_PARSE_SYNTAX;
    res = val*sign;
    return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;

dot_ok: // digit or eEdD
    if (eof(++p))
    {
        if (!has_ip)
            return NUM_PARSE_SYNTAX;
        res = val*sign;
        return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;
    }

    if (*p >= '0' && *p <= '9')
        goto fp_parse;

    if ('e' == *p || 'E' == *p || 'd' == *p || 'D' == *p)
        goto ep_ok;

    if (!has_ip)
        return NUM_PARSE_SYNTAX;
    res = val*sign;
    return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;

fp_parse:
    val     = val*10 + *p - '0';
    fdigits = 1;
    has_fp  = true;
    ++p;

    while(!eof(p))
    {
        if (*p >= '0' && *p <= '9')
        {
            val = val*10 + *p - '0';
            ++fdigits;
            ++p;
        }
        else
            goto fp_ok;
    }
// eof here
    res = sign*val*pow(10.,-fdigits);
    return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;

fp_ok: // eEdD
    if ('e' == *p || 'E' == *p || 'd' == *p || 'D' == *p)
        goto ep_ok;

    if (!(has_ip || has_fp))
        return NUM_PARSE_SYNTAX;
    res = sign*val*pow(10.,-fdigits);
    return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;

ep_ok: //+-digit
    if (eof(++p))
    {
        if (!(has_ip || has_fp))
            return NUM_PARSE_SYNTAX;
        res = sign*val*pow(10.,-fdigits);
        return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;
    }

    if (*p >= '0' && *p <= '9')
        goto ep_parse;

    if ('-' == *p)
        { esign = -1; goto esign_ok; }

    if ('+' == *p)
        goto esign_ok;

    return NUM_PARSE_SYNTAX;

esign_ok:
    if (eof(++p))
        return NUM_PARSE_SYNTAX;

    if (*p >= '0' && *p <= '9')
        goto ep_parse;

    return NUM_PARSE_SYNTAX;

ep_parse:
    ep = *p - '0';
    ++p;
    while (!eof(p))
    {
        if (*p >= '0' && *p <= '9')
        {
            ep = ep*10 + *p - '0';
            ++p;
        }
        else
            break;
    }

    if (ep > 1e6)
    {
        ep *= esign;
        ep -= fdigits;
        res = sign*val*pow(10., ep);
    }
    else
    {
        int iep = esign*int(ep)-fdigits;
        res = sign*val*pow(10., iep);
    }

    return NT::is_finite(res) ? NUM_PARSE_OK : NUM_PARSE_OVERFLOW;
}
Re[5]: offtop, parse double
От: night beast СССР  
Дата: 17.06.08 11:53
Оценка: 59 (2)
Здравствуйте, eao197, Вы писали:

E>А во многих случаях не нужен std::string. Я подсмотрел хорошее решение в библиотеке PCRE -- там есть класс StringPiece, разработанный для C++ной обертки PCRE в Google. Я сделал из него для себя вариант. Он не такой функциональный, как Google-овский, зато у него есть шаблонные конструкторы специально для строковых литералов.


не сочти за придирку, но строковые литералы с С++ передаются по ссылке:
      template< size_t LEN >
      string_piece_t( const char (&ptr)[ LEN ] )

хотя в данном случае сработает не-шаблонный конструктор...
Re[26]: Читай что пишешь, что ли...
От: landerhigh Пират  
Дата: 17.06.08 12:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>IMHO, если твоя прога занимается тем, что ждёт, пока основную работу сделает БД, то С++ тебе нафиг не упёрся. Для таких задач есть намного более эффективные средства разработки...

Вот именно что "читай что пишешь".
Откуда теперь даза банных взялась? И почему опять C++ не уперся?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.