/**
 * Common string functions including filename manipulation.
 *
 * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
 * Authors:   Walter Bright, https://www.digitalmars.com
 * License:   $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d, common/_string.d)
 * Documentation: https://dlang.org/phobos/dmd_common_string.html
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/string.d
 */
module dmd.common.string;

/**
Defines a temporary array using a fixed-length buffer as back store. If the length
of the buffer suffices, it is readily used. Otherwise, `malloc` is used to
allocate memory for the array and `free` is used for deallocation in the
destructor.

This type is meant to use exclusively as an automatic variable. It is not
default constructible or copyable.
*/
struct SmallBuffer(T)
{
    import core.stdc.stdlib : malloc, free;

    private T[] _extent;
    private bool needsFree;

    @disable this(); // no default ctor
    @disable this(ref const SmallBuffer!T); // noncopyable, nonassignable

    this(size_t len, T[] buffer)
    {
        if (len <= buffer.length)
        {
            _extent = buffer[0 .. len];
        }
        else
        {
            _extent = (cast(typeof(_extent.ptr)) malloc(len * _extent[0].sizeof))[0 .. len];
            _extent.ptr || assert(0, "Out of memory.");
            needsFree = true;
        }
        assert(this.length == len);
    }

    ~this()
    {
        if (needsFree)
            free(_extent.ptr);
    }

    void create(size_t len)
    {
        if (len <= _extent.length)
        {
            _extent = _extent[0 .. len];
        }
        else
        {
            __dtor();
            _extent = (cast(typeof(_extent.ptr)) malloc(len * _extent[0].sizeof))[0 .. len];
            _extent.ptr || assert(0, "Out of memory.");
            needsFree = true;
        }
        assert(this.length == len);
    }

    // Force accesses to extent to be scoped.
    scope inout extent()
    {
        return _extent;
    }

    alias extent this;
}

/// ditto
unittest
{
    char[230] buf = void;
    auto a = SmallBuffer!char(10, buf);
    assert(a[] is buf[0 .. 10]);
    auto b = SmallBuffer!char(1000, buf);
    assert(b[] !is buf[]);
    b.create(1000);
    assert(b.length == 1000);
    assert(b[] !is buf[]);
}

/**
Converts a zero-terminated C string to a D slice. Takes linear time and allocates no memory.

Params:
stringz = the C string to be converted

Returns:
a slice comprehending the string. The terminating 0 is not part of the slice.
*/
auto asDString(C)(C* stringz) pure @nogc nothrow
{
    import core.stdc.string : strlen;
    return stringz[0 .. strlen(stringz)];
}

///
unittest
{
    const char* p = "123".ptr;
    assert(p.asDString == "123");
}

/**
(Windows only) Converts a narrow string to a wide string using `buffer` as strorage. Returns a slice managed by
`buffer` containing the converted string. The terminating zero is not part of the returned slice,
but is guaranteed to follow it.
*/
version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow
{
    import core.sys.windows.winnls : CP_ACP, MultiByteToWideChar;
    // assume filenames encoded in system default Windows ANSI code page
    enum CodePage = CP_ACP;

    if (narrow is null)
        return null;

    const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
    if (requiredLength < cast(int) buffer.length)
    {
        buffer[requiredLength] = 0;
        return buffer[0 .. requiredLength];
    }

    buffer.create(requiredLength + 1);
    const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, requiredLength);
    assert(length == requiredLength);
    buffer[length] = 0;
    return buffer[0 .. length];
}

/**************************************
* Converts a path to one suitable to be passed to Win32 API
* functions that can deal with paths longer than 248
* characters then calls the supplied function on it.
*
* Params:
*  path = The Path to call F on.
*
* Returns:
*  The result of calling F on path.
*
* References:
*  https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
*/
version(Windows) auto extendedPathThen(alias F)(const(char)[] path)
{
    import core.sys.windows.winbase;
    import core.sys.windows.winnt;

    if (!path.length)
        return F((wchar[]).init);

    wchar[1024] buf = void;
    auto store = SmallBuffer!wchar(buf.length, buf);
    auto wpath = toWStringz(path, store);

    // GetFullPathNameW expects a sized buffer to store the result in. Since we don't
    // know how large it has to be, we pass in null and get the needed buffer length
    // as the return code.
    const pathLength = GetFullPathNameW(&wpath[0],
                                        0 /*length8*/,
                                        null /*output buffer*/,
                                        null /*filePartBuffer*/);
    if (pathLength == 0)
    {
        return F((wchar[]).init);
    }

    // wpath is the UTF16 version of path, but to be able to use
    // extended paths, we need to prefix with `\\?\` and the absolute
    // path.
    static immutable prefix = `\\?\`w;

    // prefix only needed for long names and non-UNC names
    const needsPrefix = pathLength >= MAX_PATH && (wpath[0] != '\\' || wpath[1] != '\\');
    const prefixLength = needsPrefix ? prefix.length : 0;

    // +1 for the null terminator
    const bufferLength = pathLength + prefixLength + 1;

    wchar[1024] absBuf = void;
    auto absPath = SmallBuffer!wchar(bufferLength, absBuf);

    absPath[0 .. prefixLength] = prefix[0 .. prefixLength];

    const absPathRet = GetFullPathNameW(&wpath[0],
        cast(uint)(absPath.length - prefixLength - 1),
        &absPath[prefixLength],
        null /*filePartBuffer*/);

    if (absPathRet == 0 || absPathRet > absPath.length - prefixLength)
    {
        return F((wchar[]).init);
    }

    absPath[$ - 1] = '\0';
    // Strip null terminator from the slice
    return F(absPath[0 .. $ - 1]);
}
