File: DiaSymReader\Utilities\InteropUtilities.cs
Web Access
Project: src\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace Microsoft.DiaSymReader
{
    internal static class EmptyArray<T>
    {
        public static readonly T[] Instance = new T[0];
    }
 
    internal class InteropUtilities
    {
        private static readonly IntPtr s_ignoreIErrorInfo = new IntPtr(-1);
 
        internal static T[] NullToEmpty<T>(T[] items) => (items == null) ? EmptyArray<T>.Instance : items;
 
        internal static void ThrowExceptionForHR(int hr)
        {
            // E_FAIL indicates "no info".
            // E_NOTIMPL indicates a lack of ISymUnmanagedReader support (in a particular implementation).
            if (hr < 0 && hr != HResult.E_FAIL && hr != HResult.E_NOTIMPL)
            {
                Marshal.ThrowExceptionForHR(hr, s_ignoreIErrorInfo);
            }
        }
 
        internal static unsafe void CopyQualifiedTypeName(char* qualifiedName, int qualifiedNameBufferLength, int* qualifiedNameLength, string namespaceStr, string nameStr)
        {
            Debug.Assert(nameStr != null);
 
            if (namespaceStr == null)
            {
                namespaceStr = string.Empty;
            }
 
            if (qualifiedNameLength != null)
            {
                int fullLength = (namespaceStr.Length > 0 ? namespaceStr.Length + 1 : 0) + nameStr.Length;
                if (qualifiedName != null)
                {
                    // If the buffer is given return the length of the possibly truncated name not including NUL.
                    // If we returned length greater than the buffer length the SymWriter would replace the name with CRC32 hash.
                    *qualifiedNameLength = Math.Min(fullLength, Math.Max(0, qualifiedNameBufferLength - 1));
                }
                else
                {
                    // If the buffer is not given then return the full length.
                    *qualifiedNameLength = fullLength;
                }
            }
 
            if (qualifiedName != null && qualifiedNameBufferLength > 0)
            {
                char* dst = qualifiedName;
                char* dstEndPtr = dst + qualifiedNameBufferLength - 1;
 
                if (namespaceStr.Length > 0)
                {
                    for (int i = 0; i < namespaceStr.Length && dst < dstEndPtr; i++)
                    {
                        *dst = namespaceStr[i];
                        dst++;
                    }
 
                    if (dst < dstEndPtr)
                    {
                        *dst = '.';
                        dst++;
                    }
                }
 
                for (int i = 0; i < nameStr.Length && dst < dstEndPtr; i++)
                {
                    *dst = nameStr[i];
                    dst++;
                }
 
                Debug.Assert(dst <= dstEndPtr);
                *dst = '\0';
            }
        }
    }
}