public static List <ImageSelfDefiningField> GetAllSDFs(byte[] sdfData) { List <ImageSelfDefiningField> sdfList = new List <ImageSelfDefiningField>(); // Container info byte[] beginCodes = new byte[4] { 0x70, 0x8C, 0x8E, 0x91 }; byte[] endCodes = new byte[4] { 0x71, 0x8D, 0x8F, 0x93 }; List <Container> activeContainers = new List <Container>(); for (int i = 0; i < sdfData.Length;) { // Check the first byte of the code. If it's 0xFE, this is an extended format SDF and will have two byte codes and lengths instead of one bool isExtended = sdfData[i] == 0xFE; // Get the ID, length, introducer, and data bytes byte[] idArray = isExtended ? new byte[2] { 0xFE, sdfData[i + 1] } : new byte[1] { sdfData[i] }; byte id = idArray.Last(); int length = isExtended ? GetNumericValue <ushort>(new[] { sdfData[i + 2], sdfData[i + 3] }) : GetNumericValue <byte>(new[] { sdfData[i + 1] }); byte[] data = new byte[length]; Array.ConstrainedCopy(sdfData, i + (isExtended ? 4 : 2), data, 0, length); // Create an instance of the lookup type Type iSDFType = typeof(ImageSelfDefiningFields.UNKNOWN); if (Lookups.ImageSelfDefiningFields.ContainsKey(id)) { iSDFType = Lookups.ImageSelfDefiningFields[id]; } ImageSelfDefiningField sdf = (ImageSelfDefiningField)Activator.CreateInstance(iSDFType, idArray, data); // If this is a begin tag, add a new container to our active list if (beginCodes.Contains(id)) { activeContainers.Add(new Container()); } // Sync active containers sdf.Containers = new List <Container>(activeContainers); // Add this field to all containers foreach (Container c in activeContainers) { c.Structures.Add(sdf); } // If this is the last structure in a container, close it up and parse any specific container data if (endCodes.Contains(id)) { Container c = activeContainers.Last(); activeContainers.Remove(c); } sdfList.Add(sdf); // Go to next block i += (isExtended ? 4 : 2) + length; } return(sdfList); }
// This method can be overridden if it is complicated to parse protected override string GetOffsetDescriptions() { StringBuilder sb = new StringBuilder(); if (Offsets.Count == 0) { sb.AppendLine("Not yet implemented..."); sb.AppendLine(); sb.AppendLine("Raw data:"); sb.AppendLine(DataHex); sb.AppendLine(); sb.AppendLine("Raw data (EBCDIC):"); sb.Append(DataEBCDIC); return(sb.ToString()); } // If this is a repeating group identifier, loop through each subsection of offsets int skip = IsRepeatingGroup ? RepeatingGroupStart : Offsets[0].StartingIndex; int sectionLength = RepeatingGroupLength; do { for (int i = 0; i < Offsets.Count; i++) { // If we are past the data length, break out of the loop if (skip > Data.Length) { break; } // Get the length of the current repeating group if it is retrieved in each section (if there is not a fixed length) if (IsRepeatingGroup && RepeatingGroupLength == 0 && i == 0) { int rgOffsetLength = Offsets[i + 1].StartingIndex; sectionLength = GetNumericValueFromData <int>(skip, rgOffsetLength); } // Calculate section of bytes to take from data int nextOffsetIdx = i == Offsets.Count - 1 ? 0 : Offsets[i + 1].StartingIndex; int take = (nextOffsetIdx == 0 ? sectionLength : nextOffsetIdx) - Offsets[i].StartingIndex; byte[] sectionedData = GetSectionedData(skip, take); // Build description by data type switch (Offsets[i].DataType) { // For special sub sectioned data types, call the static parser case Lookups.DataTypes.IMAGESDFS: if (i > 0) { sb.AppendLine(); } sb.AppendLine(ImageSelfDefiningField.GetAllDescriptions(sectionedData)); break; // For Triplets, parse them all at once case Lookups.DataTypes.TRIPS: sb.AppendLine(); foreach (Triplet t in Triplets) { sb.AppendLine(t.GetFullDescription()); } break; // Everything else default: sb.Append(GetSingleOffsetDescription(Offsets[i], sectionedData)); break; } // Increment the skip value so we take the correct offset of data next iteration skip += take; } sb.AppendLine(); } while (skip < Data.Length); return(sb.ToString().Trim()); }