понедельник, января 25, 2010

Ужасы… Windows Platform SDK

Пользовался Windows Platform SDK for Windows Vista.  Желая иметь самую свежую документацию скачал новый Windows SDK for Windows 7 and .NET Framework 3.5 Service Pack 1 (Build date: 6/11/2009).  Ужас. Смотрим статью о WideCharToMultiByte:

Список кодовых страниц для которых флаги и некоторые параметры должны быть нулевыми.

Список из нового SDK:

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 57002 through 57011
  • 65000 (UTF-7)
  • 42 (Symbol)

А вот страницы из прежнего SDK:

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 52936
  • 54936
  • 57002 through 57011
  • 65000 (UTF7)
  • 42 (Symbol)

 

Как видим, из нового SDK исчезло упоминание страницы 52936 (54936 упоминается в документации дополнительно). Здравствуйте, грабли!

Теперь сравните описания параметров.

Новый SDK:

lpDefaultChar [in]

Optional. Pointer to the character to use if a character cannot be represented in the specified code page. The application sets this parameter to NULL if the function is to use a system default value. To obtain the system default character, the application can call the GetCPInfo or GetCPInfoEx function.

For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

lpUsedDefaultChar [out]

Optional. Pointer to a flag that indicates if the function has used a default character in the conversion. The flag is set to TRUE if one or more characters in the source string cannot be represented in the specified code page. Otherwise, the flag is set to FALSE. This parameter can be set to NULL.

For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

И прежний SDK:

lpDefaultChar

[in] Pointer to the character to use if a wide character cannot be represented in the specified code page. The application sets this parameter to a null pointer if the function is to use a system default value. To obtain the system default character, the application can call the GetCPInfo or GetCPInfoEx function.

For the code pages listed for dwFlags, this parameter must be set to a null pointer. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

lpUsedDefaultChar
[in] Pointer to a flag that indicates if the function is to use a default character in the conversion. The flag is set to TRUE if a default character is necessary, and to FALSE otherwise. This parameter can be set to a null pointer.

For the code pages mentioned in dwFlags, lpUsedDefaultChar must be a null pointer. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

Нужно ли говорить, что информация в новом SDK не соответствует действительности. Здравствуйте, еще одни грабли! Ужас… Как можно верить такой доке? Остается только проверять.

суббота, октября 31, 2009

Delphi 2010. Быдлокод

Юнит DBXJSON.pas. Я вообще в ауте...

class function TJSONString.Hex(const Digit: Integer): Byte;
var
HexData: TBytes;
begin
SetLength(HexData,16);
HexData[0] := Ord('0');
HexData[1] := Ord('1');
HexData[2] := Ord('2');
HexData[3] := Ord('3');
HexData[4] := Ord('4');
HexData[5] := Ord('5');
HexData[6] := Ord('6');
HexData[7] := Ord('7');
HexData[8] := Ord('8');
HexData[9] := Ord('9');
HexData[10] := Ord('A');
HexData[11] := Ord('B');
HexData[12] := Ord('C');
HexData[13] := Ord('D');
HexData[14] := Ord('E');
HexData[15] := Ord('F');
Result := HexData[Digit];
end;

вторник, октября 20, 2009

Delphi 2010. System.TObject.GetInterface

Полюбуйтесь на код обеспечивающий проверку идентификатора интерфейса на соответствие "magic GUID" ({CEDF24DE-80A4-447D-8C75-EB871DC121FD}), для безопасного кастинга (TMyObject(TMyIntf)) к объектому типу:

if (Int64(ObjCastGUID.D1) = Int64(IID.D1)) and
(Int64(ObjCastGUID.D4) = Int64(IID.D4)) then
Pointer(Obj) := Self;

И это в системном юните... #78808

вторник, мая 26, 2009

Ubuntu 9.04

Четыре дня назад получил по почте новую версию Ubuntu. Итог: оно все лучше и лучше. Несмотря на то, что чего-то не срослось с wubi общие впечатления самые положительные. Очень порадовала, сразу бросившаяся в глаза, качественная настройка саб-пиксельного сглаживания шрифтов. Им бы еще иконки отдизайнить в какой-нибудь конторе, чтоб в едином стиле, да в Гноме немного уменьшить контролы. В общем, мне понравилось :)

воскресенье, мая 17, 2009

#72213 Fixed

