summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/mclist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ToolBox/superpmi/superpmi-shared/mclist.cpp')
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/mclist.cpp258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/mclist.cpp b/src/ToolBox/superpmi/superpmi-shared/mclist.cpp
new file mode 100644
index 0000000000..6a6f8701bf
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shared/mclist.cpp
@@ -0,0 +1,258 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//----------------------------------------------------------
+// MCList.h - MethodContext List utility class
+//----------------------------------------------------------
+
+#include "standardpch.h"
+#include "mclist.h"
+#include "logging.h"
+
+bool MCList::processArgAsMCL(char *input, int *count, int **list)
+{
+ // If it contains only '0-9', '-', ',' try to see it as a range list, else try to load as a file
+ bool isRangeList = true;
+
+ size_t len = strlen(input);
+
+ for (unsigned int i=0; (i < len) && isRangeList; i++)
+ {
+ if ((input[i] != '-') && (input[i] != ',') && (!isdigit((unsigned char)input[i])))
+ isRangeList = false;
+ }
+
+ if (isRangeList)
+ {
+ //Count items
+ *count = 0;
+ unsigned rangeStart = 0;
+ bool inRange = false;
+ unsigned scratch = 0;
+ bool foundDigit = false;
+
+ char *tail = input+len;
+
+ for(char* head = input; head <= tail; head++)
+ {
+ scratch = 0;
+ foundDigit = false;
+ while((head<=tail)&&(isdigit((unsigned char)*head)))
+ {
+ scratch = (scratch*10)+((*head)-'0');
+ foundDigit = true;
+ head++;
+ }
+ if(foundDigit)
+ {
+ if(inRange)
+ {
+ inRange = false;
+ if(rangeStart>=scratch)
+ {
+ LogError("Invalid range in '%s'", input);
+ return false;
+ }
+ (*count) += scratch-rangeStart;
+ }
+ else
+ {
+ rangeStart = scratch;
+ (*count)++;
+ }
+ }
+ if(*head == '-')
+ inRange = true;
+ }
+
+ if (*count == 0)
+ {
+ LogError("Didn't find a list!");
+ return false;
+ }
+
+ inRange = false;
+ rangeStart = 0;
+
+ int *ll = new int[*count];
+ *list = ll;
+ int index = 0;
+ ll[index] = 0;
+
+ for(char* head = input; head <= tail; head++)
+ {
+ scratch = 0;
+ foundDigit = false;
+ while((head<=tail)&&(isdigit((unsigned char)*head)))
+ {
+ scratch = (scratch*10)+((*head)-'0');
+ foundDigit = true;
+ head++;
+ }
+ if(foundDigit)
+ {
+ if(inRange)
+ {
+ inRange = false;
+ for(unsigned int i=rangeStart+1;i<=scratch;i++)
+ ll[index++] = i;
+ }
+ else
+ {
+ rangeStart = scratch;
+ ll[index++] = scratch;
+ }
+ }
+ if(*head == '-')
+ inRange = true;
+ }
+ if(inRange)
+ {
+ LogError("Found invalid external range in '%s'", input);
+ return false;
+ }
+ goto checkMCL;
+ }
+ else
+ {
+ char *lastdot = strrchr(input,'.');
+ if(lastdot != nullptr && _stricmp(lastdot, ".mcl")==0)
+ {
+ //Read MCLFile
+ if (!getLineData(input, count, list))
+ return false;
+ if (*count >= 0)
+ goto checkMCL;
+ }
+ return false;
+ }
+
+checkMCL: //check that mcl list is increasing only
+ int *ll = (*list);
+ if (ll[0] == 0)
+ {
+ LogError("MCL list needs to start from 1!");
+ return false;
+ }
+ for (int i = 1; i < *count; i++)
+ {
+ if (ll[i-1] >= ll[i])
+ {
+ LogError("MCL list must be increasing.. found %d -> %d", ll[i - 1], ll[i]);
+ return false;
+ }
+ }
+ return true;
+}
+
+// Returns true on success, false on failure.
+// On success, sets *pIndexCount to the number of indices read, and *pIndexes to a new array with all the indices read. The caller must
+// free the memory with delete[].
+/* static */
+bool MCList::getLineData(const char *nameOfInput, /* OUT */ int *pIndexCount, /* OUT */ int **pIndexes)
+{
+ HANDLE hFile = CreateFileA(nameOfInput, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ LogError("Unable to open '%s'. GetLastError()=%u", nameOfInput, GetLastError());
+ return false;
+ }
+ LARGE_INTEGER DataTemp;
+ if (!GetFileSizeEx(hFile, &DataTemp))
+ {
+ LogError("GetFileSizeEx failed. GetLastError()=%u", GetLastError());
+ return false;
+ }
+
+ if (DataTemp.QuadPart > MAXMCLFILESIZE)
+ {
+ LogError("Size %d exceeds max size of %d", DataTemp.QuadPart, MAXMCLFILESIZE);
+ return false;
+ }
+
+ int sz = DataTemp.u.LowPart;
+ char* buff = new char[sz];
+ DWORD bytesRead;
+ if (ReadFile(hFile, buff, sz, &bytesRead, nullptr) == 0)
+ {
+ LogError("ReadFile failed. GetLastError()=%u", GetLastError());
+ delete[] buff;
+ return false;
+ }
+ if (!CloseHandle(hFile))
+ {
+ LogError("CloseHandle failed. GetLastError()=%u", GetLastError());
+ delete[] buff;
+ return false;
+ }
+
+ // Count the lines. Note that the last line better be terminated by a newline.
+ int lineCount = 0;
+ for (int i = 0; i < sz; i++)
+ {
+ if (buff[i] == '\n')
+ {
+ lineCount++;
+ }
+ }
+
+ int* indexes = new int[lineCount];
+ int indexCount = 0;
+ int i = 0;
+ while (i < sz)
+ {
+ //seek the first number on the line. This will skip empty lines and lines with no digits.
+ while (!isdigit((unsigned char)buff[i]))
+ i++;
+ //read in the number
+ indexes[indexCount++] = atoi(&buff[i]);
+ //seek to the start of next line
+ while ((i < sz) && (buff[i] != '\n'))
+ i++;
+ i++;
+ }
+ delete[] buff;
+
+ *pIndexCount = indexCount;
+ *pIndexes = indexes;
+ return true;
+}
+
+void MCList::InitializeMCL(char *filename)
+{
+ hMCLFile = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hMCLFile == INVALID_HANDLE_VALUE)
+ {
+ LogError("Failed to open output file '%s'. GetLastError()=%u", filename, GetLastError());
+ }
+}
+
+void MCList::AddMethodToMCL(int methodIndex)
+{
+ if (hMCLFile != INVALID_HANDLE_VALUE)
+ {
+ char strMethodIndex[12];
+ DWORD charCount = 0;
+ DWORD bytesWritten = 0;
+
+ charCount = sprintf(strMethodIndex, "%d\r\n", methodIndex);
+
+ if (!WriteFile(hMCLFile, strMethodIndex, charCount, &bytesWritten, nullptr) || bytesWritten != charCount)
+ {
+ LogError("Failed to write method index '%d'. GetLastError()=%u", strMethodIndex, GetLastError());
+ }
+ }
+}
+
+void MCList::CloseMCL()
+{
+ if (hMCLFile != INVALID_HANDLE_VALUE)
+ {
+ if (CloseHandle(hMCLFile) == 0)
+ {
+ LogError("CloseHandle failed. GetLastError()=%u", GetLastError());
+ }
+ }
+}