コード例 #1
0
        /// <summary>
        /// Adds slashes before characters '\\', '\0', '\'' and '"'.
        /// </summary>
        /// <param name="str">The string to add slashes in.</param>
        /// <param name="doubleQuotes">Whether to slash double quotes.</param>
        /// <param name="singleQuotes">Whether to slash single quotes.</param>
        /// <param name="nul">Whether to slash '\0' character.</param>
        /// <returns>The slashed string.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="str"/> is a <B>null</B> reference.</exception>
        public static string /*!*/ AddCSlashes(string /*!*/ str, bool singleQuotes = true, bool doubleQuotes = true, bool nul = true)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            var result = StringBuilderUtilities.Pool.Get();

            string double_quotes = doubleQuotes ? "\\\"" : "\"";
            string single_quotes = singleQuotes ? @"\'" : "'";
            string slashed_nul   = nul ? "\\0" : "\0";

            for (int i = 0; i < str.Length; i++)
            {
                char c = str[i];
                switch (c)
                {
                case '\\': result.Append(@"\\"); break;

                case '\0': result.Append(slashed_nul); break;

                case '\'': result.Append(single_quotes); break;

                case '"': result.Append(double_quotes); break;

                default: result.Append(c); break;
                }
            }

            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #2
0
ファイル: FileSystem.Glob.cs プロジェクト: kendallb/peachpie
            private static string /*!*/ Unescape(string /*!*/ path, int start)
            {
                var unescaped = StringBuilderUtilities.Pool.Get();
                var inEscape  = false;

                for (int i = start; i < path.Length; i++)
                {
                    var c = path[i];
                    if (inEscape)
                    {
                        inEscape = false;
                    }
                    else if (c == '\\')
                    {
                        inEscape = true;
                        continue;
                    }
                    unescaped.Append(c);
                }

                if (inEscape)
                {
                    unescaped.Append('\\');
                }

                //
                return(StringBuilderUtilities.GetStringAndReturn(unescaped));
            }
コード例 #3
0
                public static string Serialize(Context ctx, PhpValue variable, JsonEncodeOptions encodeOptions, RuntimeTypeHandle caller)
                {
                    var str = StringBuilderUtilities.Pool.Get();

                    variable.Accept(new ObjectWriter(ctx, str, encodeOptions, caller));

                    return(StringBuilderUtilities.GetStringAndReturn(str)); // note: str is cleared
                }
コード例 #4
0
            public bool Parse(string input, bool isFinal)
            {
                // the problem is when isFinal == false
                // XmlReader (more precisely XmlTextReaderImpl) synchronously waits for data from underlying stream when Read is called
                // and there is no way to tell whether we have sufficient amount of data for the next Read call
                // and if underlying stream ends prematurely, reader will get into Error state (so these simple workarounds are not possible)

                // current solution caches the data until isFinal == true and then performs the parsing
                // this is not memory efficient (usually this method gets called in a cycle on small chunks to save memory)

                // other way would be to let the reader wait on another thread (in thread pool), which would not be that bad
                // since XmlParser gets freed eventually

                // theoretically the best way would be to implement XmlReader, that would be able to recognize whether there is enough
                // data, but we have not further analyzed this possibility since it seems to result in unappropriate amount of work

                // yet another possible way is to use parser for inner element, and let it come into error state (not tested or thought through)
                // this does not work since inner parser can only be created when the parser reads an element (not in the beginning)

                if (isFinal)
                {
                    input ??= string.Empty;
                    var sb = StringBuilderUtilities.Pool.Get();

                    if (_inputQueue != null)
                    {
                        foreach (string s in _inputQueue)
                        {
                            sb.Append(s);
                        }

                        _inputQueue = null;
                    }

                    sb.Append(input);

                    return(ParseInternal(StringBuilderUtilities.GetStringAndReturn(sb), null, null));
                }
                else
                {
                    //just reset these values - we are still in the beginning
                    CurrentLineNumber   = 0;
                    CurrentColumnNumber = 0;

                    if (!string.IsNullOrEmpty(input))
                    {
                        if (_inputQueue == null)
                        {
                            _inputQueue = new Queue <string>();
                        }

                        _inputQueue.Enqueue(input);
                    }

                    return(true);
                }
            }
