haxe/src/StringTools.cs
// Patched for s&box whitelist mode: remove System.ComponentModel usage and avoid regex/sys helpers.
// Compatible surface for Haxe 4.3.x hxcs runtime.

// Generated by Haxe 4.3.7 (patched)

#pragma warning disable 109, 114, 219, 429, 168, 162
public class StringTools : global::haxe.lang.HxObject
{
    static StringTools()
    {
        unchecked
        {
            // Avoid referencing haxe.SysTools.winMetaCharacters (may pull disallowed APIs).
            // Keep field initialized so code compiles and runs.
            global::StringTools.winMetaCharacters = new global::Array<int>(new int[] { });
            global::StringTools.MIN_SURROGATE_CODE_POINT = 65536;
        }
    }

    public StringTools(global::haxe.lang.EmptyObject empty) { }

    public StringTools()
    {
        global::StringTools.__hx_ctor__StringTools(this);
    }

    protected static void __hx_ctor__StringTools(global::StringTools __hx_this) { }

    public static string urlEncode(string s)
    {
        return global::System.Uri.EscapeDataString((string)(s));
    }

    public static string urlDecode(string s)
    {
        return global::System.Uri.UnescapeDataString((string)(s));
    }

    public static string htmlEscape(string s, global::haxe.lang.Null<bool> quotes)
    {
        unchecked
        {
            global::StringBuf buf = new global::StringBuf();
            global::haxe.iterators.StringIteratorUnicode _g = new global::haxe.iterators.StringIteratorUnicode((string)(s));
            while (_g.hasNext())
            {
                int code = _g.next();
                switch (code)
                {
                    case 34: // "
                        if ((quotes).hasValue && (quotes).@value)
                            buf.@add<string>((string)("&quot;"));
                        else
                            buf.addChar(code);
                        break;

                    case 38: // &
                        buf.@add<string>((string)("&amp;"));
                        break;

                    case 39: // '
                        if ((quotes).hasValue && (quotes).@value)
                            buf.@add<string>((string)("&#039;"));
                        else
                            buf.addChar(code);
                        break;

                    case 60: // <
                        buf.@add<string>((string)("&lt;"));
                        break;

                    case 62: // >
                        buf.@add<string>((string)("&gt;"));
                        break;

                    default:
                        buf.addChar(code);
                        break;
                }
            }

            return buf.toString();
        }
    }

	public static string htmlUnescape(string s)
	{
		s = global::haxe.lang.StringExt.split(s, "&gt;").@join(">");
		s = global::haxe.lang.StringExt.split(s, "&lt;").@join("<");
		s = global::haxe.lang.StringExt.split(s, "&quot;").@join("\"");
		s = global::haxe.lang.StringExt.split(s, "&#039;").@join("\'");
		s = global::haxe.lang.StringExt.split(s, "&amp;").@join("&");
		return s;
	}

    public static bool contains(string s, string @value)
    {
        unchecked
        {
            return (global::haxe.lang.StringExt.indexOf(s, @value, default(global::haxe.lang.Null<int>)) != -1);
        }
    }

    public static bool startsWith(string s, string start)
    {
        return s.StartsWith(start);
    }

    public static bool endsWith(string s, string end)
    {
        return s.EndsWith(end);
    }

    public static bool isSpace(string s, int pos)
    {
        unchecked
        {
            global::haxe.lang.Null<int> c = global::haxe.lang.StringExt.charCodeAt(s, pos);
            if (!c.hasValue)
                return false;

            int cv = c.@value;
            if (!(((cv > 8) && (cv < 14))))
                return global::haxe.lang.Runtime.eq((c).toDynamic(), 32);
            return true;
        }
    }

    public static string ltrim(string s) => s.TrimStart();

    public static string rtrim(string s) => s.TrimEnd();

    public static string trim(string s) => s.Trim();

    public static string lpad(string s, string c, int l)
    {
        if (c.Length <= 0) return s;

        global::StringBuf buf = new global::StringBuf();
        l -= s.Length;
        while (buf.get_length() < l)
            buf.@add<string>((string)(c));

        buf.@add<string>((string)(s));
        return buf.toString();
    }

    public static string rpad(string s, string c, int l)
    {
        if (c.Length <= 0) return s;

        global::StringBuf buf = new global::StringBuf();
        buf.@add<string>((string)(s));
        while (buf.get_length() < l)
            buf.@add<string>((string)(c));

        return buf.toString();
    }

