Приложения
Приложение А. Функции, константы и структуры RDS
А.1. Типы параметров
А.1.3. Строковые поля в служебных структурах
В отличие от первой версии RDS, где все строки хранились в кодировке CP1251, во второй версии везде используется кодировка UTF8. Однако, в функциях и структурах Windows API применяется кодировка UTF16, поэтому во всех служебных структурах RDS с именами вида RDS_*, содержащих поля-указатели на строки, эти поля удвоены: поле с суффиксом «A» содержит указатель на строку в UTF8, а поле с суффиксом «W» – на строку в UTF16. Таким образом, программист может выбрать, с какой кодировкой ему удобнее работать.
Рассмотрим условную структуру с полем-строкой «sField». Если бы не необходимость в двойной кодировке, она выглядела бы следующим образом:
typedef struct { int iField; // Целое поле const char *sField; // Строка } RDS_STRINGSTRUCT;
Если сейчас не рассматривать анонимные объединения для выравнивания полей, то в RDS эта структура будет выглядеть так:
typedef struct { int iField; // Целое поле const char *sFieldA; // Строка в UTF8 const wchar_t *sFieldW; // Строка в UTF16 } RDS_STRINGSTRUCT;
Строковое поле «sField» заменено двумя: «sFieldA» для строки в UTF8 и «sFieldW» для строки в UTF16 (в программах для Windows тип wchar_t* описывает строку в UTF16). Принцип работы с этими новыми полями следующий:
- если структура заполняется в RDS и передается в модель блока при вызове (например, RDS_BLOCKDATA, RDS_NETCONNDATA и т.п.), то в переданной структуре всегда будут заполнены оба поля (они будут содержать указатели на одну и ту же строку в разных кодировках), и программист модели может считывать любое из них;
- если указатель на пустую структуру передается в RDS для ее заполнения какими-либо описаниями (например, RDS_BLOCKDESCRIPTION, RDS_CONNDESCRIPTION и т.п.), то в структуре тоже всегда будут заполнены оба поля;
- если структура заполняется какими-либо данными в модели, а потом вызывается сервисная функция для передачи этих данных в RDS (например, для этого может использоваться структура RDS_SERVFONTPARAMS), то программист модели перед вызовом должен заполнить в структуре поля, соответствующие суффиксу вызываемой функции (как и функции с параметрами-строками, функции с параметрами-структурами тоже могут иметь суффиксы «A» и «W», если в этих структурах есть «двойные» строковые поля).
Таким образом, на стороне RDS в структурах всегда заполняются оба поля, а на стороне модели следует заполнять поле, соответствующее версии вызываемой функции.
Для сохранения совместимости с первой версией RDS, где строковые поля не имели суффиксов, а также для того, чтобы, при желании, можно было использовать имя поля и без суффикса для доступа к строке с кодировкой по умолчанию, для строковых полей структур введены псевдонимы, совпадающие с названиями соответствующих полей в структурах версии RDS 1.x. Псевдонимы введены через анонимные объединения (union), в которые, в зависимости от наличия описаний констант RDS_NO_UTFALIASES и RDS_UTF16DEFAULT, вводятся дополнительные поля со старым именем. В объединениях все поля находятся по одному и тому же адресу, поэтому, если объединение содержит два поля одного и того же типа, их имена полностью взаимозаменяемы.
Рассмотренная выше условная структура RDS_STRINGSTRUCT с псевдонимом для поля sField выглядит примерно так (реальное описание отличается наличием дополнительных служебных полей для выравнивания):
typedef struct { int iField; // Целое поле union { const char *sFieldA; // Строка в UTF8 #if (!defined(RDS_NO_UTFALIASES)) && (!defined(RDS_UTF16DEFAULT)) const char *sField; // Псевдоним #endif }; union { const wchar_t *sFieldW; // Строка в UTF16 #if (!defined(RDS_NO_UTFALIASES)) && defined(RDS_UTF16DEFAULT) const wchar_t *sField;// Псевдоним #endif }; } RDS_STRINGSTRUCT;
Макроопределения констант RDS_NO_UTFALIASES и RDS_UTF16DEFAULT управляют описанием «псевдонимов» для полей структур и функций с параметрами-строками. Команды #define для них следует помещать в исходный текст модели перед включением файлов «RdsDef.h» и «RdsFunc.h».
Если программист хочет по имени без суффикса «sField» обращаться к полю, содержащему строку в кодировке UTF8, то перед включением заголовков RDS никаких констант описывать не нужно:
#include <RdsDef.h> #include <RdsFunc.h> … RDS_STRINGSTRUCT a; a.sField="1234";
Если программист хочет, чтобы имя «sField» давало доступ к строке в кодировке UTF16, то перед включением заголовков RDS сдедует описать константу RDS_UTF16DEFAULT:
#define RDS_UTF16DEFAULT #include <RdsDef.h> #include <RdsFunc.h> … RDS_STRINGSTRUCT a; a.sField=L"1234";
(здесь префикс «L» перед строкой в кавычках указывает на то, что это строка в «расширенной» кодировке, т.е. в UTF16 при компиляции для Windows).
Если же программист вообще не хочет использовать псевдонимы полей, то перед включением заголовков RDS следует описать константу RDS_NO_UTFALIASES:
#define RDS_NO_UTFALIASES #include <RdsDef.h> #include <RdsFunc.h> … RDS_STRINGSTRUCT a; a.sFieldA="1234"; a.sFieldW=L"1234";
Разумеется, имена полей с суффиксами «A» и «W» доступны всегда, независимо от описаний RDS_NO_UTFALIASES и RDS_UTF16DEFAULT.