private static IEnumerable <ExtractedString> Extract(Stream data, long base_offset, int minimum_length, ExtractedStringType type, string source)
        {
            if (data is null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (minimum_length <= 0)
            {
                throw new ArgumentException("Must specify a minimum length of at least 1.");
            }

            StringBuilder ascii             = new StringBuilder();
            StringBuilder unicode           = new StringBuilder();
            StringBuilder unicode_unaligned = new StringBuilder();
            bool          parse_ascii       = type.HasFlagSet(ExtractedStringType.Ascii);
            bool          parse_unicode     = type.HasFlagSet(ExtractedStringType.Unicode);

            byte[] unicode_char = new byte[2];
            int    b            = data.ReadByte();
            long   i            = 0;

            while (b >= 0)
            {
                if (parse_ascii)
                {
                    char c = (char)b;
                    if (IsPrintable(c))
                    {
                        ascii.Append(c);
                    }
                    else
                    {
                        if (ascii.Length >= minimum_length)
                        {
                            yield return(ascii.CreateResult(base_offset, i, ExtractedStringType.Ascii, source));
                        }
                        ascii.Clear();
                    }
                }
                if (parse_unicode)
                {
                    unicode_char[0] = unicode_char[1];
                    unicode_char[1] = (byte)b;
                    char c = BitConverter.ToChar(unicode_char, 0);
                    if ((i & 1) == 1)
                    {
                        if (IsPrintable(c))
                        {
                            unicode.Append(c);
                        }
                        else
                        {
                            if (unicode.Length >= minimum_length)
                            {
                                yield return(unicode.CreateResult(base_offset, i, ExtractedStringType.Unicode, source));
                            }
                            unicode.Clear();
                        }
                    }
                    else if (i > 1)
                    {
                        if (IsPrintable(c))
                        {
                            unicode_unaligned.Append(c);
                        }
                        else
                        {
                            if (unicode_unaligned.Length >= minimum_length)
                            {
                                yield return(unicode_unaligned.CreateResult(base_offset, i, ExtractedStringType.Unicode, source));
                            }
                            unicode_unaligned.Clear();
                        }
                    }
                }

                i++;
                b = data.ReadByte();
            }

            if (ascii.Length >= minimum_length)
            {
                yield return(ascii.CreateResult(base_offset, i, ExtractedStringType.Ascii, source));
            }

            if (unicode.Length >= minimum_length)
            {
                yield return(unicode.CreateResult(base_offset, i, ExtractedStringType.Unicode, source));
            }

            if (unicode_unaligned.Length >= minimum_length)
            {
                yield return(unicode_unaligned.CreateResult(base_offset, i, ExtractedStringType.Unicode, source));
            }
        }
        private static ExtractedString CreateResult(this StringBuilder builder, long base_offset, long i, ExtractedStringType type, string source)
        {
            int str_length = type.HasFlagSet(ExtractedStringType.Unicode) ? (builder.Length * 2 + 1) : builder.Length;

            return(new ExtractedString(builder.ToString(), base_offset + i - str_length, type, source));
        }