1
+ #region copyright
2
+
3
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
4
+ /* Carl Zeiss Industrielle Messtechnik GmbH */
5
+ /* Softwaresystem PiWeb */
6
+ /* (c) Carl Zeiss 2024 */
7
+ /* * * * * * * * * * * * * * * * * * * * * * * * * */
8
+
9
+ #endregion
10
+
11
+ namespace Zeiss . PiWeb . Volume . Block ;
12
+
13
+ #region usings
14
+
15
+ using System ;
16
+ using System . IO ;
17
+
18
+ #endregion
19
+
20
+ /// <summary>
21
+ /// Holds information about a block of encoded values.
22
+ /// </summary>
23
+ internal readonly record struct BlockInfo ( ushort ValueCount , bool IsFirstValueShort , bool AreOtherValuesShort )
24
+ {
25
+ #region constants
26
+
27
+ private const ushort ValueCountMask = 0b0000111111111111 ;
28
+ private const ushort IsFirstValueShortMask = 0b0001000000000000 ;
29
+ private const int IsFirstValueShortOffset = 12 ;
30
+ private const ushort AreOtherValuesShortMask = 0b0010000000000000 ;
31
+ private const int AreOtherValuesShortOffset = 13 ;
32
+
33
+ #endregion
34
+
35
+ #region properties
36
+
37
+ /// <summary>
38
+ /// The length of the block in bytes.
39
+ /// </summary>
40
+ public ushort Length =>
41
+ ValueCount switch
42
+ {
43
+ 0 => 0 ,
44
+ 1 => FirstValueSize ,
45
+ _ => ( ushort ) ( FirstValueSize + ( ValueCount - 1 ) * ( AreOtherValuesShort ? 2 : 1 ) )
46
+ } ;
47
+
48
+ /// <summary>
49
+ /// The size of the first value in bytes.
50
+ /// </summary>
51
+ public byte FirstValueSize => ( byte ) ( IsFirstValueShort ? 2 : 1 ) ;
52
+
53
+ #endregion
54
+
55
+ #region methods
56
+
57
+ /// <summary>
58
+ /// Reads the <see cref="BlockInfo"/> from the specified <paramref name="reader"/>.
59
+ /// </summary>
60
+ public static BlockInfo Read ( BinaryReader reader )
61
+ {
62
+ var resultLength = reader . ReadUInt16 ( ) ;
63
+ var valueCount = resultLength & ValueCountMask ;
64
+ var isFirstValueShort = ( resultLength & IsFirstValueShortMask ) >> IsFirstValueShortOffset ;
65
+ var areOtherValuesShort = ( resultLength & AreOtherValuesShortMask ) >> AreOtherValuesShortOffset ;
66
+
67
+ return new BlockInfo ( ( ushort ) valueCount , isFirstValueShort > 0 , areOtherValuesShort > 0 ) ;
68
+ }
69
+
70
+ /// <summary>
71
+ /// Writes the <see cref="BlockInfo"/> to the specified <paramref name="writer"/>.
72
+ /// </summary>
73
+ public void Write ( BinaryWriter writer )
74
+ {
75
+ var result = ValueCount & ValueCountMask ;
76
+ if ( IsFirstValueShort )
77
+ result |= ( 1 << IsFirstValueShortOffset ) ;
78
+ if ( AreOtherValuesShort )
79
+ result |= ( 1 << AreOtherValuesShortOffset ) ;
80
+
81
+ writer . Write ( ( ushort ) result ) ;
82
+ }
83
+
84
+ /// <summary>
85
+ /// Creates a <see cref="BlockInfo"/> for the specified <paramref name="resultBlock"/>.
86
+ /// </summary>
87
+ public static BlockInfo Create ( ReadOnlySpan < short > resultBlock )
88
+ {
89
+ var count = 0 ;
90
+ var isFirstValueShort = resultBlock [ 0 ] is > sbyte . MaxValue or < sbyte . MinValue ;
91
+ var areOtherValuesShort = false ;
92
+
93
+ for ( var i = 0 ; i < BlockVolume . N3 ; i ++ )
94
+ {
95
+ var value = resultBlock [ i ] ;
96
+ if ( value != 0 )
97
+ count = i + 1 ;
98
+
99
+ if ( i > 0 && ( value is > sbyte . MaxValue or < sbyte . MinValue ) )
100
+ areOtherValuesShort = true ;
101
+ }
102
+
103
+ return new BlockInfo ( ( ushort ) count , isFirstValueShort , areOtherValuesShort ) ;
104
+ }
105
+
106
+ #endregion
107
+ }
0 commit comments