четверг, 24 мая 2012 г.

Унификация Ansi-Unicode-правил

В предыдущей статье такое приведение правил ANSI-UNICODE я уже делал. Теперь я хочу показать, к чему это все привело.

Для начала стоит отметить, что с переходом на vs2010 макросы уже не принимают отсутствие каких-либо идентификаторов между запятыми. Следовательно, набор этих правил приходится адаптировать.

Я посчитал нужным ввести некоторые обозначения трансляции:

u - основной признак трансляции (unicode)
l - задан только левый фрагмент текста трансляции (left)
r - задан  только правый фрагмент текста трансляции (right)
t - трансляция шаблона или какой-либо его специализации (template)
a - задан только ANSI-фрагмент (ansi)
u - задан только UNICODE-фрагмент (unicode) [да, все верно, еще один u]

таким образом, мы можем сформировать общий набор правил трансляции:
#ifndef UNICODE
  #define u( left, right, ansi, unicode ) left ## ansi ## right
  #define ua( left, right, ansi )  left ## ansi ## right
  #define uu( left, right, unicode )  left ## right
  #define ul( left, ansi, unicode )  left ## ansi
  #define ula( left, ansi )   left ## ansi
  #define ulu( left, unicode )   left
  #define ur( right, ansi, unicode )  ansi ## right
  #define ura( right, ansi )   ansi ## right
  #define uru( right, unicode )   right

  #define ut( left, right, ansi, unicode, ... ) left ## ansi ## right < __VA_ARGS__ >
  #define uta( left, right, ansi, ... )  left ## ansi ## right < __VA_ARGS__ >
  #define utu( left, right, unicode, ... ) left ## right < __VA_ARGS__ >
  #define utl( left, ansi, unicode, ... ) left ## ansi < __VA_ARGS__ >
  #define utla( left, ansi, ... )  left ## ansi < __VA_ARGS__ >
  #define utlu( left, unicode, ... )  left < __VA_ARGS__ >
  #define utr( right, ansi, unicode, ... ) ansi ## right < __VA_ARGS__ >
  #define utra( right, ansi, ... )  ansi ## right < __VA_ARGS__ >
  #define utru( right, unicode, ... )  right < __VA_ARGS__ >
#else
  #define u( left, right, ansi, unicode ) left ## unicode ## right
  #define ua( left, right, ansi )  left ## right
  #define uu( left, right, unicode )  left ## unicode ## right
  #define ul( left, ansi, unicode )  left ## unicode
  #define ula( left, ansi )   left
  #define ulu( left, unicode )   left ## unicode
  #define ur( right, ansi, unicode )  unicode ## right
  #define ura( right, ansi )   right
  #define uru( right, unicode )   unicode ## right

  #define ut( left, right, ansi, unicode, ... ) left ## unicode ## right < __VA_ARGS__ >
  #define uta( left, right, ansi, ... )  left ## right < __VA_ARGS__ >
  #define utu( left, right, unicode, ... ) left ## unicode ## right < __VA_ARGS__ >
  #define utl( left, ansi, unicode, ... ) left ## unicode < __VA_ARGS__ >
  #define utla( left, ansi, ... )  left < __VA_ARGS__ >
  #define utlu( left, unicode, ... )  left ## unicode < __VA_ARGS__ >
  #define utr( right, ansi, unicode, ... ) unicode ## right < __VA_ARGS__ >
  #define utra( right, ansi, ... )  right < __VA_ARGS__ >
  #define utru( right, unicode, ... )  unicode ## right < __VA_ARGS__ >
#endif
каждый макрос очень просто расшифровывается, а набор их параметров следует строго из названия, например:

uru() - добавить UNICODE-префикс, т.е. имеем правую часть какого-то текста, к которой слева нужно добавить  UNICODE-фрагмент, для ANSI текст оставить без левой части, например:
uru( CHAR, W ); //транслирует CHAR и WCHAR;
uru( "текст", L ); //транслирует "текст" и L"текст", неожиданно, да? :))
ul() - добавить соответствующий кодировке постфикс, т.е. имеем левую часть какого-то текста, к которой нужно добавить фрагмент справа, например:
ul( SendMessage, A, W ); //транслирует SendMessageA и SendMessageW
ul( LOGFONT, A, W ); //транслирует LOGFONTA и LOGFONTW
ur() - добавить соответствующий кодировке префикс, т.е. имеем правую часть какого-то текста, к которой нужно добавить фрагмент слева, например:
ur( len, str, wcs ); //транслирует strlen и wcslen
uu() - добавить UNICODE-инфикс, т.е. имеем левую и правую части какого-то текста, между которыми нужно добавить фрагмент, например:
uu(  _sc, printf, w ); //транслирует _scprintf  и _scwprintf 
uu( _, icmp, str, wcs ); //транслирует _stricmp и _wcsicmp
ввод шаблонов в эти правила, с точки зрения грамматики не требуется, но особенности реализации редакторов исходного кода в visual studio пока не могут полноценно раскрывать код внутри макроса, поэтому при их использовании в шаблонах, ломается сode folding

предотвратить его поломку помогут макросы с модификатором t ( ut, utru, utl и т.п. )

utl() - аналог ul только с возможностью добавления параметров шаблона, например:
utl( MyClass, A, W, X, Y, Z ); //транслирует MyClassA и MyClassW< X, Y, Z >
На самом деле, я уже достаточно долго работаю с этим инструментом и успел оценить его плюсы и минусы, а чтобы в дальнейшем, при встрече с такими u-макросами можно было предметно обсуждать насущные темы, я буду обращаться к ним с помощью простой и, на мой взгляд, очевидной терминологии: u-логика или u-макрос

Комментариев нет:

Отправить комментарий