1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include <armnnUtils/Filesystem.hpp>
7 #include <cxxopts/cxxopts.hpp>
8
9 #include <algorithm>
10 #include <fstream>
11 #include <iostream>
12 #include <string>
13
14 namespace
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)
20 class CommandLineProcessor
21 {
22 public:
ParseOptions(cxxopts::ParseResult & result)23 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
ValidateDirectory(std::string & dir)67 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
80 if (!fs::exists(dir))
81 {
82 std::cerr << "Directory [" << dir << "] does not exist" << std::endl;
83 return false;
84 }
85
86 if (!fs::is_directory(dir))
87 {
88 std::cerr << "Given directory [" << dir << "] is not a directory" << std::endl;
89 return false;
90 }
91
92 return true;
93 }
94
ValidateOutputFile(const std::string & outputFileName)95 bool ValidateOutputFile(const std::string& outputFileName)
96 {
97 if (outputFileName.empty())
98 {
99 std::cerr << "No output file name specified" << std::endl;
100 return false;
101 }
102
103 if (fs::exists(outputFileName))
104 {
105 std::cerr << "Output file [" << outputFileName << "] already exists" << std::endl;
106 return false;
107 }
108
109 if (fs::is_directory(outputFileName))
110 {
111 std::cerr << "Output file [" << outputFileName << "] is a directory" << std::endl;
112 return false;
113 }
114
115 fs::path outputPath(outputFileName);
116 if (!fs::exists(outputPath.parent_path()))
117 {
118 std::cerr << "Directory [" << outputPath.parent_path().c_str() << "] does not exist" << std::endl;
119 return false;
120 }
121
122 return true;
123 }
124
ValidateBindingId(const std::string & id)125 bool ValidateBindingId(const std::string& id)
126 {
127 if (!std::all_of(id.begin(), id.end(), ::isdigit))
128 {
129 std::cerr << "Invalid input binding Id" << std::endl;
130 return false;
131 }
132
133 return true;
134 }
135
ProcessCommandLine(int argc,char * argv[])136 bool ProcessCommandLine(int argc, char* argv[])
137 {
138 try
139 {
140 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",
149 cxxopts::value<std::string>(m_InputDirectory))
150 ("o,outfile",
151 "Output CSV file path",
152 cxxopts::value<std::string>(m_OutputFileName))
153 ("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 }
170 catch (const cxxopts::OptionException& e)
171 {
172 std::cerr << e.what() << std::endl << std::endl;
173 return false;
174 }
175 catch (const std::exception& e)
176 {
177 std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
178 return false;
179 }
180
181 return true;
182 }
183
GetInputDirectory()184 std::string GetInputDirectory() {return m_InputDirectory;}
GetOutputFileName()185 std::string GetOutputFileName() {return m_OutputFileName;}
GetInputBindingId()186 std::string GetInputBindingId() {return m_InputBindingId;}
187
188 private:
189 std::string m_InputDirectory;
190 std::string m_OutputFileName;
191 std::string m_InputBindingId;
192 };
193
194 } // namespace anonymous
195
main(int argc,char * argv[])196 int main(int argc, char* argv[])
197 {
198 CommandLineProcessor cmdline;
199 if (!cmdline.ProcessCommandLine(argc, argv))
200 {
201 return -1;
202 }
203
204 const std::string fileFormat(".raw");
205
206 const std::string rawDirectory(cmdline.GetInputDirectory());
207 const std::string outputPath(cmdline.GetOutputFileName());
208 const std::string bindingId(cmdline.GetInputBindingId());
209
210 std::vector<fs::path> rawFiles;
211 for (auto& entry : fs::directory_iterator(rawDirectory))
212 {
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;
252 }