1 | // |
2 | // Copyright (c) Microsoft. All rights reserved. |
3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
4 | // |
5 | |
6 | #include "standardpch.h" |
7 | #include "verbstrip.h" |
8 | #include "simpletimer.h" |
9 | #include "methodcontext.h" |
10 | #include "errorhandling.h" |
11 | #include "methodcontextreader.h" |
12 | #include "methodcontextiterator.h" |
13 | |
14 | // verbStrip::DoWork handles both "-copy" and "-strip". These both copy from input file to output file, |
15 | // but treat the passed-in indexes in opposite ways. |
16 | int verbStrip::DoWork( |
17 | const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes, bool strip, bool stripCR) |
18 | { |
19 | if (strip) |
20 | return DoWorkTheOldWay(nameOfInput, nameOfOutput, indexCount, indexes, stripCR); |
21 | SimpleTimer* st1 = new SimpleTimer(); |
22 | |
23 | LogVerbose("Reading from '%s' removing Mc Indexes and writing into '%s'" , nameOfInput, nameOfOutput); |
24 | |
25 | int loadedCount = 0; |
26 | MethodContext* mc = nullptr; |
27 | int savedCount = 0; |
28 | int index = 0; |
29 | |
30 | // The method context reader handles skipping any unrequested method contexts |
31 | // Used in conjunction with an MCI file, it does a lot less work... |
32 | MethodContextReader* reader = new MethodContextReader(nameOfInput, indexes, indexCount); |
33 | if (!reader->isValid()) |
34 | { |
35 | return -1; |
36 | } |
37 | |
38 | HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, |
39 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); |
40 | if (hFileOut == INVALID_HANDLE_VALUE) |
41 | { |
42 | LogError("Failed to open input 1 '%s'. GetLastError()=%u" , nameOfOutput, GetLastError()); |
43 | return -1; |
44 | } |
45 | |
46 | if (indexCount == -1) |
47 | strip = true; // Copy command with no indexes listed should copy all the inputs... |
48 | while (true) |
49 | { |
50 | MethodContextBuffer mcb = reader->GetNextMethodContext(); |
51 | if (mcb.Error()) |
52 | { |
53 | return -1; |
54 | } |
55 | else if (mcb.allDone()) |
56 | { |
57 | break; |
58 | } |
59 | |
60 | loadedCount++; |
61 | if ((loadedCount % 500 == 0) && (loadedCount > 0)) |
62 | { |
63 | st1->Stop(); |
64 | LogVerbose("%2.1f%% - Loaded %d at %d per second" , reader->PercentComplete(), loadedCount, |
65 | (int)((double)500 / st1->GetSeconds())); |
66 | st1->Start(); |
67 | } |
68 | |
69 | if (!MethodContext::Initialize(loadedCount, mcb.buff, mcb.size, &mc)) |
70 | return -1; |
71 | |
72 | if (stripCR) |
73 | { |
74 | delete mc->cr; |
75 | mc->cr = new CompileResult(); |
76 | } |
77 | mc->saveToFile(hFileOut); |
78 | savedCount++; |
79 | delete mc; |
80 | } |
81 | if (CloseHandle(hFileOut) == 0) |
82 | { |
83 | LogError("2nd CloseHandle failed. GetLastError()=%u" , GetLastError()); |
84 | return -1; |
85 | } |
86 | LogInfo("Loaded %d, Saved %d" , loadedCount, savedCount); |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | // This is only used for "-strip". |
92 | int verbStrip::DoWorkTheOldWay( |
93 | const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes, bool stripCR) |
94 | { |
95 | LogVerbose("Reading from '%s' removing MC Indexes and writing into '%s'" , nameOfInput, nameOfOutput); |
96 | |
97 | MethodContextIterator mci(true); |
98 | if (!mci.Initialize(nameOfInput)) |
99 | return -1; |
100 | |
101 | int savedCount = 0; |
102 | bool write; |
103 | int index = 0; // Can't use MethodContextIterator indexing, since we want the opposite of that. |
104 | |
105 | HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, |
106 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); |
107 | if (hFileOut == INVALID_HANDLE_VALUE) |
108 | { |
109 | LogError("Failed to open input 1 '%s'. GetLastError()=%u" , nameOfOutput, GetLastError()); |
110 | return -1; |
111 | } |
112 | |
113 | while (mci.MoveNext()) |
114 | { |
115 | MethodContext* mc = mci.Current(); |
116 | |
117 | write = true; // assume we'll write it |
118 | if (index < indexCount) |
119 | { |
120 | if (indexes[index] == mci.MethodContextNumber()) |
121 | { |
122 | index++; |
123 | write = false; |
124 | } |
125 | } |
126 | |
127 | if (write) |
128 | { |
129 | if (stripCR) |
130 | { |
131 | delete mc->cr; |
132 | mc->cr = new CompileResult(); |
133 | } |
134 | mc->saveToFile(hFileOut); |
135 | savedCount++; |
136 | } |
137 | } |
138 | |
139 | if (CloseHandle(hFileOut) == 0) |
140 | { |
141 | LogError("2nd CloseHandle failed. GetLastError()=%u" , GetLastError()); |
142 | return -1; |
143 | } |
144 | |
145 | if (index < indexCount) |
146 | LogWarning("Didn't use all of index count input %d < %d (i.e. didn't see MC #%d)" , index, indexCount, |
147 | indexes[index]); |
148 | |
149 | LogInfo("Loaded %d, Saved %d" , mci.MethodContextNumber(), savedCount); |
150 | |
151 | if (!mci.Destroy()) |
152 | return -1; |
153 | |
154 | return 0; |
155 | } |
156 | |