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

DomCR / ACadSharp / 30339613344

28 Jul 2026 07:45AM UTC coverage: 75.811% (-0.1%) from 75.927%
30339613344

push

github

web-flow
Merge pull request #1154 from domeitzinger/prototype1b-dwg-reader

Implement full Prototype1b section parsing

9167 of 13083 branches covered (70.07%)

Branch coverage included in aggregate %.

549 of 707 new or added lines in 31 files covered. (77.65%)

2 existing lines in 2 files now uncovered.

32923 of 42437 relevant lines covered (77.58%)

152242.63 hits per line

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

5.83
/src/ACadSharp/Prototype1b/DataStorage.cs
1
using ACadSharp.Entities;
2
using ACadSharp.Prototype1b.Segments;
3
using System.Collections.Generic;
4
using System.Linq;
5

6
namespace ACadSharp.Prototype1b
7
{
8
    public class DataStorage
9
    {
10
                /// <summary>
11
                /// General information about the header of the <see cref="DataStorage"/> and Prototype_1b section
12
                /// </summary>
13
        public FileHeader FileHeader { get; set; }
60,201✔
14

15
        /// <summary>
16
                /// Information about file state at last revision
17
                /// </summary>
18
        public PreviousSave PreviousSave { get; set; }
53✔
19

20
                /// <summary>
21
                /// Pointers to individual segments of the Prototype_1b section referenced to by the <see cref="FileHeader"/>
22
                /// </summary>
23
        public DataStoragePointers IndexPointers { get; set; }
1,246✔
24

25
        /// <summary>
26
                /// All registered Schemas
27
                /// </summary>
28
        public List<SchemaData> SchemaFields { get; set; }
148✔
29

30
        /// <summary>
31
                /// The search object to get the data entries associated with schema entries
32
                /// </summary>
33
        public SchemaSearch SchemaSearch { get; set; }
106✔
34

35
                /// <summary>
36
                /// Fields containing data entries with bytes of embedded files, or references to <see cref="Blobs"/>
37
                /// </summary>
38
        public List<DataField> DataFields { get; set; }
131✔
39

40
                /// <summary>
41
                /// Blobs of bytes referenced to by <see cref="DataFields"/>. 
42
                /// Embedded files larger than 0x40000 bytes will be split into one or more blobs
43
                /// </summary>
44
                public List<Blob01> Blobs { get; set; }
53✔
45

46
        public Schema GetSchemaByName(string name)
NEW
47
        {
×
NEW
48
            foreach (SchemaData data in this.SchemaFields) {
×
NEW
49
                foreach (Schema schema in data.Values) {
×
NEW
50
                    if (schema.Name == name) {
×
NEW
51
                        return schema;
×
52
                    }
NEW
53
                }
×
NEW
54
            }
×
NEW
55
            return null;
×
NEW
56
        }
×
57

58
                public List<DataEntry> GetSchemaData(Schema schema)
NEW
59
        {
×
NEW
60
            if (schema == null) return [];
×
61

NEW
62
            foreach (SchemaSearchEntry search in this.SchemaSearch.Entries) {
×
NEW
63
                if (search.SchemaNameIndex == schema.Index) {
×
NEW
64
                    List<DataEntry> data = [];
×
NEW
65
                    Dictionary<ulong, DataEntry> allDataEntries = this.DataFields
×
NEW
66
                        .SelectMany(x => x.Entries)
×
NEW
67
                        .Where(x => x.Header.SchemaIndex == schema.Index)
×
NEW
68
                        .GroupBy(x => x.Header.Handle)
×
NEW
69
                        .ToDictionary(x => x.Key, x => x.First());
×
70

NEW
71
                    foreach (SearchEntryObject[] entries in search.IdEntryObjects) {
×
NEW
72
                        foreach (SearchEntryObject entry in entries) {
×
NEW
73
                            if (entry.Indices.Length == 0) continue;        // TODO: Find out what this index really means (maybe index inside the data field entry where the item is?) and why there can be multiple arrays and why some have none at all
×
NEW
74
                            data.Add(allDataEntries[entry.Handle]);
×
NEW
75
                        }
×
NEW
76
                    }
×
NEW
77
                    return data;
×
78
                }
NEW
79
            }
×
80

NEW
81
            return [];
×
NEW
82
                }
×
83

84
                /// <summary>
85
                /// Get all <see cref="DataEntry"/> fields referenced by the given schema. 
86
                /// Known schema names are available as constants in the <see cref="Schema"/> class.
87
                /// To get all ACIS data stored in the <see cref="DataStorage"/> for example, pass <see cref="Schema.ACIS"/> as <paramref name="schemaName"/>
88
                /// </summary>
89
                /// <param name="schemaName">The schema name to get all data entries for</param>
90
                /// <returns>A list of all data entries referenced by the given schema</returns>
91
                public List<DataEntry> GetSchemaData(string schemaName)
NEW
92
                {
×
NEW
93
                        return this.GetSchemaData(this.GetSchemaByName(schemaName));
×
NEW
94
                }
×
95

96
                /// <summary>
97
                /// Checks if a data entry with the given handle exists in the <see cref="DataStorage"/>
98
                /// </summary>
99
                /// <param name="handle">The handle to check</param>
100
                /// <returns>Whether or not a data entry with the given handle exists</returns>
101
                public bool ContainsDataWithHandle(ulong handle)
NEW
102
                {
×
NEW
103
                        foreach (DataField field in this.DataFields) {
×
NEW
104
                                foreach (DataEntry entry in field.Entries) {
×
NEW
105
                                        if (entry.Header.Handle == handle) {
×
NEW
106
                                                return true;
×
107
                                        }
NEW
108
                                }
×
NEW
109
                        }
×
NEW
110
                        return false;
×
NEW
111
                }
×
112

113
                /// <summary>
114
                /// Get the bytes of the file stored by a data field with the given handle.
115
                /// If the entry references file blobs, they will be resolved.
116
                /// </summary>
117
                /// <param name="handle">The handle of the data entry to resolve</param>
118
                /// <returns>The bytes of the resolved data entry</returns>
119
                /// <exception cref="KeyNotFoundException"></exception>
120
                public byte[] GetDataByHandle(ulong handle)
NEW
121
                {
×
NEW
122
                        foreach (DataField field in this.DataFields) {
×
NEW
123
                                foreach (DataEntry entry in field.Entries) {
×
NEW
124
                                        if (entry.Header.Handle == handle) {
×
NEW
125
                                                return this.ResolveDataEntry(entry);
×
126
                                        }
NEW
127
                                }
×
NEW
128
                        }
×
129

NEW
130
                        throw new KeyNotFoundException($"Unable to find data in DataStorage for handle {handle}");
×
NEW
131
                }
×
132

133
                /// <summary>
134
                /// Get the bytes of the file stored by a data field with the given handle.
135
                /// If the entry references file blobs, they will be resolved.
136
                /// </summary>
137
                /// <param name="handle">The handle of the data entry to resolve</param>
138
                /// <param name="data">The bytes of the resolved data entry</param>
139
                /// <returns><see langword="true"/> when the handle was found and <paramref name="data"/> contains data otherwise <see langword="false"/></returns>
140
                public bool TryGetDataByHandle(ulong handle, out byte[] data)
NEW
141
                {
×
NEW
142
                        if (this.ContainsDataWithHandle(handle)) 
×
NEW
143
                        {
×
NEW
144
                                data = this.GetDataByHandle(handle);
×
NEW
145
                                return true;
×
146
                        }
NEW
147
                        data = null;
×
NEW
148
                        return false;
×
NEW
149
                }
×
150

151
                /// <summary>
152
                /// Resolve the bytes of the provided <see cref="DataEntry"/>. 
153
                /// If the entry references file blobs, they will be resolved.
154
                /// </summary>
155
                /// <param name="entry">The data entry to resolve</param>
156
                /// <returns>The bytes of the resolved data entry</returns>
157
                public byte[] ResolveDataEntry(DataEntry entry)
NEW
158
                {
×
NEW
159
                        byte[] bytes = entry.Value.Data;
×
NEW
160
                        if (entry.Value.BlobReference != null) {
×
NEW
161
                                List<Blob01> blobs = [];
×
NEW
162
                                foreach ((uint segidx, uint _size) in entry.Value.BlobReference.SegmentPointers) {
×
NEW
163
                                        blobs.Add(this.Blobs.First(b => b.Header.SegmentIndex == segidx));
×
NEW
164
                                }
×
165

166
                                // There could probably be instances of blob01 entries not being contiguous (only when a full blob01 segment would only contain zeros).
167
                                // blob01 segments have a max size of 0xFFFB0 bytes, meaning for a segment to be missing here, it would have to contain almost 1MB of 
168
                                // bytes with value 0. It is unknown whether this is even handled the same way as in the section map of the file header of a DWG file.
169

NEW
170
                                bytes = blobs.OrderBy(x => x.PageIndex).SelectMany(x => x.Data).ToArray();
×
NEW
171
                        }
×
NEW
172
                        return bytes;
×
NEW
173
                }
×
174

175
                /// <summary>
176
                /// Get the bytes of an embedded file with a given handle. 
177
                /// This can be the handle of a <see cref="ModelerGeometry"/> referencing an ACIS file or
178
                /// a handle for a thunbnail
179
                /// </summary>
180
                /// <param name="handle">The handle of the data entry to get</param>
181
                /// <returns>The bytes of the embedded file</returns>
182
                public byte[] this[ulong handle] 
183
                {
184
                        get 
NEW
185
                        {
×
NEW
186
                                return this.GetDataByHandle(handle);
×
NEW
187
                        }
×
188
                }
189

190
                /// <summary>
191
                /// Get the bytes of an embedded file for the given <see cref="ModelerGeometry"/>.
192
                /// </summary>
193
                /// <param name="geometry">The entity to get the stored file data for</param>
194
                /// <returns>The bytes of the embedded file</returns>
195
                public byte[] this[ModelerGeometry geometry]
196
                {
197
                        get
NEW
198
                        {
×
NEW
199
                                return this.GetDataByHandle(geometry.Handle);
×
NEW
200
                        }
×
201
                }
202
        }
203
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc