Эта история произошла почти месяц назад. Постучал ко мне в скайп некий Егор.
Егор: Здравствуйте, фрилансеров ищите?)
Я: А вы что умеете?
Егор: А мы, собственно, толком ничего не умеем и хотим работать за опыт.)
Егор оказался неплохо подкованным пареньком и я предложил ему потестировать нашу либу cjCore.
Надо пояснить, что это такое. На гитхабе у нас есть репозиторий, куда мы сваливаем свои наработки, а cjCore — это одна из наших библиотек на C++.
Егор клонировал себе либу и попытался её скомпилировать, но не тут-то было. У него возникли проблемы с компиляцией нашей юникодной String.
Как известно, в стандартном С++ нет нормальных юникодных строк и поэтому многие пишут для этого свои классы. Например, в Qt написана своя QString на базе библиотеки ICU. И мы тоже решили написать свою строчку, но стали использовать не ICU, а библиотеку Boost или C++11 на выбор, кому что нравится больше.
У Егора последняя версия Ubuntu, но по какой-то причине, у него строка из C++11 компилироваться не захотела, а тянуть Boost только ради какой-то строчки он посчитал делом слишком накладным (попутно пожаловавшись на слабенький интернет) и решил использовать свободную библиотеку, в конце концов он остановился на utfcpp.sourceforge.net.
Нахрапом взять эту библиотеку Егору не удалось. Он постоянно мне скидывал возникающие ошибки, я что-то подсказывал, но постоянно что-то у него не получалось…
Тем временем я зашёл в Википедию: ru.wikipedia.org/wiki/UTF-8 и нашел там интересную табличку «Конвертирование в UTF-8»:
И тут ко мне приходит безумная мысль: написать функции преобразования UTF-8 -> UTF-32 и обратно чистым кодом, без всяких библиотек!
Я: Сейчас я кое-что скину, если у меня получится
Егор: Ок
Никаких тяжёлых операций, только проверка условий, сложение и операции с битами, 40 минут и готово!
Я: Для чего нужны либы? Чтобы быстренько своё сваял и всё работает: github.com/sitev/cjCore/blob/master/src/test_utf32to8.cpp
Егор: А обратно?
Я: Помню, сколько времени потребовалось, чтобы разобраться с кодировками в с++11 и бусте, наверное, неделя
Ещё минут 30-40 и заработала обратная конвертация.
Егор взялся за тестирование и через какое-то время скинул скриншот:
Я: Типа пашет?
Егор: Не типа, а пашет: 1 строчка — исходная, 2 строчка — UTF-32, 3 строчка — из UTF-32 в UTF-8.
Спасибо Егору, он оптимизировал получившийся код, а я его обернул в виде класса Utf: github.com/sitev/cjCore/blob/master/src/utf.cpp и попросил Егора протестировать быстродействие.
Результат не заставил себя ждать, скорость в 2-2.5 раза быстрее, чем utfcpp.sourceforge.net! К сожалению, сравнить по скорости с другими библиотеками, у нас не нашлось времени, а попробуйте сами и выложите результаты в комментариях.
Как оказалось, процесс программирования перекодировки Юникода туда-обратно очень увлекательный, заставляет с горящими глазами и учащенным сердцем быстро-быстро стучать по клавишам…
Автор: sitev_ru