Ошибка "несоответствие типов" для "набора символов" в Pascal Script версии Inno Setup для Unicode

У меня есть рабочие скрипты Pascal для Inno Setup, но недавно мы столкнулись с проблемой символов Unicode. И после изменения Inno Setup на версию Unicode мы получили ошибки в существующих скриптах. И эта ошибка слишком общая - "Несоответствие типов" для определенной строки. Так как наш основной скрипт состоит из множества других скриптов, которые включены, я не уверен, что эта строка правильная, и она указывает на эту функцию ниже, и строка Set of Char, Посмотрев документацию Inno Setup, я обнаружил, что версия Unicode немного строже в некоторых вещах, а также произошли некоторые изменения в обработке строк ANSI (и, возможно, Char также).

function IsValidName(Name: String):String;
var
  Valid_Ch: Set of Char;
  Location: Integer;
begin
    Valid_Ch := ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '_', '-'];
    Result := '';
    for Location := 1 to Length(Name) do
    begin
        if Name[Location] in Valid_Ch then
        begin
            Result := Result + Name[Location];
        end
        else
        begin
            Result := Result + '_';
        end;
    end;    
end;

Все это выглядит хорошо для меня, но это мой первый контакт с Паскалем. Я был бы благодарен, если бы кто-то более опытный мог помочь мне в этом. Спасибо!

2 ответа

Решение

В Паскале (Сценарий) set может содержать только 256 (2^8) значений. В Unicode Inno Setup Char является 2-байтовым, следовательно, он может содержать более 256 различных значений. Таким образом, вы не можете использовать его с set больше.

У вас есть эти варианты:

  • В вашем случае, поскольку набор на самом деле является постоянным, вы можете использовать постоянный набор в if выражение. Интересно, что это работает даже в версии Unicode (возможно, есть встроенный хак, который допускает это исключение).

    function IsValidName(Name: string): string;
    var
      Location: Integer;
    begin
      Result := Name;
      for Location := 1 to Length(Name) do
      begin
        if not (Name[Location] in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '_', '-']) then
        begin
          Result[Location] := '_';
        end;
      end;    
    end;
    

Если бы вам нужно, чтобы набор был переменным (не ваш случай):

  • использование Byte и бросить между Char а также Byte и явно заменить все символы Ord() > 255
  • Или используйте string вместо set, Пример см. Ниже.

    function IsValidName(Name: string): string;
    var
      Valid_Ch: string;
      Location: Integer;
    begin
      Valid_Ch := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-';
      Result := Name;
      for Location := 1 to Length(Result) do
      begin
        if Pos(Result[Location], Valid_Ch) = 0 then
        begin
          Result[Location] := '_';
        end;
      end;    
    end;
    

Также обратите внимание, что добавление строки char-by-char может быть довольно неэффективным. Вместо этого замените символы на месте (как показано в обоих примерах выше).

С набором символов лучше использовать типизированный TSysCharSet или конвертер типа StrToCharSet, чтобы избежать несоответствия типов, например в maXbox4:

        function IsValidName2(Name: string): string;
  var Location: Integer;
  begin
    Result:= Name;
    for Location := 1 to Length(Name) do begin
    if not (Name[Location] in StrToCharSet(lowercase(LETTERSET)+
                            LETTERSET+DIGISET+ '_'+'-')) then begin
      Result[Location] := '_';
    end;
  end;    
 end;
Другие вопросы по тегам