将分隔的字段合二为一
Concat separated fields in one
我在 Ada 工作,我有一个非常丑陋的类型,我无法修改,我想做一些易于使用的东西。
类型是这样的:
for T_Ugly_Type'Alignment use 4;
for T_Ugly_Type'Size use 48;
for T_Ugly_Type use record
Value_Bits_00_07 at 16#00# range 0 .. 7; -- 8 bits
Field1 at 16#00# range 8 .. 15; -- 8 bits
Field2 at 16#02# range 0 .. 11; -- 12 bits
Value_Bits_08_11 at 16#02# range 12 .. 15; -- 4 bits
Value_Bits_12_15 at 16#03# range 0 .. 3; -- 4 bits
Field3 at 16#03# range 4 .. 15; -- 12 bits
end record;
此结构由一条消息填充,地址无法更改。但是我的 Value
是一个 16 位的类型,分为 3 个部分。我不想将所有这些部分与我想使用的每种类型相结合。
有没有办法使用 T_Ugly_Type.Value
并得到 Value_Bits_00_07 + 2 ** 8 * Value_Bits_08_12 + 2 ** 12 * Value_Bits_12_15
的结果?
你可以这样做:
type T_Wrapper is tagged record
Values : T_Ugly_Type;
end record;
function Value (Subject : T_Wrapper) return Uint16 is
(Subject.Values.Value_Bits_00_07 * 2**8 +
Subject.Values.Value_Bits_08_12 * 2**4 +
Subject.Values.Vaule_Bits_13_15);
function Field1 (Subject : T_Wrapper) return Uint12 is
(Subject.Values.Field1);
function Field2 (Subject : T_Wrapper) return Uint12 is
(Subject.Values.Field2);
function Field3 (Subject : T_Wrapper) return Uint12 is
(Subject.Values.Field3);
成为 tagged
使您能够在 T_Wrapper
函数上使用前缀语法:
declare
-- assuming a T_Ugly_Type instance named Orig
Wrapped : T_Wrapper := (Values => Orig);
begin
Do_Something (Wrapped.Value);
Do_Something_Elese (Wrapped.Field1);
end;
请注意,由于未标记原始类型,因此您不能在其上声明 Value
可以使用前缀表示法调用的函数。
一种可能更好的方法是使用 access
值和一些 Ada 2012 功能:
type Reference (Data : not null access T_Ugly_Type) is tagged limited null record
with Implicit_Dereference => Data;
function Value (Subject : Reference) return Uint16 is
(Subject.Data.Value_Bits_00_07 * 2**8 +
Subject.Data.Value_Bits_08_12 * 2**4 +
Subject.Data.Vaule_Bits_13_15);
Implicit_Dereference
允许您直接访问原始字段,而您可以使用Value
函数进行计算。
declare
Ref : Reference := (Data => Orig'Access);
begin
Do_Something (Ref.Value); -- calls function
Do_Something (Ref.Field1); -- accesses Field1 of the inner record
end;
我在 Ada 工作,我有一个非常丑陋的类型,我无法修改,我想做一些易于使用的东西。
类型是这样的:
for T_Ugly_Type'Alignment use 4;
for T_Ugly_Type'Size use 48;
for T_Ugly_Type use record
Value_Bits_00_07 at 16#00# range 0 .. 7; -- 8 bits
Field1 at 16#00# range 8 .. 15; -- 8 bits
Field2 at 16#02# range 0 .. 11; -- 12 bits
Value_Bits_08_11 at 16#02# range 12 .. 15; -- 4 bits
Value_Bits_12_15 at 16#03# range 0 .. 3; -- 4 bits
Field3 at 16#03# range 4 .. 15; -- 12 bits
end record;
此结构由一条消息填充,地址无法更改。但是我的 Value
是一个 16 位的类型,分为 3 个部分。我不想将所有这些部分与我想使用的每种类型相结合。
有没有办法使用 T_Ugly_Type.Value
并得到 Value_Bits_00_07 + 2 ** 8 * Value_Bits_08_12 + 2 ** 12 * Value_Bits_12_15
的结果?
你可以这样做:
type T_Wrapper is tagged record
Values : T_Ugly_Type;
end record;
function Value (Subject : T_Wrapper) return Uint16 is
(Subject.Values.Value_Bits_00_07 * 2**8 +
Subject.Values.Value_Bits_08_12 * 2**4 +
Subject.Values.Vaule_Bits_13_15);
function Field1 (Subject : T_Wrapper) return Uint12 is
(Subject.Values.Field1);
function Field2 (Subject : T_Wrapper) return Uint12 is
(Subject.Values.Field2);
function Field3 (Subject : T_Wrapper) return Uint12 is
(Subject.Values.Field3);
成为 tagged
使您能够在 T_Wrapper
函数上使用前缀语法:
declare
-- assuming a T_Ugly_Type instance named Orig
Wrapped : T_Wrapper := (Values => Orig);
begin
Do_Something (Wrapped.Value);
Do_Something_Elese (Wrapped.Field1);
end;
请注意,由于未标记原始类型,因此您不能在其上声明 Value
可以使用前缀表示法调用的函数。
一种可能更好的方法是使用 access
值和一些 Ada 2012 功能:
type Reference (Data : not null access T_Ugly_Type) is tagged limited null record
with Implicit_Dereference => Data;
function Value (Subject : Reference) return Uint16 is
(Subject.Data.Value_Bits_00_07 * 2**8 +
Subject.Data.Value_Bits_08_12 * 2**4 +
Subject.Data.Vaule_Bits_13_15);
Implicit_Dereference
允许您直接访问原始字段,而您可以使用Value
函数进行计算。
declare
Ref : Reference := (Data => Orig'Access);
begin
Do_Something (Ref.Value); -- calls function
Do_Something (Ref.Field1); -- accesses Field1 of the inner record
end;