Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 229
Текст из файла (страница 229)
Он позволяет писать программы, использующие удобные внутренние представления символов (в виде сйаг, нсйаг !и т.п.), и воспринимающие различные представления символов потока посредством управления контекстом их локализации. Альтернативой была бы необходимость изменения самой программы или необходимость в промежуточных переконвертациях файлов при их чтении и записи. Приложение О.
Локализация 1068 Фасет со<!есг< обеспечивает преобразования между различными наборами символов, когда символ перемещается между буфером потока и внешним хранилищем: с1ат зЫ«со«есг< Ьазе ( риЬЕс< епит гезий (ой,рог<!а<, етог, посопг); )1 // индикаторы результата <етр<а<е<с1азз 1, с1азз Е, сй<зз $<а<е> ей<аз зЫ: <содесг(< риЬЕс !оса<в::/осе<, риЫ<с со«есг< Ьазе ( риЫ<с: <уре<!е~! т<егп <уре< <уре«е3' е ех<егп <уре< <уре«е! Бте з<а<е 1уре< ехр!<с<1 содест (з!зе < г = О) 1 гезий!и (Я<иге ь, сопл< Е* 3гот, сопл< Е"3гот еп«, сопл< Е* ь угот пех<, // нтение 1* <о, 1* т еп«, 1*ь <о пех<) соил<1 гезий он<(Я<а<еь, сопл<1*агат, сопт1*агат ецио, соли!*ь/гот пех<, //запись Е* <о, Е* <о еп<!, Е*Ь <о пех<) сопл<1 гезий ипзй(й(Б<о<еь, Е* <о, Е* (о еи«, Е*ь <о пел<) сопл<; т< епсойпе () сопи( йгоп(); //свойства перекодирования Ьоо< а!<гауз посопг () соим йгон ( ) 1 //можно вьтолнять ввод/вывод без трансляции? <и<!вязей(соптЯ~а<еь, соитЕ* <гот, сопз<Е*/гот епд, з!зе <тах) сопл<1 1п< тах 1еиа<й () соил« йго<г() 1 з<абс !оса<в::!<!Ы< /объект идентификации фасета !3Р.2, зР.3, зР.3.!) рго<ес<е«: -со<!есг< ( ); // виртуальные л!о "-функции !см.
3Р.4!) )1 с1азз 3!Бег«риЫ(с содесг<«гсйаг <, сйаг, тЬз<а<е <> ( /*...*/) 1 Фасет со<!есз< используется Ьаз!с Щейи!'(521.5) для чтения или записи символов. Этот фасет Ьаз!с й!ейи!'получает из контекста локализации потока (В21.7.1). Аргумент шаблона Ьта<е является типом, который используется длл хранения состояния сдвига подлежашего конвертированию потока. Кроме того, Я<иге можно использовать для идентификации различных преобразований путем уточняющих специализаций. Последний механизм полезен, поскольку символы разнообразных кодировок могут храниться в объектах одного и того же типа.
Например: с1ат ЛЯз<а<е ( / * .. * / ) 1 р = ие<г со«есг<«гсйаг 1, сйаг, тЬта<е <>1 //стандаргпный сйаг в <зсйаг 1 ц = пе<г содесге<псйаг 1, сйаг, 31Бз<а<е>/ //Ло в <зсйаг 1 Без аргумента Я<иге не существовало бы способа сообшить фасету, в какой кодировке воспринимать поток символов сйаг. Тип тЬз<а<е <из <си сйаг> или <псйаг й> идентифицирует стандартное системное преобразование между сйаг и псйаг 1. Можно также создать новый вариант со<!есз< в качестве производного класса. Например: 0.4. Стандартные фасеты 1069 Вызов !л(з,!)ттт,1гот елИ,1гот яехг,го,ю ела,го яехт) читает каждый символ из интервала Яояг,13втя ея4 и пытается преобразовать его.
Если символ удается преобразовать, ш () записывает его преобразованную форму в соответствукицую позицию интервала (га, го ела); если не удается — 1я() завершает на этом свое выполнение. По завершении, 1я() сохраняет ввозя леха позицию за последним прочитанным символом, а в го яехг — позицию за последним записанным символом.
Значение геи1г, возвращаемое функцией 1я (), индицирует выполненный объем работы: о)г: преобразованы все символы из интервала (!~от,Я"от еяИ). раМа1: преобразованы не все символы из интервала (ггоя), Ггот еяН) . еггогк) функция 1я() встретила символ, который не смогла преобразовать. юсоягс не потребовалось преобразований. Заметьте, что возврат раМа! не обязательно свидетельствует об ошибке. Возможно, просто нужно прочесть больше символов для завершения многобайтного символа с последующей его записью, или нужно очистить выходной буфер, чтобы в нем оказалось достаточно места для приема символов.
Аргумент з типа агате индицирует состояние входной последовательности символов в момент вызова функции и(). Это важно для случаев, когда внешнее представление символов использует состояние сдвига (з))(1( ма(е). Обратите внимание на то, что з является неконстантной ссылкой; под конец вызова з содержит состояние сдвига входной последовательности. Это позволяет программисту работать с раМа1-результатом преобразований и конвертировать длинные последовательности посредством нескольких вызовов функции !я () . Вызов оаг(а,1гот,1гот епт1,!гот лехб го, ю еит1, га пехг) преобразует (ггот, 1гоят еят!) из внутреннего представление во внешнее так же, как 1я () преобразует из внешнего представления во внутреннее. Поток символов должен начинаться и заканчиваться в нейтральном» состоянии (без сдвига — цпзЫйе() ыа(е). Как правило, это состояние агагеО.
Вызов ипзЫгг(з, го, го еиИ, го иехй анализирует з и помешает символы в (го, го ее!) таким образом, что последовательность символов возвращается в нейтральное состояние. Возврат иязя()т() и использование аргумента го яехг вполне аналогичны таковым для функции оиг() . Вызов !еяяг1т(з,1гот,1гот еяй,птах) возврашает число символов из (1)от, !гоят еяИ), которое функция 1я () может преобразовать. Функция епса11яй О возвращает: ° — 1 — если внешнее представление символов использует состояние (есть сдвиг, нет сдвига) ° 0 — если кодировка символов использует переменное число байт (например, отдельный бит может сообшать о том, один или два байта отводятся под символ) ° я — если каждый символ во внешнем представлении занимает и байт Вызов а1юауз яоеояг() возвращает ггие, если не требуется преобразований между внутренним и внешним представлениями символов, и возврашает !а!хе в противном случае.
Ясно, что а1юауз посоле() ==ггие открывает возможность максимально эффективной реализации, которая просто не вызывает функции преобразования. 1070 Приложение (). Локализация Вызов шах !еийтй ( ) возврашает максимальное значение, которое может вернуть 1епатй ( ) при корректных аргументах. Простейшее преобразование кодировок, которое я смог придумать, это преобразование входных символов в верхний регистр. Так что ниже представлен возможно простейший вариант со<(ест<, который выполняет все-таки некоторую работу: с1азз С» со иррег: риЫ<с со<<ест«сйат,сйаг,тйз<а<е г> ( ехрдсс< С» <о иррег(<<се с г = 0) с со«ест<(г) () ргосессес<: <У читает внешнее представление - пишет внутреннее: тези1< <<о ш(3<а<ей з, сола< сйаг*(тот, сола< сйат*!тот еп«, соим сйаг*ь <тот пах<, сйаг* <о, сйаг* <о епс<, сйаг" й <о пех<) солсас 1 читает внутреннее представление - лиисет внесинеес гезий с<о ош(Я<асей з, солз< сйагч !тот, сои<< сйаг* !тот ел<1, солт сйаг*ь !тот иехс, сйаг* <о, сйаг* со еи«, сйаг*ь со лен<) солт ( ге<иги соИест«сйаг, сйаг, тйзы<е <> с <<<о ои< (з,Яот,!тот еп«,!тот иех«, о, <о ел«, <о пех<) гезий ссо илзйсс<(Я<асей, е* <о, е* ш ел<<, е*й <о пех<) солт< (ге<игл ойс ) ш«<о елсос<1лд() соли( сйгон () (ге<игл 1< ) Ьоо< с<о ай<ау< посоли() солз< <Его»() (те<игл!а<вес) ш< с<о 1епд<й (сола< Я<асей, сои<< Е*утот, солз< Е*<гот ел«, <<се < тах) солт; ш«<о тах !епйвй () сои<<<Его»() с )с сойест«сйаг, сйаг, тЬзиие <> с: гезий С» <о иррег::<Со 1п (Е<а<ей з, солса сйаг*!тот, саин< сйат*!тот епИ, сои<< сйаг*ь !тот пенс, сйат* <о, сйаг* со еп«, сйаг*ь со лекс) санса У...
~Я).б(!б/ ... ) !л< таси () У тривиасьный тест 1оса1е и!ока!е(1оса1е(), пе» Ст< со иррег) с<и . ииЬие (и<оса1е) сйаг ей с сгйИе(с1и»сй) соис «сйс ) Для со<!ест< имеется и Ьупате-версия Цс>.4, 5Р.4.)): <етр!а<е<с1ат 1, с!аз< Е, с!аз< К<а<в> с<ат зМ::соИес» Ьулате: риЫ<с со<<ест<<1,Е,К~а<в> (/*...*/) с с).4. Стандартные фасеты зоу1 юу.4.7.
Сообщения Неудивительно, что большинство пользователей предпочитает взаимодействовать с программой на своем родном языке. Однако мы не можем обеспечить универсальный стандартный механизм взаимодействия с программой в точном соответствии с контекстом локализации. Вместо этого, стандартная библиотека предоставляет нехитрый механизм хранения зависящих от локализации строк, из которых программист может составлять простые сообщения. По существу, класс теяяаяея (сообщения) реализует тривиальную базу данных, доступную только для чтения: е1ат яЫ: ."тетенек Ьаяе риЫюс: (урежет'1пю саюа1ояю р тин идентификаюнора каталога )ю юеюпр!аюе<сЫт СЬ> е1аяя яЫ:: тетаяея ю риЫ(е!оса(е ю ю/асею, риЫ!е теяяаяея Ьаяе ( риЫюс: юурею(е!' Сй еааю туре! юуреютеу Ьаяюе яюгюпе<СЬ> яюг(пе юурею екр!!ей теяяаеея (я(яе ю г = О) ю еаюа(ое орел (сопя! Ьаяк яюгтя<еааг>я)п, сопя! 1оеа(еа) сопя!! яюйпя туре ее!(еаюа!ое с, шю яею, шю тяеЫ, сопя! яюг(пе юуреа И) еопяюю »оЫ с(ояе (еаюа1ое с) еопм; яюаие 1оеа(е::Ы Ы; УУ объект идентификации фаеета Д1).2, я1>З, я1Э.З.1) ргоюесюею1 ю -тетаяея () ' УУеиртуолнные юто "-функции (си.
З1).4.1) )ю Вызов орел (я, 1ос) открывает «каталог» сообщений я для контекста локализации 1ос. Каталог — это набор строк, организованных зависящим от реализации способом и доступных посредством функции теяяаяея: юле!О. Если открыть каталог с именем я не удается, то возвращается отрицательное значение. Каталог должен быть открыт до первого вызова функции яею() . Вызов с1ояе(саю) закрывает каталог, идентифицируемый посредством саю, и освобождает все связанные с ним ресурсы.