На фикс такой очевидной ошибки компилятора потребовалось два месяца... Страшно подумать сколько будут фиксить некорректную инициализацию/финализацию advanced-records, на которую налететь не так просто :( Вот и юзай новые языковые фичи...

вторник, апреля 28, 2009

Три класса секундомеров

Выложен модуль Common.Classes.pas содержащий три класса (advanced-records) секундомеров. TLowResStopwatch на основе GetTickCount, THighResStopwatch на основе QueryPerformanceCounter, и TStopwatch использующий один из предыдущих классов секундомеров в зависимости от аппаратной части компьютера.

вторник, апреля 21, 2009

Исправление в Interface Extender

Исправлена ошибка при работе с динамическим массивом. Проявлялась при попытке добавить несколько интерфейсов на один класс.

понедельник, апреля 20, 2009

Расширенная поддержка интерфейсов для Delphi

В блоге Алексея Тимохина озвучена хотелка касающаяся поддержки интерфейсов базовыми классами. На мой взгляд, идея весьма спорная, во всяком случае при нынешнем положении дел в языке. Однако, реализовать нечно подобное можно уже сейчас ;) Тут я набросал пример, как это может быть реализовано (intfExtender.pas реализует непосредственно механизм расширения, а unit1.pas содержит два примера). Если кому пригодится, буду только рад ;) Универсальность прикладного кода, о которой говорит Алексей, таким образом можно обеспечить.

p.s. Модуль сильно не тестировался, посему никаких гарантий если что ;)

среда, апреля 15, 2009

Очередные ошибки инициализации/финализации в Delphi 2006 - 2009

Отчет #73008 описывает несвоевременную финализцию энумератора являющегося интерфейсом при использовании в основном теле программы (в процедурах и функциях работает нормально), что в некоторых случаях может приводить к ошибкам доступа (Access violation).

Отчет #73009 описывает неадекватную инициализацию (а точнее ее отсутствие) интерфейсного поля advanced record в случае, когда последняя используется в качестве возвращаемого значения.

пятница, апреля 10, 2009

Утечки и неадекватное поведение Delphi 2006 - 2009 Update 1

При передаче advanced record имеющей интерфейсное поле, в качестве константного параметра, есть немалый шанс налететь на утечку и получить неадекватное поведение т.к. даже константный параметр имеющий размер поинтера передается по значению. Подробности и код в отчете #72878

понедельник, марта 23, 2009

суббота, марта 14, 2009

Ошибка компиляции на ровном месте

Если у класса или записи определить вложенный энумератор, который будет иметь поля "управляемых" типов (string, interface, dynamic array, variant), то при попытке использования в операторе for-in-do мы получим ошибку компиляции на несоответствие типов. Воспроизводится, и на Turbo Delphi Explorer, и на Delphi 2009 Update 1. Репорт #72213.

понедельник, февраля 02, 2009

Обновлен Common.Encodings.pas

На домашней страничке выложен обновленный Common.Encodings.pas

Добавлены классы кодировок UTF-32 и UTF-32BE (только Delphi 2009), добавлен метод определения кодировки по BOM. Добавлены функции-аналоги WideCharToMultiByte и MultiByteToWideChar для кодировок UTF-16, UTF-16BE, UTF-32, UTF-32BE. Функции приведены к единым сигнатурам. Определен процедурный тип с сигнатурой кодирующей и декодирующей функций. Добавлен воркараунд для корректного определения доступности кодировок UTF-7, UTF-8 под Windows NT 4.0

суббота, января 31, 2009

Утечки на интерфейсных параметрах

Теряются объекты передаваемые в качестве параметров интерфейсных типов в случае, когда не происходит кастинга с проверкой (as) к определенному интерфейсу. Для кода:

 Test(TMyObject.Create('1')); // will not be destroyed
Test(IInterface(TMyObject.Create('2'))); // will not be destroyed
Test(TMyObject.Create('3') As IInterface);

утечки будут в первых двух вызовах. Воспроизводится, и на Turbo Delphi, и на Delphi 2009. Отчет #71015.

пятница, января 16, 2009

QC, в чем магия?

Только вчера "ругался" на неторопливость правки багов в компиляторе, а сегодня глянул на свой  отчет №70529 и удивился -- он получил статус Internally Opened (как я понимаю, над ошибкой уже работают). Так вот, в чем магия? Неужели голос Алексея был решающим? ;)

четверг, января 15, 2009

Ошибка в Delphi 2009 Update 1

Передача односимвольной строки в диспетчеризируемый метод приводит к передаче кода символа, а не строки. Лечится приведением строки к строке :) т.е. вот так: String('1'). Репорт номер 70529, поддержите, кому не лень.

пятница, октября 31, 2008

Приемчик

Потребовалось символ юникод строки проверить на предмет вхождения в суррогатную пару (а конкретно, является ли символ младшим суррогатом). Все бы ничего, но индекс символа вычисляемый и вычислять его для каждого сравнения (коих собственно два) не кошерно. Есть варианты решения:

1. Сохранить индекс в переменной. Просто, но нужна переменная.

2. Сделать функцию и заинлайнить ее. Нужна функция.

3. Извернуться.

Собственно, я о третьем варианте:

     With WordRec(AContent[ACharIndex + CharCount]) Do
If (Word(Bytes) >= $DC00) And (Word(Bytes) <= $DFFF) Then;

воскресенье, октября 26, 2008

Оперативность QC

Все шесть моих репортов прошли во внутреннюю базу в среднем через 2 недели после подачи. Шустро. Правда с одним лажа вышла, отрепортил о баге пофикшеном в релизе :(