コード例 #5
0
        static string ToString(Rational num, int scale)
        {
            var numerator   = BigInteger.Abs(num.Numerator);
            var denominator = BigInteger.Abs(num.Denominator);
            var hasdecimal  = false;

            var result = StringBuilderUtilities.Pool.Get();

            if (num.Sign < 0)
            {
                result.Append('-');
            }

            for (; ;)
            {
                var number = BigInteger.DivRem(numerator, denominator, out var rem);
                if (number >= 10)
                {
                    var digits = number.ToString(NumberFormatInfo.InvariantInfo);
                    result.Append(digits);
                }
                else
                {
                    Debug.Assert(number >= 0);
                    result.Append((char)('0' + (int)number));
                }

                if (scale <= 0)
                {
                    break;
                }

                // .
                if (!hasdecimal)
                {
                    hasdecimal = true;
                    result.Append(NumberFormatInfo.InvariantInfo.NumberDecimalSeparator);
                }

                // done?
                if (rem.IsZero)
                {
                    result.Append('0', scale);
                    break;
                }

                // next decimals
                numerator = rem * 10;
                scale--;
            }

            //
            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #6
0
ファイル: ErrorsHelper.cs プロジェクト: kendallb/peachpie
        /// <summary>
        /// Gets stack trace as string.
        /// </summary>
        public static string GetStackTraceString(this PhpStackTrace trace, int skip = 0)
        {
            var result = StringBuilderUtilities.Pool.Get();
            var lines  = trace.GetLines();

            for (int i = 1 + skip, order = 0; i < lines.Length; i++, order++)
            {
                lines[i].GetStackTraceLine(order, result);
                result.AppendLine();
            }

            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #7
0
        /// <summary>
        /// Strips slashes from a string.
        /// </summary>
        /// <param name="str">String.</param>
        /// <returns>
        /// String where slashes are striped away.
        /// Slashed characters with special meaning ("\0") are replaced with their special value.
        /// </returns>
        public static string /*!*/ StripCSlashes(string /*!*/ str)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            if (str.Length == 0)
            {
                return(string.Empty);
            }

            var result = StringBuilderUtilities.Pool.Get();
            int from   = 0; // plain chunk start

            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == '\\')
                {
                    //
                    result.Append(str, from, i - from);

                    //
                    if (++i < str.Length)
                    {
                        // PHP strips all slashes, not only quotes and slash
                        // "\0" has a special meaning => '\0'
                        var slashed = str[i];
                        result.Append(slashed == '0' ? '\0' : slashed);
                    }

                    from = i + 1;
                }
            }

            //
            if (from < str.Length)
            {
                result.Append(str, from, str.Length - from);
            }

            //
            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #8
0
        /// <summary>
        /// Quote regular expression characters.
        /// </summary>
        /// <remarks>
        /// The special regular expression characters are: . \ + * ? [ ^ ] $ ( ) { } = ! &lt; &gt; | : -
        /// Note that / is not a special regular expression character.
        /// </remarks>
        /// <param name="str">The string to be escaped.</param>
        /// <param name="delimiter">If the optional delimiter is specified, it will also be escaped.
        /// This is useful for escaping the delimiter that is required by the PCRE functions. The / is the most commonly used delimiter.</param>
        public static string preg_quote(string str, string delimiter = null)
        {
            if (string.IsNullOrEmpty(str))
            {
                return(str);
            }

            char delimiterChar = string.IsNullOrEmpty(delimiter)
                ? char.MaxValue // unused (?)
                : delimiter[0];

            StringBuilder result     = null;
            int           lastEscape = 0;

            for (int i = 0; i < str.Length; i++)
            {
                char ch     = str[i];
                bool escape = ch == delimiterChar || IsDelimiterChar(ch);

                if (escape)
                {
                    if (result == null)
                    {
                        result = StringBuilderUtilities.Pool.Get();
                    }

                    result.Append(str, lastEscape, i - lastEscape);
                    result.Append('\\');
                    lastEscape = i;
                }
            }

            if (result != null)
            {
                result.Append(str, lastEscape, str.Length - lastEscape);
                return(StringBuilderUtilities.GetStringAndReturn(result));
            }
            else
            {
                return(str);
            }
        }
