Количество байтов и количество символов - PullRequest
0 голосов
/ 28 января 2011

Для некоторых API требуется количество символов.

// Why did they choose cch in these functions.
HRESULT StringCchCopyW(
  __out  LPWSTR pszDest,
  __in   size_t cchDest,
  __in   LPCWSTR pszSrc
);

errno_t wcscpy_s(
   wchar_t *strDestination,
   size_t numberOfElements,
   const wchar_t *strSource 
);

DWORD WINAPI GetCurrentDirectoryW(
  __in   DWORD nBufferLength, // Count of Chars
  __out  LPWSTR lpBuffer
);  

И для некоторых API требуется количество байтов.

// What do you prefer cch vs cb function.
// Do cch functions almost useful?
HRESULT StringCbCopyW(
  __out  LPWSTR pszDest,
  __in   size_t cbDest,
  __in   LPCWSTR pszSrc
);

BOOL WINAPI ReadFile(
  __in         HANDLE hFile,
  __out        LPVOID lpBuffer,
  __in         DWORD nNumberOfBytesToRead,
  __out_opt    LPDWORD lpNumberOfBytesRead,
  __inout_opt  LPOVERLAPPED lpOverlapped
);

// Why did they choose cb in these structures.
// Because there are some apis uses cb, I always should see MSDN.
typedef struct _LSA_UNICODE_STRING {
  USHORT Length; // Count of bytes.
  USHORT MaximumLength; // Count of bytes.
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _FILE_RENAME_INFO {
  BOOL   ReplaceIfExists;
  HANDLE RootDirectory;
  DWORD  FileNameLength; // Count of bytes.
  WCHAR  FileName[1];
} FILE_RENAME_INFO, *PFILE_RENAME_INFO;

Когда выспроектировать функцию или структуру данных, как вы определяете cb или cch?И почему?
Чтобы лучше написать API для вызывающего абонента, что я должен знать об этом?

Ответы [ 2 ]

3 голосов
/ 28 января 2011

Если возвращаемые данные являются строкой, вы должны вернуть количество символов, так как количество байтов часто бесполезно. Но если это общие двоичные данные (а не конкретно строка), то, очевидно, количество символов не имеет никакого смысла, поэтому используйте количество байтов.

Почему:

Я считаю, что причина для LSA_UNICODE_STRING хранения количества байтов заключается в том, что он должен быть совместим с UNICODE_STRING, который, в свою очередь, используется в NtCreateFile . Но NtCreateFile принимает параметр FILE_OPEN_BY_FILE_ID, который на самом деле обрабатывает UNICODE_STRING, чтобы он указывал на значение LONGLONG, а не строку ... так что количество байтов имело больше смысла , хотя я бы сказал, что это в целом плохой дизайн:

FILE_OPEN_BY_FILE_ID: имя файла, указанное параметром ObjectAttributes, включает 8-байтовый номер ссылки на файл для файла.

0 голосов
/ 28 января 2011

Если вы заметили, первая группа функций, которую вы упомянули, это все функции ASCII, и поэтому в этом случае нет никакой разницы - количество байтов - это количество символов. Это потому, что (как правило, в любом случае) один символ ASCII имеет размер только один байт.

Вторая группа - это функции / структуры Юникода. В этом случае символы не гарантированно будут иметь размер только один байт - если в формате UTF16 они будут иметь ширину в два байта, в UTF32 их будет четыре, а в UTF8 они (как правило) будут где-то от ширина от одного до четырех байтов.

В частности, в случае данных UTF8, если вы создаете буфер, обычно вы откладываете определенное количество байт , которое в зависимости от размеров символов может быть весьма разнообразным по количеству символов. Я не слишком знаком с большинством представленных вами функций / структур, но меня не удивит, если это как-то связано с этим.

Чтобы ответить на ваш вопрос, если вы работаете с ASCII, вы можете использовать любой из этих подходов - без разницы. Однако, если вы работаете с кодировками переменной длины (такими как UTF8), то, используете ли вы один или другой, зависит от того, заинтересованы ли вы только в задействованных символах, или вам также необходимо учитывать их кодировку.

...