blob: 5405df9e164f4587f4aac93b517c562d8ad280bd [file] [log] [blame]
Sadik Armagan8271f812019-04-19 09:55:06 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Francis Murtagh532a29d2020-06-29 11:50:01 +01006#include <Filesystem.hpp>
Matthew Sloyan620e0732020-09-25 11:43:32 +01007#include <cxxopts/cxxopts.hpp>
8#include <boost/range/iterator_range.hpp>
Sadik Armagan8271f812019-04-19 09:55:06 +01009
10#include <algorithm>
11#include <fstream>
12#include <iostream>
13#include <string>
14
15namespace
16{
17
18// parses the command line to extract
19// * the directory -i to look through .raw files from (must exist)
20// * the name of the file -o the output CSV file path (must not already exist)
21class CommandLineProcessor
22{
23public:
Matthew Sloyan620e0732020-09-25 11:43:32 +010024 bool ParseOptions(cxxopts::ParseResult& result)
25 {
26 // indir is mandatory, dir could possibly be changed.
27 if (result.count("indir"))
28 {
29 std::string dir = result["indir"].as<std::string>();
30
31 if (!ValidateDirectory(dir))
32 {
33 return false;
34 }
35
36 m_InputDirectory = dir;
37 }
38 else
39 {
40 std::cerr << "-i/--indir parameter is mandatory." << std::endl;
41 return false;
42 }
43
44 // outfile is mandatory
45 if (result.count("outfile"))
46 {
47 if (!ValidateOutputFile(result["outfile"].as<std::string>()))
48 {
49 return false;
50 }
51 }
52 else
53 {
54 std::cerr << "-o/--outfile parameter is mandatory." << std::endl;
55 return false;
56 }
57
58 if (result.count("layer-binding-id"))
59 {
60 if(!ValidateBindingId(result["layer-binding-id"].as<std::string>()))
61 {
62 return false;
63 }
64 }
65 return true;
66 }
67
Sadik Armagan8271f812019-04-19 09:55:06 +010068 bool ValidateDirectory(std::string& dir)
69 {
70 if (dir.empty())
71 {
72 std::cerr << "No directory specified" << std::endl;
73 return false;
74 }
75
76 if (dir[dir.length() - 1] != '/')
77 {
78 dir += "/";
79 }
80
Francis Murtagh532a29d2020-06-29 11:50:01 +010081 if (!fs::exists(dir))
Sadik Armagan8271f812019-04-19 09:55:06 +010082 {
83 std::cerr << "Directory [" << dir << "] does not exist" << std::endl;
84 return false;
85 }
86
Francis Murtagh532a29d2020-06-29 11:50:01 +010087 if (!fs::is_directory(dir))
Sadik Armagan8271f812019-04-19 09:55:06 +010088 {
89 std::cerr << "Given directory [" << dir << "] is not a directory" << std::endl;
90 return false;
91 }
92
93 return true;
94 }
95
Matthew Sloyan620e0732020-09-25 11:43:32 +010096 bool ValidateOutputFile(const std::string& outputFileName)
Sadik Armagan8271f812019-04-19 09:55:06 +010097 {
98 if (outputFileName.empty())
99 {
100 std::cerr << "No output file name specified" << std::endl;
101 return false;
102 }
103
Francis Murtagh532a29d2020-06-29 11:50:01 +0100104 if (fs::exists(outputFileName))
Sadik Armagan8271f812019-04-19 09:55:06 +0100105 {
106 std::cerr << "Output file [" << outputFileName << "] already exists" << std::endl;
107 return false;
108 }
109
Francis Murtagh532a29d2020-06-29 11:50:01 +0100110 if (fs::is_directory(outputFileName))
Sadik Armagan8271f812019-04-19 09:55:06 +0100111 {
112 std::cerr << "Output file [" << outputFileName << "] is a directory" << std::endl;
113 return false;
114 }
115
Francis Murtagh532a29d2020-06-29 11:50:01 +0100116 fs::path outputPath(outputFileName);
117 if (!fs::exists(outputPath.parent_path()))
Sadik Armagan8271f812019-04-19 09:55:06 +0100118 {
119 std::cerr << "Directory [" << outputPath.parent_path().c_str() << "] does not exist" << std::endl;
120 return false;
121 }
122
123 return true;
124 }
125
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100126 bool ValidateBindingId(const std::string& id)
127 {
Matthew Sloyan620e0732020-09-25 11:43:32 +0100128 if (!std::all_of(id.begin(), id.end(), ::isdigit))
129 {
130 std::cerr << "Invalid input binding Id" << std::endl;
131 return false;
132 }
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100133
134 return true;
135 }
136
Sadik Armagan8271f812019-04-19 09:55:06 +0100137 bool ProcessCommandLine(int argc, char* argv[])
138 {
Sadik Armagan8271f812019-04-19 09:55:06 +0100139 try
140 {
Matthew Sloyan620e0732020-09-25 11:43:32 +0100141 cxxopts::Options options("ImageCSVFileGenerator",
142 "Program for creating a CSV file that "
143 "contains a list of .raw tensor files. "
144 "These .raw tensor files can be generated using the ImageTensorGenerator");
145
146 options.add_options()
147 ("h,help", "Display help messages")
148 ("i,indir",
149 "Directory that .raw files are stored in",
150 cxxopts::value<std::string>(m_InputDirectory))
151 ("o,outfile",
152 "Output CSV file path",
153 cxxopts::value<std::string>(m_OutputFileName))
154 ("l, layer-binding-id",
155 "Input layer binding Id, Defaults to 0",
156 cxxopts::value<std::string>(m_InputBindingId)->default_value("0"));
157
158 auto result = options.parse(argc, argv);
159
160 if (result.count("help"))
161 {
162 std::cout << options.help() << std::endl;
163 return false;
164 }
165
166 // Check for mandatory parameters and validate inputs
167 if(!ParseOptions(result)){
168 return false;
169 }
170 }
171 catch (const cxxopts::OptionException& e)
172 {
173 std::cerr << e.what() << std::endl << std::endl;
174 return false;
Sadik Armagan8271f812019-04-19 09:55:06 +0100175 }
176 catch (const std::exception& e)
177 {
178 std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
179 return false;
180 }
181
Sadik Armagan8271f812019-04-19 09:55:06 +0100182 return true;
183 }
184
185 std::string GetInputDirectory() {return m_InputDirectory;}
186 std::string GetOutputFileName() {return m_OutputFileName;}
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100187 std::string GetInputBindingId() {return m_InputBindingId;}
Sadik Armagan8271f812019-04-19 09:55:06 +0100188
189private:
190 std::string m_InputDirectory;
191 std::string m_OutputFileName;
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100192 std::string m_InputBindingId;
Sadik Armagan8271f812019-04-19 09:55:06 +0100193};
194
195} // namespace anonymous
196
197int main(int argc, char* argv[])
198{
199 CommandLineProcessor cmdline;
200 if (!cmdline.ProcessCommandLine(argc, argv))
201 {
202 return -1;
203 }
204
Sadik Armagan8271f812019-04-19 09:55:06 +0100205 const std::string fileFormat(".raw");
Sadik Armagan8271f812019-04-19 09:55:06 +0100206
207 const std::string rawDirectory(cmdline.GetInputDirectory());
208 const std::string outputPath(cmdline.GetOutputFileName());
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100209 const std::string bindingId(cmdline.GetInputBindingId());
Sadik Armagan8271f812019-04-19 09:55:06 +0100210
211 std::vector<fs::path> rawFiles;
212 for (auto& entry : boost::make_iterator_range(fs::directory_iterator(rawDirectory), {}))
213 {
214 if (entry.path().extension().c_str() == fileFormat)
215 {
216 rawFiles.push_back(entry.path());
217 }
218 }
219
220 if (!rawFiles.empty())
221 {
222 unsigned int pass = 0;
223 std::ofstream refinementData;
224 refinementData.open(outputPath, std::ofstream::out);
225 if (refinementData.is_open())
226 {
227 for (auto const& raw : rawFiles)
228 {
229 refinementData << pass << ", " << bindingId << ", " << raw.c_str() << "\n";
230 if (!refinementData)
231 {
232 std::cerr << "Failed to write to output file: " << outputPath << std::endl;
233 continue;
234 }
235 ++pass;
236 }
237 refinementData.close();
238 }
239 else
240 {
241 std::cerr << "Failed to open output file: " << outputPath << std::endl;
242 return -1;
243 }
244 }
245 else
246 {
247 std::cerr << "No matching files with the \".raw\" extension found in the directory: "
248 << rawDirectory << std::endl;
249 return -1;
250 }
251
252 return 0;
253}