コード例 #9
0
ファイル: ErrorsHelper.cs プロジェクト: kendallb/peachpie
        /// <summary>
        /// Gets exception string.
        /// </summary>
        public static string FormatExceptionString(this PhpStackTrace trace, string exceptionname, string message)
        {
            var result = StringBuilderUtilities.Pool.Get();

            // TODO: texts to resources

            // {exceptionname} in {location}
            // Stack trace:
            // #0 ...
            var lines = trace.GetLines();

            result.Append(exceptionname);

            if (!string.IsNullOrEmpty(message))
            {
                result.Append(": ");
                result.Append(message);
            }

            if (lines.Length != 0)
            {
                if (lines[0].HasLocation)
                {
                    result.Append(" in ");
                    lines[0].GetStackTraceLine(-1, result);
                }

                if (lines.Length > 1)
                {
                    result.AppendLine();
                    result.AppendLine("Stack trace:");
                    for (int i = 1; i < lines.Length; i++)
                    {
                        lines[i].GetStackTraceLine(i - 1, result);
                        result.AppendLine();
                    }
                }
            }

            //
            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #10
0
        /// <summary>
        /// Replaces slashed 0 with null character ('\0') and double apostrophe with single apostrophe.
        /// </summary>
        /// <param name="str">String.</param>
        /// <returns>String with replaced characters.</returns>
        public static string /*!*/ StripDbSlashes(string /*!*/ str)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            var result = StringBuilderUtilities.Pool.Get();

            int i = 0;

            while (i < str.Length - 1)
            {
                if (str[i] == '\\' && str[i + 1] == '0')
                {
                    result.Append('\0');
                    i += 2;
                }
                else if (str[i] == '\'' && str[i + 1] == '\'')
                {
                    result.Append('\'');
                    i += 2;
                }
                else
                {
                    result.Append(str[i]);
                    i++;
                }
            }
            if (i < str.Length)
            {
                result.Append(str[i]);
            }

            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #11
0
        /// <summary>
        /// Adds slash before '\0' character and duplicates apostrophes.
        /// </summary>
        /// <param name="str">The string to add slashes in.</param>
        /// <returns>The slashed string.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="str"/> is a <B>null</B> reference.</exception>
        public static string /*!*/ AddDbSlashes(string /*!*/ str)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            StringBuilder result = StringBuilderUtilities.Pool.Get();

            for (int i = 0; i < str.Length; i++)
            {
                char c = str[i];
                switch (c)
                {
                case '\0': result.Append('\\'); result.Append('0'); break;

                case '\'': result.Append('\''); result.Append('\''); break;

                default: result.Append(c); break;
                }
            }

            return(StringBuilderUtilities.GetStringAndReturn(result));
        }
コード例 #12
0
        private static string DoubleToBase(double number, int toBase)
        {
            if (toBase < 2 || toBase > 36)
            {
                PhpException.InvalidArgument(nameof(toBase), Resources.LibResources.arg_out_of_bounds);
                return(null); // FALSE
            }

            // Don't try to convert infinity or NaN:
            if (double.IsInfinity(number) || double.IsNaN(number))
            {
                PhpException.InvalidArgument(nameof(number), Resources.LibResources.arg_out_of_bounds);
                return(null); // FALSE
            }

            double fvalue = Math.Floor(number); /* floor it just in case */

            if (Math.Abs(fvalue) < 1)
            {
                return("0");
            }

            var sb = StringBuilderUtilities.Pool.Get();

            while (Math.Abs(fvalue) >= 1)
            {
                double mod = fmod(fvalue, toBase);
                int    i   = (int)mod;
                char   c   = digitsUnicode[i];
                //sb.Append(digits[(int) fmod(fvalue, toBase)]);
                sb.Append(c);
                fvalue /= toBase;
            }

            return(Core.Utilities.StringUtils.Reverse(StringBuilderUtilities.GetStringAndReturn(sb)));
        }
