summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/mcs/verbstrip.cpp
blob: 352ef04e93cfee8aeb30ed3f306c08ca3bfae1b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "standardpch.h"
#include "verbstrip.h"
#include "simpletimer.h"
#include "methodcontext.h"
#include "errorhandling.h"
#include "methodcontextreader.h"
#include "methodcontextiterator.h"

// verbStrip::DoWork handles both "-copy" and "-strip". These both copy from input file to output file,
// but treat the passed-in indexes in opposite ways.
int verbStrip::DoWork(
    const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes, bool strip, bool stripCR)
{
    if (strip)
        return DoWorkTheOldWay(nameOfInput, nameOfOutput, indexCount, indexes, stripCR);
    SimpleTimer* st1 = new SimpleTimer();

    LogVerbose("Reading from '%s' removing Mc Indexes and writing into '%s'", nameOfInput, nameOfOutput);

    int            loadedCount = 0;
    MethodContext* mc          = nullptr;
    int            savedCount  = 0;
    int            index       = 0;

    // The method context reader handles skipping any unrequested method contexts
    // Used in conjunction with an MCI file, it does a lot less work...
    MethodContextReader* reader = new MethodContextReader(nameOfInput, indexes, indexCount);
    if (!reader->isValid())
    {
        return -1;
    }

    HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (hFileOut == INVALID_HANDLE_VALUE)
    {
        LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
        return -1;
    }

    if (indexCount == -1)
        strip = true; // Copy command with no indexes listed should copy all the inputs...
    while (true)
    {
        MethodContextBuffer mcb = reader->GetNextMethodContext();
        if (mcb.Error())
        {
            return -1;
        }
        else if (mcb.allDone())
        {
            break;
        }

        loadedCount++;
        if ((loadedCount % 500 == 0) && (loadedCount > 0))
        {
            st1->Stop();
            LogVerbose("%2.1f%% - Loaded %d at %d per second", reader->PercentComplete(), loadedCount,
                       (int)((double)500 / st1->GetSeconds()));
            st1->Start();
        }

        if (!MethodContext::Initialize(loadedCount, mcb.buff, mcb.size, &mc))
            return -1;

        if (stripCR)
        {
            delete mc->cr;
            mc->cr = new CompileResult();
        }
        mc->saveToFile(hFileOut);
        savedCount++;
        delete mc;
    }
    if (CloseHandle(hFileOut) == 0)
    {
        LogError("2nd CloseHandle failed. GetLastError()=%u", GetLastError());
        return -1;
    }
    LogInfo("Loaded %d, Saved %d", loadedCount, savedCount);

    return 0;
}

// This is only used for "-strip".
int verbStrip::DoWorkTheOldWay(
    const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes, bool stripCR)
{
    LogVerbose("Reading from '%s' removing MC Indexes and writing into '%s'", nameOfInput, nameOfOutput);

    MethodContextIterator mci(true);
    if (!mci.Initialize(nameOfInput))
        return -1;

    int  savedCount = 0;
    bool write;
    int  index = 0; // Can't use MethodContextIterator indexing, since we want the opposite of that.

    HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (hFileOut == INVALID_HANDLE_VALUE)
    {
        LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
        return -1;
    }

    while (mci.MoveNext())
    {
        MethodContext* mc = mci.Current();

        write = true; // assume we'll write it
        if (index < indexCount)
        {
            if (indexes[index] == mci.MethodContextNumber())
            {
                index++;
                write = false;
            }
        }

        if (write)
        {
            if (stripCR)
            {
                delete mc->cr;
                mc->cr = new CompileResult();
            }
            mc->saveToFile(hFileOut);
            savedCount++;
        }
    }

    if (CloseHandle(hFileOut) == 0)
    {
        LogError("2nd CloseHandle failed. GetLastError()=%u", GetLastError());
        return -1;
    }

    if (index < indexCount)
        LogWarning("Didn't use all of index count input %d < %d  (i.e. didn't see MC #%d)", index, indexCount,
                   indexes[index]);

    LogInfo("Loaded %d, Saved %d", mci.MethodContextNumber(), savedCount);

    if (!mci.Destroy())
        return -1;

    return 0;
}