blob: 46aad4397614b523cdc8df17f906792efdc142f9 [file] [log] [blame]
Sadik Armagan8271f812019-04-19 09:55:06 +01001//
Jim Flynn357add22023-04-10 23:26:40 +01002// Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan8271f812019-04-19 09:55:06 +01003// SPDX-License-Identifier: MIT
4//
5
Rob Hughes9542f902021-07-14 09:48:54 +01006#include <armnnUtils/Filesystem.hpp>
Matthew Sloyan620e0732020-09-25 11:43:32 +01007#include <cxxopts/cxxopts.hpp>
Sadik Armagan8271f812019-04-19 09:55:06 +01008
9#include <algorithm>
10#include <fstream>
11#include <iostream>
12#include <string>
13
14namespace
15{
16
17// parses the command line to extract
18// * the directory -i to look through .raw files from (must exist)
19// * the name of the file -o the output CSV file path (must not already exist)
20class CommandLineProcessor
21{
22public:
Matthew Sloyan620e0732020-09-25 11:43:32 +010023 bool ParseOptions(cxxopts::ParseResult& result)
24 {
25 // indir is mandatory, dir could possibly be changed.
26 if (result.count("indir"))
27 {
28 std::string dir = result["indir"].as<std::string>();
29
30 if (!ValidateDirectory(dir))
31 {
32 return false;
33 }
34
35 m_InputDirectory = dir;
36 }
37 else
38 {
39 std::cerr << "-i/--indir parameter is mandatory." << std::endl;
40 return false;
41 }
42
43 // outfile is mandatory
44 if (result.count("outfile"))
45 {
46 if (!ValidateOutputFile(result["outfile"].as<std::string>()))
47 {
48 return false;
49 }
50 }
51 else
52 {
53 std::cerr << "-o/--outfile parameter is mandatory." << std::endl;
54 return false;
55 }
56
57 if (result.count("layer-binding-id"))
58 {
59 if(!ValidateBindingId(result["layer-binding-id"].as<std::string>()))
60 {
61 return false;
62 }
63 }
64 return true;
65 }
66
Sadik Armagan8271f812019-04-19 09:55:06 +010067 bool ValidateDirectory(std::string& dir)
68 {
69 if (dir.empty())
70 {
71 std::cerr << "No directory specified" << std::endl;
72 return false;
73 }
74
75 if (dir[dir.length() - 1] != '/')
76 {
77 dir += "/";
78 }
79
Francis Murtagh532a29d2020-06-29 11:50:01 +010080 if (!fs::exists(dir))
Sadik Armagan8271f812019-04-19 09:55:06 +010081 {
82 std::cerr << "Directory [" << dir << "] does not exist" << std::endl;
83 return false;
84 }
85
Francis Murtagh532a29d2020-06-29 11:50:01 +010086 if (!fs::is_directory(dir))
Sadik Armagan8271f812019-04-19 09:55:06 +010087 {
88 std::cerr << "Given directory [" << dir << "] is not a directory" << std::endl;
89 return false;
90 }
91
92 return true;
93 }
94
Matthew Sloyan620e0732020-09-25 11:43:32 +010095 bool ValidateOutputFile(const std::string& outputFileName)
Sadik Armagan8271f812019-04-19 09:55:06 +010096 {
97 if (outputFileName.empty())
98 {
99 std::cerr << "No output file name specified" << std::endl;
100 return false;
101 }
102
Francis Murtagh532a29d2020-06-29 11:50:01 +0100103 if (fs::exists(outputFileName))
Sadik Armagan8271f812019-04-19 09:55:06 +0100104 {
105 std::cerr << "Output file [" << outputFileName << "] already exists" << std::endl;
106 return false;
107 }
108
Francis Murtagh532a29d2020-06-29 11:50:01 +0100109 if (fs::is_directory(outputFileName))
Sadik Armagan8271f812019-04-19 09:55:06 +0100110 {
111 std::cerr << "Output file [" << outputFileName << "] is a directory" << std::endl;
112 return false;
113 }
114
Francis Murtagh532a29d2020-06-29 11:50:01 +0100115 fs::path outputPath(outputFileName);
116 if (!fs::exists(outputPath.parent_path()))
Sadik Armagan8271f812019-04-19 09:55:06 +0100117 {
118 std::cerr << "Directory [" << outputPath.parent_path().c_str() << "] does not exist" << std::endl;
119 return false;
120 }
121
122 return true;
123 }
124
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100125 bool ValidateBindingId(const std::string& id)
126 {
Matthew Sloyan620e0732020-09-25 11:43:32 +0100127 if (!std::all_of(id.begin(), id.end(), ::isdigit))
128 {
129 std::cerr << "Invalid input binding Id" << std::endl;
130 return false;
131 }
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100132
133 return true;
134 }
135
Sadik Armagan8271f812019-04-19 09:55:06 +0100136 bool ProcessCommandLine(int argc, char* argv[])
137 {
Sadik Armagan8271f812019-04-19 09:55:06 +0100138 try
139 {
Matthew Sloyan620e0732020-09-25 11:43:32 +0100140 cxxopts::Options options("ImageCSVFileGenerator",
141 "Program for creating a CSV file that "
142 "contains a list of .raw tensor files. "
143 "These .raw tensor files can be generated using the ImageTensorGenerator");
144
145 options.add_options()
146 ("h,help", "Display help messages")
147 ("i,indir",
148 "Directory that .raw files are stored in",
Matthew Sloyan2b428032020-10-06 10:45:32 +0100149 cxxopts::value<std::string>(m_InputDirectory))
Matthew Sloyan620e0732020-09-25 11:43:32 +0100150 ("o,outfile",
151 "Output CSV file path",
Matthew Sloyan2b428032020-10-06 10:45:32 +0100152 cxxopts::value<std::string>(m_OutputFileName))
Matthew Sloyan620e0732020-09-25 11:43:32 +0100153 ("l, layer-binding-id",
154 "Input layer binding Id, Defaults to 0",
155 cxxopts::value<std::string>(m_InputBindingId)->default_value("0"));
156
157 auto result = options.parse(argc, argv);
158
159 if (result.count("help"))
160 {
161 std::cout << options.help() << std::endl;
162 return false;
163 }
164
165 // Check for mandatory parameters and validate inputs
166 if(!ParseOptions(result)){
167 return false;
168 }
169 }
Jim Flynn357add22023-04-10 23:26:40 +0100170 catch (const cxxopts::exceptions::exception& e)
Matthew Sloyan620e0732020-09-25 11:43:32 +0100171 {
172 std::cerr << e.what() << std::endl << std::endl;
173 return false;
Sadik Armagan8271f812019-04-19 09:55:06 +0100174 }
175 catch (const std::exception& e)
176 {
177 std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
178 return false;
179 }
180
Sadik Armagan8271f812019-04-19 09:55:06 +0100181 return true;
182 }
183
184 std::string GetInputDirectory() {return m_InputDirectory;}
185 std::string GetOutputFileName() {return m_OutputFileName;}
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100186 std::string GetInputBindingId() {return m_InputBindingId;}
Sadik Armagan8271f812019-04-19 09:55:06 +0100187
188private:
189 std::string m_InputDirectory;
190 std::string m_OutputFileName;
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100191 std::string m_InputBindingId;
Sadik Armagan8271f812019-04-19 09:55:06 +0100192};
193
194} // namespace anonymous
195
196int main(int argc, char* argv[])
197{
198 CommandLineProcessor cmdline;
199 if (!cmdline.ProcessCommandLine(argc, argv))
200 {
201 return -1;
202 }
203
Sadik Armagan8271f812019-04-19 09:55:06 +0100204 const std::string fileFormat(".raw");
Sadik Armagan8271f812019-04-19 09:55:06 +0100205
206 const std::string rawDirectory(cmdline.GetInputDirectory());
207 const std::string outputPath(cmdline.GetOutputFileName());
FinnWilliamsArmd6507c92019-08-19 17:17:19 +0100208 const std::string bindingId(cmdline.GetInputBindingId());
Sadik Armagan8271f812019-04-19 09:55:06 +0100209
210 std::vector<fs::path> rawFiles;
Matthew Sloyan2b428032020-10-06 10:45:32 +0100211 for (auto& entry : fs::directory_iterator(rawDirectory))
Sadik Armagan8271f812019-04-19 09:55:06 +0100212 {
213 if (entry.path().extension().c_str() == fileFormat)
214 {
215 rawFiles.push_back(entry.path());
216 }
217 }
218
219 if (!rawFiles.empty())
220 {
221 unsigned int pass = 0;
222 std::ofstream refinementData;
223 refinementData.open(outputPath, std::ofstream::out);
224 if (refinementData.is_open())
225 {
226 for (auto const& raw : rawFiles)
227 {
228 refinementData << pass << ", " << bindingId << ", " << raw.c_str() << "\n";
229 if (!refinementData)
230 {
231 std::cerr << "Failed to write to output file: " << outputPath << std::endl;
232 continue;
233 }
234 ++pass;
235 }
236 refinementData.close();
237 }
238 else
239 {
240 std::cerr << "Failed to open output file: " << outputPath << std::endl;
241 return -1;
242 }
243 }
244 else
245 {
246 std::cerr << "No matching files with the \".raw\" extension found in the directory: "
247 << rawDirectory << std::endl;
248 return -1;
249 }
250
251 return 0;
Jim Flynn357add22023-04-10 23:26:40 +0100252}