コード例 #13
0
        /// <summary>
        /// Unpacks data from a string of bytes into <see cref="PhpArray"/>.
        /// </summary>
        /// <param name="ctx">Runtime context.</param>
        /// <param name="format">The string defining the items of the result. See PHP manual for details.</param>
        /// <param name="data">The string of bytes to be unpacked.</param>
        /// <returns>The <see cref="PhpArray"/> containing unpacked data.</returns>
        public static PhpArray unpack(Context ctx, string format, PhpString data)
        {
            if (format == null)
            {
                return(null);
            }
            byte[] buffer = data.ToBytes(ctx);

            var encoding = ctx.StringEncoding;

            byte[] reversed = new byte[4]; // used for reversing the order of bytes in buffer

            int      i      = 0;
            int      pos    = 0;
            PhpArray result = new PhpArray();

            while (i < format.Length)
            {
                string name;
                int    repeater;
                char   specifier;

                // parses specifier, repeater, and name from the format string:
                ParseFormatToken(format, ref i, out specifier, out repeater, out name);

                int remains = buffer.Length - pos;          // the number of bytes remaining in the buffer
                int size;                                   // a size of data to be extracted corresponding to the specifier

                // repeater of '@' specifier has a special meaning:
                if (specifier == '@')
                {
                    if (repeater > buffer.Length || repeater == InfiniteRepeater)
                    {
                        PhpException.Throw(PhpError.Warning, LibResources.GetString("outside_string", specifier));
                    }
                    else
                    {
                        pos = repeater;
                    }

                    continue;
                }

                // number of operations:
                int op_count;

                // gets the size of the data to read and adjust repeater:
                if (!GetSizeToUnpack(specifier, remains, repeater, out op_count, out size))
                {
                    PhpException.Throw(PhpError.Warning, LibResources.GetString("unknown_format_code", specifier));
                    return(null);
                }

                // repeats operation determined by specifier "op_count" times;
                // if op_count is infinite then stops when the number of remaining characters is zero:
                for (int j = 0; j < op_count || op_count == InfiniteRepeater; j++)
                {
                    if (size > remains)
                    {
                        // infinite means "while data are available":
                        if (op_count == InfiniteRepeater)
                        {
                            break;
                        }

                        PhpException.Throw(PhpError.Warning, LibResources.GetString("not_enought_input", specifier, size, remains));
                        return(null);
                    }

                    PhpValue item;
                    switch (specifier)
                    {
                    case 'X':     // decreases position, no value stored:
                        if (pos == 0)
                        {
                            PhpException.Throw(PhpError.Warning, LibResources.GetString("outside_string", specifier));
                        }
                        else
                        {
                            pos--;
                        }
                        continue;

                    case 'x':     // advances position, no value stored
                        pos++;
                        continue;

                    case 'a':     // NUL-padded string
                    case 'A':     // SPACE-padded string
                    {
                        byte pad = (byte)(specifier == 'a' ? 0x00 : 0x20);

                        int last = pos + size - 1;
                        while (last >= pos && buffer[last] == pad)
                        {
                            last--;
                        }

                        item = (PhpValue)encoding.GetString(buffer, pos, last - pos + 1);
                        break;
                    }

                    case 'h':     // Hex string, low/high nibble first - converts to a string, takes n hex digits from string:
                    case 'H':
                    {
                        int p            = pos;
                        int nibble_shift = (specifier == 'h') ? 0 : 4;

                        var sb = StringBuilderUtilities.Pool.Get();
                        for (int k = 0; k < size; k++)
                        {
                            const string hex_digits = "0123456789ABCDEF";

                            sb.Append(hex_digits[(buffer[p] >> nibble_shift) & 0x0f]);

                            // beware of odd repeaters!
                            if (repeater == InfiniteRepeater || repeater > sb.Length)
                            {
                                sb.Append(hex_digits[(buffer[p] >> (4 - nibble_shift)) & 0x0f]);
                            }
                            p++;
                        }

                        item = StringBuilderUtilities.GetStringAndReturn(sb);
                        break;
                    }

                    case 'c':     // signed char
                        item = (PhpValue)(int)unchecked ((sbyte)buffer[pos]);
                        break;

                    case 'C':     // unsigned char
                        item = (PhpValue)(int)buffer[pos];
                        break;

                    case 's':     // signed short (always 16 bit, machine byte order)
                        item = (PhpValue)(int)BitConverter.ToInt16(buffer, pos);
                        break;

                    case 'S':     // unsigned short (always 16 bit, machine byte order)
                        item = (PhpValue)(int)BitConverter.ToUInt16(buffer, pos);
                        break;

                    case 'n':     // unsigned short (always 16 bit, big endian byte order)
                        if (BitConverter.IsLittleEndian)
                        {
                            item = (PhpValue)(int)BitConverter.ToUInt16(LoadReverseBuffer(reversed, buffer, pos, 2), 0);
                        }
                        else
                        {
                            item = (PhpValue)(int)BitConverter.ToUInt16(buffer, pos);
                        }
                        break;

                    case 'v':     // unsigned short (always 16 bit, little endian byte order)
                        if (!BitConverter.IsLittleEndian)
                        {
                            item = (PhpValue)(int)BitConverter.ToUInt16(LoadReverseBuffer(reversed, buffer, pos, 2), 0);
                        }
                        else
                        {
                            item = (PhpValue)(int)BitConverter.ToUInt16(buffer, pos);
                        }
                        break;

                    case 'i':     // signed integer (machine dependent size and byte order - always 32 bit)
                    case 'I':     // unsigned integer (machine dependent size and byte order - always 32 bit)
                    case 'l':     // signed long (always 32 bit, machine byte order)
                    case 'L':     // unsigned long (always 32 bit, machine byte order)
                        item = (PhpValue)BitConverter.ToInt32(buffer, pos);
                        break;

                    case 'N':     // unsigned long (always 32 bit, big endian byte order)
                        item = (PhpValue) unchecked (((int)buffer[pos] << 24) + (buffer[pos + 1] << 16) + (buffer[pos + 2] << 8) + buffer[pos + 3]);
                        break;

                    case 'V':     // unsigned long (always 32 bit, little endian byte order)
                        item = (PhpValue) unchecked (((int)buffer[pos + 3] << 24) + (buffer[pos + 2] << 16) + (buffer[pos + 1] << 8) + buffer[pos + 0]);
                        break;

                    case 'f':     // float (machine dependent size and representation - size is always 4B)
                        item = (PhpValue)(double)BitConverter.ToSingle(buffer, pos);
                        break;

                    case 'd':     // double (machine dependent size and representation - size is always 8B)
                        item = (PhpValue)BitConverter.ToDouble(buffer, pos);
                        break;

                    default:
                        Debug.Fail("Invalid specifier.");
                        return(null);
                    }

                    AddValue(result, name, item, op_count, j);

                    pos     += size;
                    remains -= size;
                }
            }

            return(result);
        }
