summaryrefslogtreecommitdiff
path: root/src/pal/src/include/pal/stackstring.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/include/pal/stackstring.hpp')
-rw-r--r--src/pal/src/include/pal/stackstring.hpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/pal/src/include/pal/stackstring.hpp b/src/pal/src/include/pal/stackstring.hpp
new file mode 100644
index 0000000000..1f18d5fe03
--- /dev/null
+++ b/src/pal/src/include/pal/stackstring.hpp
@@ -0,0 +1,239 @@
+// 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.
+
+#ifndef __STACKSTRING_H_
+#define __STACKSTRING_H_
+
+template <SIZE_T STACKCOUNT, class T>
+class StackString
+{
+private:
+ T m_innerBuffer[STACKCOUNT + 1];
+ T * m_buffer;
+ SIZE_T m_size; // actual allocated size
+ SIZE_T m_count; // actual length of string
+
+ void NullTerminate()
+ {
+ m_buffer[m_count] = 0;
+ }
+
+ void DeleteBuffer()
+ {
+ if (m_innerBuffer != m_buffer)
+ PAL_free(m_buffer);
+
+ m_buffer = NULL;
+ return;
+ }
+
+ BOOL ReallocateBuffer(SIZE_T count)
+ {
+ // count is always > STACKCOUNT here.
+ // We got so far, we will allocate a little extra
+ // to prevent frequent allocations
+#if _DEBUG
+ SIZE_T count_allocated = count;
+#else
+ SIZE_T count_allocated = count + 100;
+#endif //_DEBUG
+
+ BOOL dataOnStack = m_buffer == m_innerBuffer;
+ if( dataOnStack )
+ {
+ m_buffer = NULL;
+ }
+
+ T * newBuffer = (T *)PAL_realloc(m_buffer, (count_allocated + 1) * sizeof(T));
+ if (NULL == newBuffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+ DeleteBuffer();
+ m_count = 0;
+ m_buffer = m_innerBuffer;
+ return FALSE;
+ }
+
+ if( dataOnStack)
+ {
+ CopyMemory(newBuffer, m_innerBuffer, (m_count + 1) * sizeof(T));
+ }
+
+ m_buffer = newBuffer;
+ m_count = count;
+ m_size = count_allocated + 1;
+
+ return TRUE;
+ }
+
+ BOOL HasAvailableMemory(SIZE_T count)
+ {
+ return (count < m_size);
+ }
+
+ //NOTE: Always call this before modifying the underlying buffer
+ BOOL Resize(SIZE_T count)
+ {
+
+ if (NULL == m_buffer)
+ {
+ m_buffer = m_innerBuffer;
+ }
+
+ if (HasAvailableMemory(count))
+ {
+ m_count = count;
+ }
+ else
+ {
+ if (count > STACKCOUNT)
+ {
+ return ReallocateBuffer(count);
+ }
+ else
+ {
+ m_count = count;
+ m_size = STACKCOUNT+1;
+ }
+ }
+
+ return TRUE;
+ }
+
+ StackString(const StackString &s)
+ {
+ Set(s);
+ }
+
+public:
+ StackString()
+ : m_buffer(m_innerBuffer), m_size(0), m_count(0)
+ {
+ }
+
+
+ BOOL Set(const T * buffer, SIZE_T count)
+ {
+ if (!Resize(count))
+ return FALSE;
+
+ CopyMemory(m_buffer, buffer, (count + 1) * sizeof(T));
+ NullTerminate();
+ return TRUE;
+ }
+
+ BOOL Set(const StackString &s)
+ {
+ return Set(s.m_buffer, s.m_count);
+ }
+
+ SIZE_T GetCount() const
+ {
+ return m_count;
+ }
+
+ SIZE_T GetSizeOf() const
+ {
+ return m_size * sizeof(T);
+ }
+
+ CONST T * GetString() const
+ {
+ return (const T *)m_buffer;
+ }
+
+ operator const T * () const { return GetString(); }
+
+ //Always preserves the existing content
+ T * OpenStringBuffer(SIZE_T count)
+ {
+ T * result = NULL;
+ if (Resize(count))
+ {
+ result = (T *)m_buffer;
+ }
+ return result;
+ }
+
+ //count should not include the terminating null
+ void CloseBuffer(SIZE_T count)
+ {
+ if (m_count > count)
+ m_count = count;
+
+ NullTerminate();
+ return;
+ }
+
+ //Call this with the best estimate if you want to
+ //prevent possible reallocations on further operations
+ BOOL Reserve(SIZE_T count)
+ {
+ SIZE_T endpos = m_count;
+
+ if (!Resize(count))
+ return FALSE;
+
+ m_count = endpos;
+ NullTerminate();
+
+ return TRUE;
+ }
+
+ //count Should not include the terminating null
+ BOOL Append(const T * buffer, SIZE_T count)
+ {
+ SIZE_T endpos = m_count;
+ if (!Resize(m_count + count))
+ return FALSE;
+
+ CopyMemory(&m_buffer[endpos], buffer, (count + 1) * sizeof(T));
+ NullTerminate();
+ return TRUE;
+ }
+
+ BOOL Append(const StackString &s)
+ {
+ return Append(s.GetString(), s.GetCount());
+ }
+
+ BOOL IsEmpty()
+ {
+ return 0 == m_buffer[0];
+ }
+
+ void Clear()
+ {
+ m_count = 0;
+ NullTerminate();
+ }
+ ~StackString()
+ {
+ DeleteBuffer();
+ }
+};
+
+#if _DEBUG
+typedef StackString<32, CHAR> PathCharString;
+typedef StackString<32, WCHAR> PathWCharString;
+#else
+typedef StackString<260, CHAR> PathCharString;
+typedef StackString<260, WCHAR> PathWCharString;
+#endif
+#endif
+
+// Some Helper Definitions
+BOOL
+PAL_GetPALDirectoryW(
+ PathWCharString& lpDirectoryName);
+BOOL
+PAL_GetPALDirectoryA(
+ PathCharString& lpDirectoryName);
+DWORD
+GetCurrentDirectoryA(
+ PathCharString& lpBuffer);
+void
+FILEDosToUnixPathA(
+ PathCharString& lpPath);