记录中的多个变体部分

6
我正在使用Delphi XE2编写一个小工具来操作SWF文件。到目前为止,我只是简单地遵循SWF规范,现在在实现表示形状的数据结构时遇到了一个小问题。
SWF形状包含多个形状记录。形状记录可以是边缘记录或非边缘记录,这两种类型都有两个额外的子类型。
具体来说,在规范的第135页上描述了两种非边缘记录类型;EndShapeRecordStyleChangeRecord。在SWF文件中,区分它们的方法是检查TypeFlag后的五个标志位是否都为0;如果是,则为EndShapeRecord,否则为StyleChangeRecord
为了方便后续处理形状记录,我想将边缘和非边缘记录统一为单个记录类型,并使用变体记录。区分不同类型的记录很容易;嵌套的变体记录让我轻松地将边缘记录与非边缘记录分开,对于非边缘记录,我可以声明StyleChangeRecord中的5个标志并编写一个IsEndRecord函数。
然而,为了使我的源代码尽可能地反映规范,我想再进一步。 StyleChangeRecord中其他字段的存在取决于这5个标志的值,因此我希望能够声明5个变体记录,每个标志一个,其中包含每个标志添加的字段。(我意识到这不会以任何方式影响内存使用,但这不是重点。)
不幸的是,Delphi似乎不允许在同一“级别”上有多个变体部分,试图在同一级别上定义这5个变体部分只会产生大量语法错误。
TShapeRecord = record
  case EdgeRecord: Boolean of
    False: (
      case StateMoveTo: Boolean of
        True: (
          MoveBits: Byte;
          MoveDeltaX: Int32;
          MoveDeltaY: Int32;
        );
      case StateLineStyle: Boolean of // << Errors start here
        True: (LineStyle: UInt16);
      //Additional flags
    );
    //Fields for edge records
end;

在更简单的说法中,目标是能够像这样制定记录:
TNonEdgeRecord = record
    case StateMoveTo: Boolean of
      True: (
        MoveBits: Byte;
        MoveDeltaX: Int32;
        MoveDeltaY: Int32;
      );
    case StateLineStyle: Boolean of
      True: (LineStyle: UInt16);
end;

...不删除记录的变体部分,也不嵌套它们(因为嵌套会从语法上暗示错误的关系)。

是否有其他方法可以声明记录中的多个(非嵌套)变体部分,还是我应该回到不使用内部变体记录的方式?


我不完全理解你想要实现什么,但听起来你想要自己处理变体记录。使用记录属性很容易实现这一点。 - David Heffernan
@DavidHeffernan:不,那不是完全正确的。我想让类型定义显示哪些字段存在,给定某个标志或变量的值 - 这基本上就是变体记录所做的,而且很简单。对我来说,问题在于在单个记录中获取多个这样的记录;我能做到的最好的就是将它们嵌套,但那会很愚蠢,因为这些标志彼此独立。我将尝试重新编写问题,希望能更清楚地表达。 - Michael Madsen
语法不支持多个独立标志。嵌套是一种选择。具有方法/属性的记录是我能想到的另一个选择。 - David Heffernan
1个回答

5

不可以。Borland Pascal分支只允许变体部分在记录末尾。

嵌套是唯一的方法。

有一些有趣的例子和观察结果,请参见Rudy Velthuis的这篇文章:

http://rvelthuis.de/articles/articles-convert.html (搜索“union”部分)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接