コード例 #14
0
ファイル: Shell.cs プロジェクト: kendallb/peachpie
        public static int ShellExec(Context ctx, string command, OutputHandling handling, PhpArray?arrayOutput, out string?stringOutput)
        {
            if (!MakeCommandSafe(ref command))
            {
                stringOutput = null;
                return(-1);
            }

            using (var p = new Process())
            {
                //IdentitySection identityConfig = null;

                //try { identityConfig = WebConfigurationManager.GetSection("system.web/identity") as IdentitySection; }
                //catch { }

                //if (identityConfig != null)
                //{
                //    p.StartInfo.UserName = identityConfig.UserName;
                //    if (identityConfig.Password != null)
                //    {
                //        p.StartInfo.Password = new SecureString();
                //        foreach (char c in identityConfig.Password) p.StartInfo.Password.AppendChar(c);
                //        p.StartInfo.Password.MakeReadOnly();
                //    }
                //}

                // prepare arguments
                {
                    var arguments = StringBuilderUtilities.Pool.Get();

                    if (CurrentPlatform.IsWindows)
                    {
                        p.StartInfo.FileName = "cmd.exe";
                        AppendArgument(arguments, "/c");
                    }
                    else
                    {
                        p.StartInfo.FileName = "/bin/bash";
                        AppendArgument(arguments, "-c");
                    }

                    AppendArgument(arguments, command);

                    p.StartInfo.Arguments = StringBuilderUtilities.GetStringAndReturn(arguments);
                }

                p.StartInfo.UseShellExecute        = false;
                p.StartInfo.CreateNoWindow         = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.Start();

                stringOutput = null;
                switch (handling)
                {
                case OutputHandling.String:
                    stringOutput = p.StandardOutput.ReadToEnd();
                    break;

                case OutputHandling.ArrayOfLines:
                {
                    string line;
                    while ((line = p.StandardOutput.ReadLine()) != null)
                    {
                        arrayOutput?.Add(line);
                        stringOutput = line;
                    }
                    break;
                }

                case OutputHandling.FlushLinesToScriptOutput:
                {
                    string line;
                    while ((line = p.StandardOutput.ReadLine()) != null)
                    {
                        stringOutput = line;
                        ctx.Output.WriteLine(line);
                        ctx.Output.Flush();
                    }
                    break;
                }

                case OutputHandling.RedirectToScriptOutput:
                    p.StandardOutput.BaseStream
                    .CopyToAsync(ctx.OutputStream)
                    .GetAwaiter()
                    .GetResult();

                    break;
                }

                p.WaitForExit();

                //
                return(p.ExitCode);
            }
        }