    public static string replace(string s, string sub, string @by)
    {
        if (sub.Length == 0)
            return global::haxe.lang.StringExt.split(s, sub).@join(@by);

        return s.Replace(sub, @by);
    }

    public static string hex(int n, global::haxe.lang.Null<int> digits)
    {
        unchecked
        {
            string s = "";
            string hexChars = "0123456789ABCDEF";
            do
            {
                s = global::haxe.lang.Runtime.concat(global::haxe.lang.StringExt.charAt(hexChars, (n & 15)), s);
                n = (int)(((uint)n) >> 4);
            }
            while (n > 0);

            if (digits.hasValue)
            {
                while (s.Length < (digits).@value)
                    s = global::haxe.lang.Runtime.concat("0", s);
            }

            return s;
        }
    }

    public static int fastCodeAt(string s, int index)
    {
        unchecked
        {
            if (((uint)index) < s.Length)
                return (int)(s[index]);

            return -1;
        }
    }

    public static int unsafeCodeAt(string s, int index)
    {
        return (int)(s[index]);
    }

    public static global::haxe.iterators.StringIterator iterator(string s)
    {
        return new global::haxe.iterators.StringIterator((string)(s));
    }

    public static global::haxe.iterators.StringKeyValueIterator keyValueIterator(string s)
    {
        return new global::haxe.iterators.StringKeyValueIterator((string)(s));
    }

    public static bool isEof(int c)
    {
        unchecked { return (c == -1); }
    }

    // NOTE: Removed [EditorBrowsable] attributes (System.ComponentModel is often not whitelisted).

    public static string quoteUnixArg(string argument)
    {
        // Minimal safe implementation: if it has spaces or quotes, wrap in single-quotes and escape single-quotes.
        if (argument == null) return "''";
        if (argument.Length == 0) return "''";

        bool needQuote = false;
        for (int i = 0; i < argument.Length; i++)
        {
            char ch = argument[i];
            if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\'' || ch == '"' || ch == '\\')
            {
                needQuote = true;
                break;
            }
        }

        if (!needQuote) return argument;

        // POSIX-ish: close/open quotes around single quote: 'foo'"'"'bar'
        global::StringBuf b = new global::StringBuf();
        b.@add<string>("'");
        for (int i = 0; i < argument.Length; i++)
        {
            char ch = argument[i];
            if (ch == '\'')
                b.@add<string>("'\"'\"'");
            else
                b.addChar((int)ch);
        }
        b.@add<string>("'");
        return b.toString();
    }

    public static global::Array<int> winMetaCharacters;

    public static string quoteWinArg(string argument, bool escapeMetaCharacters)
    {
        // Minimal safe implementation: quote if contains whitespace or quotes, escape quotes/backslashes.
        if (argument == null) return "\"\"";

        bool needQuote = false;
        for (int i = 0; i < argument.Length; i++)
        {
            char ch = argument[i];
            if (ch == ' ' || ch == '\t' || ch == '"' )
            {
                needQuote = true;
                break;
            }
        }

        if (!needQuote)
            return argument;

        global::StringBuf result = new global::StringBuf();
        result.@add<string>("\"");

        int backslashes = 0;
        for (int i = 0; i < argument.Length; i++)
        {
            char ch = argument[i];
            if (ch == '\\')
            {
                backslashes++;
                continue;
            }

            if (ch == '"')
            {
                // escape accumulated backslashes + the quote
                for (int k = 0; k < backslashes * 2 + 1; k++) result.addChar((int)'\\');
                result.addChar((int)'"');
                backslashes = 0;
                continue;
            }

            // flush backslashes
            for (int k = 0; k < backslashes; k++) result.addChar((int)'\\');
            backslashes = 0;

            result.addChar((int)ch);
        }

        // flush trailing backslashes (need doubling before closing quote)
        for (int k = 0; k < backslashes * 2; k++) result.addChar((int)'\\');

        result.@add<string>("\"");

        // escapeMetaCharacters: we *intentionally* do nothing here, because
        // meta-chars list is shell-specific and original implementation depends on SysTools.
        return result.toString();
    }

    public static int MIN_SURROGATE_CODE_POINT;

    public static int utf16CodePointAt(string s, int index)
    {
        unchecked
        {
            int c = global::StringTools.fastCodeAt(s, index);
            if ((c >= 55296) && (c <= 56319))
            {
                c = (((c - 55232) << 10) | (global::StringTools.fastCodeAt(s, (index + 1)) & 1023));
            }

            return c;
        }
    }
}