// Generated from executable documentation examples. Edit the source region, then regenerate. using System; using System.IO; using System.IO.Pipelines; using System.Linq; using System.Buffers; using System.Collections.Generic; using System.Dynamic; using System.Globalization; using System.Numerics; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using CStructSharp; using CStructSharp.Codecs; using CStructSharp.Diagnostics; using CStructSharp.Introspection; using CStructSharp.Values; internal static partial class Program { public static void Main() { HeaderPreprocessor(); Console.WriteLine("PASS header-preprocessor"); } private static void HeaderPreprocessor() { // Preprocessor lines and expression forms that appear in real headers: text and 64-bit defines are // published as constants, `#ifdef` selects declarations, and counts may use sizeof, offsetof, % and ?:. const string definition = """ #define MAGIC "CD001" #define BLOCK_MASK (1 << 40) #define LEGACY_VERSION 1 #ifdef WIDE_COUNTS typedef uint32 count_t; #else typedef uint16 count_t; #endif struct header { uint8 kind; uint32 length; }; struct root { count_t count; uint8 payload[count % 4 == 0 ? sizeof(header) : offsetof(header, length)]; }; """; var narrow = new CStruct(definition); Equal("CD001", narrow.Constants["MAGIC"].Value); Equal(BigInteger.One << 40, narrow.Constants["BLOCK_MASK"].Value); Equal(LayoutConstantKind.Integer, narrow.Constants["LEGACY_VERSION"].Kind); StructValue aligned = narrow.Parse(new byte[] { 4, 0, 1, 2, 3, 4, 5 }, "root"); Equal(5, aligned.Get("payload").Length); StructValue unaligned = narrow.Parse(new byte[] { 3, 0, 1 }, "root"); Equal(1, unaligned.Get("payload").Length); // The same source compiled with a -D style definition takes the other branch and is its own cache entry. var wide = CStruct.GetOrCompile(definition, compilationOptions: new CStructCompilationOptions { Defined = new HashSet { "WIDE_COUNTS" } }); Equal(4, wide.Layout.Declarations.Single(item => item.Name == "root").Fields[0].Size!.Value); } private static void Equal(T expected, T actual) { if (!EqualityComparer.Default.Equals(expected, actual)) { throw new InvalidOperationException($"Expected '{expected}', received '{actual}'."); } } }