• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mergeProgram.h"
17 
18 #if defined(PANDA_TARGET_WINDOWS)
19 #include <io.h>
20 #else
21 #include <dirent.h>
22 #endif
23 
24 namespace panda::proto {
25 #if PANDA_TARGET_WINDOWS
EnumerateFilesWindows(const std::string & protoBinPath,const std::string & protoBinSuffix,std::vector<std::string> & directoryFiles)26 bool MergeProgram::EnumerateFilesWindows(const std::string &protoBinPath, const std::string &protoBinSuffix,
27                                          std::vector<std::string> &directoryFiles)
28 {
29     int handle = 0;
30     struct _finddata_t fileInfo;
31     std::string path;
32     if ((handle = _findfirst(path.assign(protoBinPath).append("\\*").c_str(), &fileInfo)) == -1) {
33         return false;
34     }
35     do {
36         if (fileInfo.attrib & _A_SUBDIR) {
37             if ((!strncmp(fileInfo.name, ".", 1)) || (!strncmp(fileInfo.name, "..", 2))) {
38                 continue;
39             }
40             if (!GetProtoFiles(path.assign(protoBinPath).append("\\").append(fileInfo.name), protoBinSuffix,
41                                directoryFiles)) {
42                 _findclose(handle);
43                 return false;
44             }
45         } else {
46             std::string fileName(fileInfo.name);
47             if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
48                 directoryFiles.emplace_back(path.assign(protoBinPath).append("\\").append(fileName));
49             }
50         }
51     } while (_findnext(handle, &fileInfo) == 0);
52     _findclose(handle);
53     return true;
54 }
55 
56 #elif PANDA_TARGET_UNIX
57 bool MergeProgram::EnumerateFilesUnix(const std::string &protoBinPath, const std::string &protoBinSuffix,
58                                       std::vector<std::string> &directoryFiles)
59 {
60     DIR *protoBin = opendir(protoBinPath.c_str());
61     if (protoBin == nullptr) {
62         return false;
63     }
64     dirent *dir = nullptr;
65     std::string pathPrefix = protoBinPath + "/";
66     while ((dir = readdir(protoBin)) != nullptr) {
67         if ((!strncmp(dir->d_name, ".", 1)) || (!strncmp(dir->d_name, "..", 2))) {
68             continue;
69         }
70         if (dir->d_type == DT_DIR) {
71             std::string subDirName = pathPrefix + dir->d_name;
72             if (!GetProtoFiles(subDirName, protoBinSuffix, directoryFiles)) {
73                 closedir(protoBin);
74                 return false;
75             }
76         } else {
77             std::string fileName = pathPrefix + dir->d_name;
78             if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
79                 directoryFiles.emplace_back(fileName);
80             }
81         }
82     }
83     closedir(protoBin);
84     return true;
85 }
86 #endif
87 
GetProtoFiles(const std::string & protoBinPath,const std::string & protoBinSuffix,std::vector<std::string> & directoryFiles)88 bool MergeProgram::GetProtoFiles(const std::string &protoBinPath, const std::string &protoBinSuffix,
89                                  std::vector<std::string> &directoryFiles)
90 {
91 #if PANDA_TARGET_WINDOWS
92     return EnumerateFilesWindows(protoBinPath, protoBinSuffix, directoryFiles);
93 #elif PANDA_TARGET_UNIX
94     return EnumerateFilesUnix(protoBinPath, protoBinSuffix, directoryFiles);
95 #endif
96 }
97 
AppendProtoFiles(const std::string & filePath,const std::string & protoBinSuffix,std::vector<std::string> & protoFiles)98 bool MergeProgram::AppendProtoFiles(const std::string &filePath, const std::string &protoBinSuffix,
99                                     std::vector<std::string> &protoFiles)
100 {
101     auto inputAbs = panda::os::file::File::GetAbsolutePath(filePath);
102     if (!inputAbs) {
103         std::cerr << "Failed to open: " << filePath << std::endl;
104         return false;
105     }
106 
107     auto fPath = inputAbs.Value();
108     if (panda::os::file::File::IsRegularFile(fPath)) {
109         if (filePath.substr(filePath.find_last_of(".") + 1).compare(protoBinSuffix) == 0) {
110             protoFiles.emplace_back(fPath);
111         }
112     } else if (panda::os::file::File::IsDirectory(fPath)) {
113         std::vector<std::string> directoryFiles;
114         if (!GetProtoFiles(fPath, protoBinSuffix, directoryFiles)) {
115             return false;
116         }
117         protoFiles.insert(protoFiles.end(), directoryFiles.begin(), directoryFiles.end());
118     } else {
119         std::cerr << "The input path: " << fPath << " must be either a regular file or directory." << std::endl;
120         return false;
121     }
122 
123     return true;
124 }
125 
CollectProtoFiles(std::string & input,const std::string & protoBinSuffix,std::vector<std::string> & protoFiles)126 bool MergeProgram::CollectProtoFiles(std::string &input, const std::string &protoBinSuffix,
127                                      std::vector<std::string> &protoFiles)
128 {
129     constexpr const char DOGGY = '@';
130     std::vector<std::string> inputs;
131     bool isList = false;
132 
133     if (input[0] == DOGGY) {
134         input.erase(input.begin() + 0);
135         isList = true;
136     }
137 
138     auto inputAbs = panda::os::file::File::GetAbsolutePath(input);
139     if (!inputAbs) {
140         std::cerr << "Failed to open: " << input << std::endl;
141         return false;
142     }
143     if (isList) {
144         std::ifstream in(panda::os::file::File::GetExtendedFilePath(inputAbs.Value()));
145         std::string line;
146         constexpr const char CARRIAGE = '\r';
147         while (getline(in, line)) {
148             // erase front spaces
149             line.erase(line.begin(),
150                        std::find_if(line.begin(), line.end(), [](unsigned char ch) { return std::isspace(ch) == 0; }));
151             // erase carrige return symbol (Windows workaround)
152             line.erase(std::find_if(line.rbegin(), line.rend(), [](unsigned char ch) { return ch != CARRIAGE; }).base(),
153                        line.end());
154             if (!line.empty()) {
155                 inputs.push_back(line);
156             }
157         }
158         in.close();
159     } else {
160         inputs.push_back(inputAbs.Value());
161     }
162 
163     protoFiles.reserve(inputs.size());
164     for (auto &filePath : inputs) {
165         if (!AppendProtoFiles(filePath, protoBinSuffix, protoFiles)) {
166             return false;
167         }
168     }
169 
170     return true;
171 }
172 } // namespace panda::proto
173