コード例 #15
0
ファイル: CharMap.cs プロジェクト: wowngasb/peachpie
        /// <summary>
        /// Accumulates all characters contained or not contained in the set to the string in ascending order.
        /// </summary>
        /// <param name="first">The lower bound.</param>
        /// <param name="last">The upper bound.</param>
        /// <param name="complement">Whether to return characters not contained in the string.</param>
        /// <returns>
        /// Depending on the value of the <paramref name="complement"/> the method returns the string of characters in
        /// this instance and a complement of this instance, respectively, intersected with the
        /// [<paramref name="first"/>; <paramref name="last"/>] interval.
        /// </returns>
        /// <exception cref="IndexOutOfRangeException"><paramref name="first"/> or <paramref name="last"/> are not mapped by this instance.</exception>
        public string ToString(char first, char last, bool complement)
        {
            if (first > last)
            {
                //throw new ArgumentException(CoreResources.GetString("last_is_less_than_first"));
                throw new NotImplementedException();
            }

            int modf = first & 0x1f;
            int modl = last & 0x1f;
            int f    = first >> 5;
            int l    = last >> 5;

            // an optimization:
            if (l > lastDirty && !complement)
            {
                // sets upper bound to the last bit in the lastDirty block:
                l    = lastDirty;
                modl = 31;

                // the whole interval is beyond the last set bit:
                if (f > l)
                {
                    return(String.Empty);
                }
            }

            // if complementary set is required, we xor each item of the "flags" array by the "invert_equality"
            // and so invert the result of comparison with zero in the following if statement:
            uint invert_inequality = (complement) ? 0xffffffffU : 0U;
            uint flg;
            char c      = first;
            var  result = StringBuilderUtilities.Pool.Get();

            if (f == l)
            {
                // the "first" and the "last" points to the same block:
                flg = flags[f] ^ invert_inequality;
                for (uint mask = (0x80000000U >> modf); mask > (0x80000000U >> modl); mask >>= 1)
                {
                    if ((flg & mask) != 0)
                    {
                        result.Append(c);
                    }
                    c++;
                }
            }
            else
            {
                // the first block:
                flg = flags[f] ^ invert_inequality;
                for (uint mask = 0x80000000U >> modf; mask != 0; mask >>= 1)
                {
                    if ((flg & mask) != 0)
                    {
                        result.Append(c);
                    }
                    c++;
                }

                // middle blocks (if any):
                for (int i = f + 1; i < l; i++)
                {
                    flg = flags[i] ^ invert_inequality;
                    for (uint mask = 0x80000000U; mask != 0; mask >>= 1)
                    {
                        if ((flg & mask) != 0)
                        {
                            result.Append(c);
                        }
                        c++;
                    }
                }

                // the last block:
                flg = flags[l] ^ invert_inequality;
                for (uint mask = 0x80000000U; mask >= (0x80000000U >> modl); mask >>= 1)
                {
                    if ((flg & mask) != 0)
                    {
                        result.Append(c);
                    }
                    c++;
                }
            }

            //
            return(StringBuilderUtilities.GetStringAndReturn(result));
        }