• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DomCR / ACadSharp / 29143042407

11 Jul 2026 06:34AM UTC coverage: 2.912% (-73.0%) from 75.918%
29143042407

push

github

web-flow
Merge pull request #1146 from ilCosmico/acds-read-payload-anchor

Read the AcDs payload area offset from the data segment header

264 of 12999 branches covered (2.03%)

Branch coverage included in aggregate %.

0 of 30 new or added lines in 1 file covered. (0.0%)

31243 existing lines in 465 files now uncovered.

1337 of 41984 relevant lines covered (3.18%)

5.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/ACadSharp/IO/AcisTextCodec.cs
1
using System.Text;
2

3
namespace ACadSharp.IO
4
{
5
        /// <summary>
6
        /// Codec for the character swap applied to the SAT text carried by the
7
        /// modeler geometry entities (3DSOLID, REGION, BODY) in pre-2013 files.
8
        /// </summary>
9
        /// <remarks>
10
        /// Each character above the space is stored as 0x9F minus its code, the rest
11
        /// pass through unchanged. The transformation is an involution: applying it
12
        /// twice returns the original text, so the same method encodes and decodes.
13
        /// </remarks>
14
        internal static class AcisTextCodec
15
        {
16
                /// <summary>
17
                /// Decodes (or encodes) a chunk of character-swapped SAT text.
18
                /// </summary>
19
                public static string Decode(string text)
UNCOV
20
                {
×
UNCOV
21
                        if (string.IsNullOrEmpty(text))
×
22
                        {
×
23
                                return text;
×
24
                        }
25

UNCOV
26
                        StringBuilder sb = new StringBuilder(text.Length);
×
UNCOV
27
                        foreach (char c in text)
×
UNCOV
28
                        {
×
UNCOV
29
                                if (c > ' ' && c < (char)0x9F)
×
UNCOV
30
                                {
×
UNCOV
31
                                        sb.Append((char)(0x9F - c));
×
UNCOV
32
                                }
×
33
                                else
UNCOV
34
                                {
×
UNCOV
35
                                        sb.Append(c);
×
UNCOV
36
                                }
×
UNCOV
37
                        }
×
38

UNCOV
39
                        return sb.ToString();
×
UNCOV
40
                }
×
41

42
                /// <summary>
43
                /// Decodes (or encodes) a buffer of character-swapped SAT text.
44
                /// </summary>
45
                public static byte[] Decode(byte[] data)
UNCOV
46
                {
×
UNCOV
47
                        if (data == null || data.Length == 0)
×
48
                        {
×
49
                                return data;
×
50
                        }
51

UNCOV
52
                        byte[] result = new byte[data.Length];
×
UNCOV
53
                        for (int i = 0; i < data.Length; i++)
×
UNCOV
54
                        {
×
UNCOV
55
                                byte b = data[i];
×
UNCOV
56
                                result[i] = b > 0x20 && b < 0x9F ? (byte)(0x9F - b) : b;
×
UNCOV
57
                        }
×
58

UNCOV
59
                        return result;
×
UNCOV
60
                }
×
61

62
                /// <summary>
63
                /// Trims an ACIS payload at its end marker.
64
                /// </summary>
65
                /// <remarks>
66
                /// The DWG entity stream gives no length for the payload, so the caller
67
                /// reads up to the end of the object data and this method cuts the result
68
                /// right after the End-of-ACIS-data marker. SAT text and single-tag SAB
69
                /// records spell the marker as plain ASCII; older SAB writers emit it as a
70
                /// compound entity name split in tagged chunks. The payload is returned
71
                /// unchanged when no marker is found.
72
                /// </remarks>
73
                public static byte[] TrimAtAcisEnd(byte[] data)
UNCOV
74
                {
×
UNCOV
75
                        if (data == null || data.Length == 0)
×
76
                        {
×
77
                                return data;
×
78
                        }
79

UNCOV
80
                        foreach (byte[] marker in _endMarkers)
×
UNCOV
81
                        {
×
UNCOV
82
                                int index = indexOf(data, marker, 0);
×
UNCOV
83
                                if (index >= 0)
×
UNCOV
84
                                {
×
UNCOV
85
                                        return cutAfter(data, index + marker.Length);
×
86
                                }
UNCOV
87
                        }
×
88

UNCOV
89
                        return data;
×
UNCOV
90
                }
×
91

92
                //End-of-ACIS-data / End-of-ASM-data markers: the name depends on the kernel
93
                //that wrote the payload, spelled as plain ASCII (SAT text and single-tag SAB
94
                //records) or as a compound SAB entity name split in tagged chunks.
UNCOV
95
                private static readonly byte[][] _endMarkers = new byte[][]
×
UNCOV
96
                {
×
UNCOV
97
                        Encoding.ASCII.GetBytes("End-of-ACIS-data"),
×
UNCOV
98
                        Encoding.ASCII.GetBytes("End-of-ASM-data"),
×
UNCOV
99
                        new byte[]
×
UNCOV
100
                        {
×
UNCOV
101
                                0x0E, 0x03, (byte)'E', (byte)'n', (byte)'d',
×
UNCOV
102
                                0x0E, 0x02, (byte)'o', (byte)'f',
×
UNCOV
103
                                0x0E, 0x04, (byte)'A', (byte)'C', (byte)'I', (byte)'S',
×
UNCOV
104
                                0x0D, 0x04, (byte)'d', (byte)'a', (byte)'t', (byte)'a'
×
UNCOV
105
                        },
×
UNCOV
106
                        new byte[]
×
UNCOV
107
                        {
×
UNCOV
108
                                0x0E, 0x03, (byte)'E', (byte)'n', (byte)'d',
×
UNCOV
109
                                0x0E, 0x02, (byte)'o', (byte)'f',
×
UNCOV
110
                                0x0E, 0x03, (byte)'A', (byte)'S', (byte)'M',
×
UNCOV
111
                                0x0D, 0x04, (byte)'d', (byte)'a', (byte)'t', (byte)'a'
×
UNCOV
112
                        }
×
UNCOV
113
                };
×
114

115
                private static byte[] cutAfter(byte[] data, int end)
UNCOV
116
                {
×
UNCOV
117
                        if (end >= data.Length)
×
118
                        {
×
119
                                return data;
×
120
                        }
121

UNCOV
122
                        byte[] result = new byte[end];
×
UNCOV
123
                        System.Array.Copy(data, result, end);
×
UNCOV
124
                        return result;
×
UNCOV
125
                }
×
126

127
                private static int indexOf(byte[] haystack, byte[] needle, int start)
UNCOV
128
                {
×
UNCOV
129
                        for (int i = start; i <= haystack.Length - needle.Length; i++)
×
UNCOV
130
                        {
×
UNCOV
131
                                bool match = true;
×
UNCOV
132
                                for (int j = 0; j < needle.Length; j++)
×
UNCOV
133
                                {
×
UNCOV
134
                                        if (haystack[i + j] != needle[j])
×
UNCOV
135
                                        {
×
UNCOV
136
                                                match = false;
×
UNCOV
137
                                                break;
×
138
                                        }
UNCOV
139
                                }
×
140

UNCOV
141
                                if (match)
×
UNCOV
142
                                {
×
UNCOV
143
                                        return i;
×
144
                                }
UNCOV
145
                        }
×
146

UNCOV
147
                        return -1;
×
UNCOV
148
                }
×
149

150
                /// <summary>
151
                /// Detects if a SAT chunk is character-swapped.
152
                /// </summary>
153
                /// <remarks>
154
                /// Plain SAT starts with the numeric header line (for example "400 0 1 0"),
155
                /// so a first printable character that is not a digit marks a swapped payload.
156
                /// </remarks>
157
                public static bool IsEncoded(string text)
UNCOV
158
                {
×
UNCOV
159
                        if (string.IsNullOrEmpty(text))
×
160
                        {
×
161
                                return false;
×
162
                        }
163

UNCOV
164
                        foreach (char c in text)
×
UNCOV
165
                        {
×
UNCOV
166
                                if (c <= ' ')
×
167
                                {
×
168
                                        continue;
×
169
                                }
170

UNCOV
171
                                return !char.IsDigit(c);
×
172
                        }
173

174
                        return false;
×
UNCOV
175
                }
×
176
        }
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc