【问题标题】:Is this an encoding technique?这是一种编码技术吗?
【发布时间】:2011-12-05 15:21:33
【问题描述】:

ruakh 的帖子here 之后,我想确定以下sn-p 是否属于TLVKLV 编码类型:

interface

const
  Lex_0: string[length('(EOF)')] ='(EOF)';
  Lex_1: string[length('(Error)')] ='(Error)';

  LexTable : array[0..114] of ^String = (
  @Lex_0,
  @Lex_1
  )

【问题讨论】:

  • 你显示的根本不是编码,只是一些常量的定义。
  • 这属于非类型安全代码类别。您已经声明了一个指向长字符串的指针数组,但是您已经存储了指向其他异构字符串类型的指针。即使您禁用了长字符串(我认为这很愚蠢),它们仍然指向长度与数组所说的长度不同的短字符串。
  • 这与 Gold 解析器有什么关系?
  • @Rob Kennedy:这个 sn-p 取自从 Gold Parser 站点获取的代码。由于对问题的进一步编辑,这些细节被剥夺了。它甚至被它的作者称为“笨拙”。

标签: delphi encoding tlv


【解决方案1】:

您的示例代码不起作用,因为您正在混合 shortstring constpointerstring - 正如 Rob 在他的评论中所说的那样。

而且您的代码与 KLV 或 TLV 编码无关。

这里可能是一个 TLV 编码示例(我只展示了字符串编码,但您可以添加其他类型):

type
  TTLVType = (tlvUnknown, tlvString, tlvInteger);

function EncodeToTLV(const aString: WideString): TBytes;
var Len: integer;
begin
  Len := length(aString)*2;
  SetLength(result,Len+sizeof(TTLVType)+sizeof(integer));
  Result[0] := ord(tlvString); // Type
  PInteger(@Result[sizeof(TTLVType)])^ := Len; // Length
  move(pointer(aString)^,Result[sizeof(TTLVType)+sizeof(integer)],Len); // Value
end;

function DecodeStringFromTLV(const aValue: TBytes): WideString;
begin
  if (length(aValue)<3) or (aValue[0]<>ord(tlvString)) or
     (PInteger(@aValue[sizeof(TTLVType)])^<>length(aValue)-sizeof(TTLVType)-sizeof(integer)) then
    raise EXception.Create('Invalid input format');
  SetString(result,PWideChar(@Result[sizeof(TTLVType)+sizeof(integer)]),PInteger(@aValue[sizeof(TTLVType)])^ div 2);
end;

我在这里使用了WideString,因为它可以安全地存储任何 Unicode 内容,即使在 Delphi 2009 之前的编译器版本上也是如此。

你可以使用记录代替我的指针算法:

type
  TTLVHeader = packed record
    ContentType: TTLVType;
    ContentLength: integer;
    Content: array[0..1000] of byte; // but real length will vary
  end;
  PTLVHeader = ^TTLVHeader;

function EncodeToTLV(const aString: WideString): TBytes;
var Len: integer;
begin
  Len := length(aString)*2;
  SetLength(result,Len+sizeof(TTLVType)+sizeof(integer));
  with PTLVHeader(result)^ do 
  begin
    ContentType := tlvString;
    ContentLength := Len;
    move(pointer(aString)^,Content,Len); 
  end;  
end;

KLV 可以使用类似的编码,但在标头中添加一个整数键。

【讨论】:

  • 谢谢。 (Très instructive, merci bien)。此外,你可以找到here 我从中获取sn-p 的项目。我在 D2007 下测试过,它可以工作。
  • @menjaraz 您的代码 sn-p 甚至无法编译。 ^string 不是 ^shortstring(从 Delphi 1 开始)。如果在使用前将其类型转换回 ^shortstring 或依赖短字符串布局,则此代码可能会起作用。
  • 你说的很对。 sn-p 本身并不完整,我没有让自己理解。当我说它有效时,我指的是整个原始项目,我从中剥离了它。实际使用了某种类型转换。
【解决方案2】:

据我所知,这仅定义了两个常量(本例中为Lex_0Lex_1)并将它们放入一个名为LexTable 的数组中,这根本不是编码。

Lex_0: string // declares a string constant by the name of Lex_0
[length('(EOF)')] // specifies the length of the string, this is equivalent to [5] in this case
='(EOF)' // sets the constant to '(EOF)'

然后创建指向字符串的指针LexTable 数组,并将两个常量的地址放入数组中。

【讨论】:

  • sn-p 是从语法和模板作为输入的一些解析器生成的代码的摘录。该工具没有评估字符串长度的广泛能力(下降情况下的词素)。我相信,硬编码只是一种解决方法。
猜你喜欢
  • 2020-06-28
  • 2013-08-11
  • 2019-08-19
  • 1970-01-01
  • 2010-09-07
  • 2010-10-12
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
相关资源
最近更新 更多