11.07.2015 Views

ПРИНТЕРЫ СЕГОДНЯ - Xakep Online

ПРИНТЕРЫ СЕГОДНЯ - Xakep Online

ПРИНТЕРЫ СЕГОДНЯ - Xakep Online

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

ХАКЕР 04 /171/ 2013 Сериализация без напряга107На выходе функции save мы получим примерно такую строку:«120\n23\nsome string». Плюсы этого подхода в том, что данныеостаются сравнительно читаемыми для человека, а самареализация проста и не требует специальных знаний. А основнымминусом тут будет то, что представление структур в видестроки подойдет только для очень простых наборов данных.К тому же придется писать довольно много кода для кодированияи декодирования, а скорость его выполнения будет оставлятьжелать лучшего.Другой популярный метод — это запись данных в XML.Разнообразных библиотек, занимающихся парсингом XMLфайлов,можно насчитать великое множество, что упрощаетпроцесс написания механизмов сериализации. Данные в этомслучае представлены еще нагляднее, да и гибкость тут на высоте.Многие популярные протоколы используют этот язык разметкив качестве своей основы, так как он расширяемый и позволяетне сильно задумываться об обратной совместимостипри обновлении структуры данных. К таким протоколам можноотнести SOAP или Jabber.Но, как и в случае с предыдущим способом, чтение и запись данных в XMLформатнакладывает большие ограничения на производительность. Навигацияпо дереву неслабо нагрузит процессор, да и код все-таки тоже придетсянемного дописать, чтобы все работало так, как задумано. Еще один минус,о котором многие забывают в эпоху высокоскоростного интернета, — это размерполучаемых данных. При достаточно больших объемах информации илиплохих сетевых соединениях использовать XML не очень целесообразно.Ну и наконец, последний метод, который получил широкое распространение,— это упаковка в бинарный вид. В этом случае мы практически полностьютеряем читабельность сериализованных данных, но зато значительновыигрываем в скорости их парсинга и выходном объеме. Все бы хорошо,но в случае байтового представления информации мы получаем кучу проблемс совместимостью при изменении структур данных в программе, а такжетратим много усилий на поддержку кода упаковки и распаковки в актуальномсостоянии.PROTOCOL BUFFERS FROM GOOGLEВсе недостатки перечисленных методов призван устранить protobuf от Гугла.Protocol Buffers — это специальный метод кодирования структур данных,который позволяет быстро и без проблем сериализовать все что угодно.PB имеет официальную поддержку от Гугла для таких языков, как C++, Javaи Python. Эта поддержка выражается в наличии компилятора для специальногоязыка, описывающего структуры данных.Начать работу с сериализацией от поискового гиганта очень просто. Сперваследует описать данные в proto-файле. Представим, что мы делаем тулзу,которая работает со списком людей и номерами их кредитных карт. На языкеprotobuf требуемые структуры данных будут выглядеть примерно так:Описание данных в proto-файлеpackage CardsApp;message CardHolder {required string firstName = 1;required string lastName = 2;required int32 id = 3;}enum CardType {VISA = 0;MASTERCARD = 1;AMERICANEXPRESS = 2;}message CreditCard {required string cardNumber = 1;optional CardType type = 2 [default = VISA];}repeated CreditCard card = 4;message CardHoldersList {repeated CardHolder person = 1;}Беглый взгляд на содержимое вызовет легкое чувство дежавю у C++иJava-кодеров. И действительно, синтаксис очень похож. В начале файла находитсястрока с именем пакета. Она определяет область видимости данныхWWWОфициальный сайтProtocol Buffers:goo.gl/B4X5SДокументацияпо boost::serialization:goo.gl/fyPp2и служит для предотвращения конфликта имен. Далее следуетблок с сообщениями, которые начинаются с ключевого словаmessage. Эти конструкции являются аналогами структур в C++.Поля сообщения поддерживают такие типы данных, как bool,string, int32 и так далее. Например, поле firstName являетсястроковой переменной. В начале объявления этой переменнойнаходится ключевое слово required. Из названия нетрудно догадаться,что это поле должно быть всегда инициализировано.Всего таких спецификаторов может быть три: required, optionalи repeated. Optional говорит протобаф-компилятору, что полеможет быть не инициализировано, а repeated сообщает о возможностинеоднократного повторения переменной, описаннойс помощью этого спецификатора в структуре данных. Крометого, каждый элемент имеет так называемые таги (десятичнаяцифра после знака равно в конце объявления).В примере видно, что, помимо сообщений, мы можем определятьперечисления, а сами messages могут быть вложеныодно в другое и использоваться как пользовательские типыпри объявлении элементов других сообщений. Все это обещаетнам, простым программистам, высокую гибкость и кучу удовольствияот работы с кодом.После правильного описания используемых нами данных скормимнаш протофайл специальному компилятору. Скачать его можно по ссылкена врезке. Поскольку Google официально поддерживает целых три языкапрограммирования, то компилеру надо знать, под какой язык мы генерируемкод. Если наш файл называется cardholders.proto, то для успешного завершенияоперации командная строка будет выглядеть примерно так:protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/cardholders.protoТут стоит обратить внимание на параметр --cpp_out, именно он определяет,что мы генерируем код для C++. Заглянув в получившийся на выходеcradsapp.pb.h, можно найти много всего интересного. Заголовочный файлполучился достаточно объемный, и полный его листинг тут показать сложно,но зато без проблем можно разобраться с некоторыми его кусками.C++-код для сообщения CardHolder// firstNameinline bool has_firstName() const;inline void clear_firstName();inline const ::std::string& firstName() const;inline void set_firstName(const ::std::string& value);inline void set_firstName(const char* value);inline ::std::string* mutable_firstName();// lastNameinline bool has_lastName() const;inline void clear_lastName();inline const ::std::string& lastName() const;inline void set_lastName(const ::std::string& value);inline void set_lastName(const char* value);inline ::std::string* mutable_lastName();// idinline bool has_id() const;inline void clear_id();inline int32_t id() const;inline void set_id(int32_t value);// cardinline int card_size() const;inline void clear_card();inline const ::google::protobuf::RepeatedPtrField& card() const;inline ::google::protobuf::RepeatedPtrField* mutable_card();inline const ::CardsApp::CardHolder_CreditCard&card(int index) const;inline ::CardsApp::CardHolder_CreditCard*mutable_card(int index);inline ::CardsApp::CardHolder_CreditCard*add_card();

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!