为什么TPageProducer没有从字符串中删除引号?

Bri*_*ost 8 delphi string delphi-xe4

我正在尝试调试仅在我的大型应用程序 - 在XE3中正常工作 - 在使用XE4编译后运行时才出现的行为.该问题似乎导致一些引用的字符串(例如"MyString")即使在由Web.HTTPProd中的TPageProducer"解除引用"之后仍保留其引号.例如,考虑以下代码,该代码是来自此Delphi源单元Web.HTTPApp的小提取:

procedure ExtractHeaderFields(Separators, _WhiteSpace: TSysCharSet; Content: PChar;
  Strings: TStrings; Decode: Boolean; StripQuotes: Boolean = False);
{$ENDIF NEXTGEN}
var
  Head, Tail: PChar;
  EOS, InQuote, LeadQuote: Boolean;
  QuoteChar: Char;
  ExtractedField: string;
{$IFNDEF NEXTGEN}
  WhiteSpaceWithCRLF: TSysCharSet;
  SeparatorsWithCRLF: TSysCharSet;
{$ENDIF !NEXTGEN}

  function DoStripQuotes(const S: string): string;
  var
    I: Integer;
    InStripQuote: Boolean;
    StripQuoteChar: Char;
  begin
    Result := S;
    InStripQuote := False;
    StripQuoteChar := #0;
    if StripQuotes then
    begin
      for I := Result.Length - 1 downto 0 do
        if Result.Chars[I].IsInArray(['''', '"']) then
          if InStripQuote and (StripQuoteChar = Result.Chars[I]) then
          begin
            Result.Remove(I, 1);
            InStripQuote := False;
          end
          else if not InStripQuote then
          begin
            StripQuoteChar := Result.Chars[I];
            InStripQuote := True;
            Result.Remove(I, 1);
          end
    end;
  end;
Run Code Online (Sandbox Code Playgroud)

我看到这个叫当我使用TPageProducer,我可以看到我的好源字符串进入ExtractHeaderFields例行以上,然后进入"DoStripQuotes"功能.走进DoStripQuotes和看"结果"表明,它不会改变,即使Result.Remove被称为(剥去引号).当我借此"DoStripQuotes"常规出一个简单的测试程序,它不会编译,告诉我,"Result.anything"是不允许的.我假设那个结果,虽然它被定义为'string'必须是Web.HTTPProd上下文中的另一种类型的字符串.

所以我想到这可能与我听说过的"不变的字符串"有关.我读到了这个关于这个问题的问题,虽然我得到了要点,但我可以提供更实用的建议.

具体来说,我想回答以下问题:

  1. 如果允许使用表示法Result.Length,那么什么类型的'字符串'是'结果'?
  2. 有没有一种方法可以告诉编译器为一个单元使用'XE3'兼容性?(这可能会让我看到问题的起源).香港专业教育学院ttried {$ ZEROBASEDSTRINGS ON}/OFF但这似乎造成更大的混乱,我不知道我在做什么!

谢谢你的帮助.

稍后编辑:如下面接受的答案中所述,这是VCL单元Web.HTTPApp.pas中的一个错误,它应该在2645行的两个地方读取"Result:= Result.Remove(I,1)"而不是"结果".删除(1,1)"

Dav*_*nan 9

如果允许使用表示法Result.Length,那么什么类型的'字符串'是'结果'?

它就像你以前一直在使用的那个旧的string,别名的.不同之处在于此代码使用新记录助手(具体而言).这就是让你在字符串变量上使用符号的原因.UnicodeStringDelphi 2009SysUtils.TStringHelper.

有没有一种方法可以告诉编译器为一个单元使用'XE3'兼容性?

不是.有问题的代码是一个库单元,它被设计为以特定模式编译.更重要的是,除非你自己编译RTL/VCL,否则你不能轻易地重新编译它.即使有这样的模式,也没有用,因为代码完全错误(见下文).没有多少模式切换可以修复这段特定的代码.

我开始想,也许这与我听说过的不变的字符串有关.

不是.没有任何Delphi编译器具有不可变的字符串.不可变字符串的概念只是作为未来变化浮现的东西.如果进行了更改,则希望首先在移动编译器中进行更改.


问题实际上只是你发布的代码中一个相当简单的错误,它显然根本没有测试.使用Remove是错误的.该方法不会就地修改字符串.相反,它返回一个删除了字符的新字符串.代码应为:

Result := Result.Remove(I, 1);
Run Code Online (Sandbox Code Playgroud)

编码的开发人员ExtractHeaderFields犯了这个错误的原因是,设计字符串帮助程序代码的人Remove不正确地命名了该方法.既然Remove是一个动词,你会期望它就地运作.如此方法不会修改主题并返回新实例的方法应该被赋予名词.所以这个方法应该被命名为Remnants.在我看来,好像RTL设计师复制了同样存在缺陷的.net命名.

如果尚未存在质量控制报告,您应提交质量控制报告.我知道XE4 update 1刚刚发布.它包含修复它似乎是合理的.

正如我所看到的,您的其他选择是:

  1. 坚持使用XE3,直到XE4充分调试.
  2. Web.HTTPApp在项目中包含该单元的副本并自行修复错误.