• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "util/options.h"
17 
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstring>
21 #include <dirent.h>
22 #include <getopt.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 
26 #include <map>
27 
28 #include "util/common.h"
29 #include "util/file.h"
30 #include "util/logger.h"
31 #include "util/string_helper.h"
32 #include "util/string_builder.h"
33 
34 namespace OHOS {
35 namespace Idl {
36 const char *Options::optSupportArgs = "hvcs:m:p:d:r:o:D:t:";
37 static struct option g_longOpts[] = {
38     {"help",          no_argument,       nullptr, 'h'},
39     {"version",       no_argument,       nullptr, 'v'},
40     {"client-enable", no_argument,       nullptr, 'C'},
41     {"system",        required_argument, nullptr, 'S'},
42     {"mode",          required_argument, nullptr, 'm'},
43     {"gen-c",         no_argument,       nullptr, '1'},
44     {"gen-cpp",       no_argument,       nullptr, '2'},
45     {"gen-java",      no_argument,       nullptr, '3'},
46     {"gen-rust",      no_argument,       nullptr, '4'},
47     {"gen-ts",        no_argument,       nullptr, '5'},
48     {"package",       required_argument, nullptr, 'p'},
49     {"dump-ast",      no_argument,       nullptr, 'a'},
50     {"dump-metadata", no_argument,       nullptr, 'e'},
51     {"hash",          no_argument,       nullptr, 'H'},
52     {"log-domainid",  required_argument, nullptr, 'i'},
53     {"log-tag",       required_argument, nullptr, 'g'},
54     {"intf-type",     required_argument, nullptr, 'T'},
55     {nullptr,         0,                 nullptr,  0 }
56 };
57 
GetInstance()58 Options &Options::GetInstance()
59 {
60     static Options option;
61     return option;
62 }
63 
Parse(int argc,char * argv[])64 bool Options::Parse(int argc, char *argv[])
65 {
66     int ret = true;
67     program = argv[0];
68     opterr = 0;
69     int op = 0;
70     int optIndex = 0;
71 
72     if (argc < 0 || argc > UINT16_MAX) {
73         Logger::E(TAG, "argc out of range");
74         return false;
75     }
76 
77     while ((op = getopt_long_only(argc, argv, optSupportArgs, g_longOpts, &optIndex)) != -1) {
78         if (optind > 0 && optind <= argc) {
79             ret = ParseSingle(op, std::string(argv[optind - 1]));
80         }
81     }
82 
83     if (doCompile) {
84         int i = 0;
85         while (++i < argc) {
86             if (argv[i][0] != '-' && StringHelper::EndWith(argv[i], ".idl")) {
87                 AddSources(argv[i]);
88             }
89         }
90     }
91 
92     return ret ? CheckOptions() : ret;
93 }
94 
ParseSingle(int option,std::string optVal)95 bool Options::ParseSingle(int option, std::string optVal)
96 {
97     bool ret = true;
98     switch (option) {
99         case 'h':
100             doShowUsage = true;
101             break;
102         case 'v':
103             doShowVersion = true;
104             break;
105         case 'a':
106             doDumpAST = true;
107             break;
108         case 'e':
109             doDumpMetadata = true;
110             break;
111         case 'H':
112             doHashKey = true;
113             break;
114         case 'c':
115             doCompile = true;
116             break;
117         case 'C':
118             doClient = true;
119             break;
120         case '1':
121             SetLanguage("c");
122             break;
123         case '2':
124             SetLanguage("cpp");
125             break;
126         case '3':
127             SetLanguage("java");
128             break;
129         case '4':
130             SetLanguage("rust");
131             break;
132         case '5':
133             SetLanguage("ts");
134             break;
135         default:
136             ret = ParseOptionWithValue(option, optVal);
137             break;
138     }
139     return ret;
140 }
141 
ParseOptionWithValue(int option,std::string optVal)142 bool Options::ParseOptionWithValue(int option, std::string optVal)
143 {
144     bool ret = true;
145     StringBuilder errors;
146 
147     switch (option) {
148         case 'o':
149             outPutFile = optarg;
150             break;
151         case 'S':
152             ret = SetSystemLevel(optarg);
153             break;
154         case 'm':
155             ret = SetGenerateMode(optarg);
156             break;
157         case 's':
158             SetMetadataFile(optarg);
159             break;
160         case 'p':
161             SetPackage(optarg);
162             break;
163         case 'D':
164             AddSourcesByDir(optarg);
165             break;
166         case 'd':
167             SetOutDir(optarg);
168             break;
169         case 'r':
170             ret = AddPackagePath(optarg);
171             break;
172         case 't':
173             ret = SetHiTrace(optarg);
174             break;
175         case 'i':
176             ret = SetLogDomainId(optarg);
177             break;
178         case 'g':
179             ret = SetLogTag(optarg);
180             break;
181         case 'T':
182             ret = SetInterfaceType(optarg);
183             break;
184         default:
185             errors.Append(optVal.c_str());
186             break;
187     }
188     illegalOptions = errors.ToString();
189     return ret;
190 }
191 
SetSystemLevel(const std::string & system)192 bool Options::SetSystemLevel(const std::string &system)
193 {
194     static std::map<std::string, SystemLevel> systemLevelMap = {
195         {"mini", SystemLevel::MINI},
196         {"lite", SystemLevel::LITE},
197         {"full", SystemLevel::FULL},
198     };
199 
200     auto levelIter = systemLevelMap.find(system);
201     if (levelIter == systemLevelMap.end()) {
202         Logger::E(TAG, "invalid system level set: '%s', please input mini/lite/full", system.c_str());
203         return false;
204     }
205     systemLevel = levelIter->second;
206     return true;
207 }
208 
SetGenerateMode(const std::string & mode)209 bool Options::SetGenerateMode(const std::string &mode)
210 {
211     static std::map<std::string, GenMode> codeGenMap = {
212         {"low", GenMode::LOW},
213         {"passthrough", GenMode::PASSTHROUGH},
214         {"ipc", GenMode::IPC},
215         {"kernel", GenMode::KERNEL},
216     };
217 
218     auto codeGenIter = codeGenMap.find(mode);
219     if (codeGenIter == codeGenMap.end()) {
220         Logger::E(TAG, "invalid generate mode set: '%s', please input low/passthrough/ipc/kernel/sa.", mode.c_str());
221         return false;
222     }
223     genMode = codeGenIter->second;
224     return true;
225 }
226 
SetLanguage(const std::string & language)227 bool Options::SetLanguage(const std::string &language)
228 {
229     static const std::map<std::string, Language> languageMap = {
230         {"c", Language::C},
231         {"cpp", Language::CPP},
232         {"java", Language::JAVA},
233         {"rust", Language::RUST},
234         {"ts", Language::TS},
235     };
236 
237     const auto kindIter = languageMap.find(language);
238     if (kindIter == languageMap.end()) {
239         Logger::E(TAG, "invalid language '%s', please input c, cpp, java, rust or ts", language.c_str());
240         return false;
241     }
242 
243     doGenerateCode = true;
244     genLanguage = kindIter->second;
245     return true;
246 }
247 
SetMetadataFile(const std::string & file)248 bool Options::SetMetadataFile(const std::string &file)
249 {
250     doSaveMetadata = true;
251     metadataFile = file;
252     return true;
253 }
254 
SetPackage(const std::string & infPackage)255 void Options::SetPackage(const std::string &infPackage)
256 {
257     idlPackage = infPackage;
258 }
259 
AddSources(const std::string & sourceFile)260 void Options::AddSources(const std::string &sourceFile)
261 {
262     std::string realPath = File::AdapterRealPath(sourceFile);
263     if (realPath.empty()) {
264         Logger::E(TAG, "invalid idl file path:%s", sourceFile.c_str());
265         return;
266     }
267 
268     if (sourceFiles.insert(realPath).second == false) {
269         Logger::E(TAG, "this idl file has been add:%s", sourceFile.c_str());
270         return;
271     }
272 }
273 
AddSourcesByDir(const std::string & dir)274 void Options::AddSourcesByDir(const std::string &dir)
275 {
276     sourceDir = dir;
277     std::set<std::string> files = File::FindFiles(sourceDir);
278     if (!files.empty()) {
279         doCompile = true;
280         sourceFiles.insert(files.begin(), files.end());
281     }
282 }
283 
AddPackagePath(const std::string & packagePath)284 bool Options::AddPackagePath(const std::string &packagePath)
285 {
286     size_t index = packagePath.find(":");
287     if (index == std::string::npos || index == packagePath.size() - 1) {
288         Logger::E(TAG, "invalid option parameters '%s'.", packagePath.c_str());
289         return false;
290     }
291 
292     std::string package = packagePath.substr(0, index);
293     std::string path = File::AdapterRealPath(packagePath.substr(index + 1));
294     if (path.empty()) {
295         Logger::E(TAG, "invalid path '%s'.", packagePath.substr(index + 1).c_str());
296         return false;
297     }
298 
299     auto it = packagePathMap.find(package);
300     if (it != packagePathMap.end()) {
301         Logger::E(TAG, "The '%s:%s' has been set.", package.c_str(), path.c_str());
302         return false;
303     }
304 
305     packagePathMap[package] = path;
306     return true;
307 }
308 
SetOutDir(const std::string & dir)309 void Options::SetOutDir(const std::string &dir)
310 {
311     doOutDir = true;
312     genDir = dir;
313 }
314 
CheckOptions()315 bool Options::CheckOptions()
316 {
317     if (doShowUsage || doShowVersion) {
318         return true;
319     }
320     if (HasErrors()) {
321         ShowErrors();
322         return false;
323     }
324     if (interfaceType == InterfaceType::SA) {
325         return CheckSaOptions();
326     } else if (interfaceType == InterfaceType::HDI) {
327         return CheckHdiOptions();
328     } else if (interfaceType == InterfaceType::SM ||
329                 interfaceType == InterfaceType::SAM ||
330                 interfaceType == InterfaceType::SAM_SM ||
331                 interfaceType == InterfaceType::SAM_UDS ||
332                 interfaceType == InterfaceType::SM_UDS) {
333         return CheckSmOptions();
334     } else {
335         Logger::E(TAG, "Interface type 'intf-type' value '%d' invalid, please input 'hdi' or 'sa'.", interfaceType);
336         return false;
337     }
338 }
339 
CheckSaOptions()340 bool Options::CheckSaOptions()
341 {
342     if (!DoSupportSaType()) {
343         return false;
344     }
345 
346     if (sourceFiles.empty() && !DoSaveMetadata()) {
347         Logger::E(TAG, "Option 'intf-type sa' must set idl file.");
348         return false;
349     }
350 
351     if (!DoLegalLog()) {
352         Logger::E(TAG, "Option 'log-domainid' and 'log-tag' must be used together.");
353         return false;
354     }
355 
356     attribute.doHitrace = doHitrace;
357     attribute.hitraceTag = hitraceTag;
358     attribute.logTag = logTag;
359     attribute.domainId = domainId;
360     attribute.doLog = DoLogOn();
361 
362     return true;
363 }
364 
DoSupportSaType()365 bool Options::DoSupportSaType()
366 {
367     bool ret = true;
368     if (genLanguage != Language::CPP && genLanguage != Language::RUST && genLanguage != Language::TS) {
369         Logger::E(TAG, "Option 'intf-type sa' only support language option 'gen-cpp', 'gen-rust' or 'gen-ts'.");
370         ret = false;
371     }
372 
373     if (systemLevel != SystemLevel::INIT) {
374         Logger::E(TAG, "Option 'intf-type sa' not support option 'system'.");
375         ret = false;
376     }
377 
378     if (genMode != GenMode::INIT) {
379         Logger::E(TAG, "Option 'intf-type sa' not support option 'm' or 'mode'.");
380         ret = false;
381     }
382 
383     if (!idlPackage.empty()) {
384         Logger::E(TAG, "Option 'intf-type sa' not support option 'p' or 'package'.");
385         ret = false;
386     }
387 
388     if (doHashKey) {
389         Logger::E(TAG, "Option 'intf-type sa' not support option 'hash'.");
390         ret = false;
391     }
392 
393     if (!packagePathMap.empty()) {
394         Logger::E(TAG, "Option 'intf-type sa' not support option 'r'.");
395         ret = false;
396     }
397 
398     if (!sourceDir.empty()) {
399         Logger::E(TAG, "Option 'intf-type sa' not support option 'D'.");
400         ret = false;
401     }
402 
403     if (!outPutFile.empty()) {
404         Logger::E(TAG, "Option 'intf-type sa' not support option 'o'.");
405         ret = false;
406     }
407 
408     if (!ret) {
409         printf("Use \"-h, --help\" to show usage.\n");
410     }
411     return ret;
412 }
413 
CheckHdiOptions()414 bool Options::CheckHdiOptions()
415 {
416     SetHdiDefaultOption();
417     if (!DoSupportHdiType()) {
418         return false;
419     }
420 
421     if (doCompile) {
422         if (!DoGetHashKey() && !doDumpAST && !doGenerateCode && !doOutDir) {
423             Logger::E(TAG, "nothing to do.");
424             return false;
425         }
426 
427         if (!doGenerateCode && doOutDir) {
428             Logger::E(TAG, "no target language.");
429             return false;
430         }
431 
432         if (doGenerateCode && !doOutDir) {
433             Logger::E(TAG, "no out directory.");
434             return false;
435         }
436     } else {
437         if (DoGetHashKey() || doDumpAST || doGenerateCode || doOutDir) {
438             Logger::E(TAG, "no idl files.");
439             return false;
440         }
441     }
442 
443     return true;
444 }
445 
SetHdiDefaultOption()446 void Options::SetHdiDefaultOption()
447 {
448     if (systemLevel == SystemLevel::INIT) {
449         systemLevel = SystemLevel::FULL;
450     }
451     if (genMode == GenMode::INIT) {
452         genMode = GenMode::IPC;
453     }
454     return;
455 }
456 
DoSupportHdiType()457 bool Options::DoSupportHdiType()
458 {
459     bool ret = true;
460 
461     if (genLanguage != Language::C && genLanguage != Language::CPP && genLanguage != Language::JAVA) {
462         Logger::E(TAG, "Option 'intf-type hdi' only support language option 'gen-c', 'gen-cpp' or 'gen-java'.");
463         ret = false;
464     }
465 
466     if (doDumpMetadata) {
467         Logger::E(TAG, "Option 'intf-type hdi' not support option 'dump-metadata'.");
468         ret = false;
469     }
470 
471     if (doKeywords) {
472         Logger::E(TAG, "Option 'intf-type hdi' not support option '-t', '-log-domainid' or '-log-tag'.");
473         ret = false;
474     }
475 
476     if (doSaveMetadata) {
477         Logger::E(TAG, "Option 'intf-type hdi' not support option '-s'.");
478         ret = false;
479     }
480 
481     if (!ret) {
482         printf("Use \"-h, --help\" to show usage.\n");
483     }
484     return ret;
485 }
486 
DoSupportSmType()487 bool Options::DoSupportSmType()
488 {
489     bool ret = true;
490 
491     if (genLanguage != Language::CPP && genLanguage != Language::JAVA) {
492         Logger::E(TAG, "Option 'intf-type sm' only support language option 'gen-cpp' or 'gen-java'.");
493         ret = false;
494     }
495 
496     if (doDumpMetadata) {
497         Logger::E(TAG, "Option 'intf-type sm' not support option 'dump-metadata'.");
498         ret = false;
499     }
500 
501     if (doKeywords) {
502         Logger::E(TAG, "Option 'intf-type sm' not support option '-t', '-log-domainid' or '-log-tag'.");
503         ret = false;
504     }
505 
506     if (doSaveMetadata) {
507         Logger::E(TAG, "Option 'intf-type sm' not support option '-s'.");
508         ret = false;
509     }
510 
511     if (!ret) {
512         printf("Use \"-h, --help\" to show usage.\n");
513     }
514     return ret;
515 }
516 
SetSmDefaultOption()517 void Options::SetSmDefaultOption()
518 {
519     systemLevel = SystemLevel::INIT;
520     genMode = GenMode::INIT;
521     return;
522 }
523 
CheckSmOptions()524 bool Options::CheckSmOptions()
525 {
526     SetSmDefaultOption();
527     if (!DoSupportSmType()) {
528         return false;
529     }
530 
531     if (doCompile) {
532         if (!DoGetHashKey() && !doDumpAST && !doGenerateCode && !doOutDir) {
533             Logger::E(TAG, "nothing to do.");
534             return false;
535         }
536 
537         if (!doGenerateCode && doOutDir) {
538             Logger::E(TAG, "no target language.");
539             return false;
540         }
541 
542         if (doGenerateCode && !doOutDir) {
543             Logger::E(TAG, "no out directory.");
544             return false;
545         }
546     } else {
547         if (DoGetHashKey() || doDumpAST || doGenerateCode || doOutDir) {
548             Logger::E(TAG, "no idl files.");
549             return false;
550         }
551     }
552 
553     return true;
554 }
555 
SetHiTrace(const std::string & tag)556 bool Options::SetHiTrace(const std::string &tag)
557 {
558     doKeywords = true;
559     hitraceTag = tag;
560     doHitrace = true;
561     return true;
562 }
563 
SetLogDomainId(const std::string & id)564 bool Options::SetLogDomainId(const std::string &id)
565 {
566     doKeywords = true;
567     domainId = id;
568     return true;
569 }
570 
SetLogTag(const std::string & tag)571 bool Options::SetLogTag(const std::string &tag)
572 {
573     doKeywords = true;
574     logTag = tag;
575     return true;
576 }
577 
SetInterfaceType(const std::string & type)578 bool Options::SetInterfaceType(const std::string &type)
579 {
580     static std::map<std::string, InterfaceType> Type = {
581         {"hdi", InterfaceType::HDI},
582         {"sa", InterfaceType::SA},
583         {"sm", InterfaceType::SM},
584         {"sam", InterfaceType::SAM},
585         {"sam_sm", InterfaceType::SAM_SM},
586         {"sam_uds", InterfaceType::SAM_UDS},
587         {"sm_uds", InterfaceType::SM_UDS},
588     };
589 
590     auto codeGenIter = Type.find(type);
591     if (codeGenIter == Type.end()) {
592         Logger::E(TAG, "invalid interface type set: '%s', please input hdi/sa.", type.c_str());
593         return false;
594     }
595     interfaceType = codeGenIter->second;
596     return true;
597 }
598 
DoLogOn() const599 bool Options::DoLogOn() const
600 {
601     if (!domainId.empty() && !logTag.empty()) {
602         return true;
603     }
604     return false;
605 }
606 
DoLegalLog() const607 bool Options::DoLegalLog() const
608 {
609     if (genLanguage == Language::CPP) {
610         if (!domainId.empty() && !logTag.empty()) {
611             return true;
612         } else if (domainId.empty() && logTag.empty()) {
613             return true;
614         } else {
615             return false;
616         }
617     }
618     return true;
619 }
620 
HasErrors() const621 bool Options::HasErrors() const
622 {
623     return !illegalOptions.empty();
624 }
625 
ShowErrors() const626 void Options::ShowErrors() const
627 {
628     std::vector<std::string> illegalOptionsVec = StringHelper::Split(illegalOptions, " ");
629     for (size_t i = 0; i < illegalOptionsVec.size(); i++) {
630         Logger::E(TAG, "The Option \"%s\" is illegal.", illegalOptionsVec[i].c_str());
631     }
632     printf("Use \"-h, --help\" to show usage.\n");
633     return;
634 }
635 
HasWarning() const636 bool Options::HasWarning() const
637 {
638     if (interfaceType == InterfaceType::SA) {
639         if (genLanguage == Language::RUST || genLanguage == Language::TS) {
640             if (DoSearchKeywords()) {
641                 return true;
642             }
643         }
644     }
645     return false;
646 }
647 
ShowWarning() const648 void Options::ShowWarning() const
649 {
650     printf("Warning : Executed successfully, but contains invalid commands !\n");
651 }
652 
ShowVersion() const653 void Options::ShowVersion() const
654 {
655     printf("idl %d.%d\n"
656           "Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.\n\n",
657            VERSION_MAJOR, VERSION_MINOR);
658 }
659 
ShowUsage() const660 void Options::ShowUsage() const
661 {
662     printf("Compile a .idl file and generate C/C++/Ts/Rust and Java codes.\n"
663            "Usage: idl [options] file\n"
664            "Options:\n"
665            "  -h, --help                      Display command line options\n"
666            "  -v, --version                   Display toolchain version information\n"
667            "      --system <value>            Set system level 'mini','lite' or 'full', the default value is 'full', "
668            "only support 'intf-type hdi'\n"
669            "  -m, --mode <value>              Set generate code mode 'low', 'passthrough', 'ipc' or 'kernel',"
670            " the default value is 'ipc', only support 'intf-type hdi'\n"
671            "  -p, --package <package name>    Set package of idl files, only support 'intf-type hdi'\n"
672            "      --dump-ast                  Display the AST of the compiled file\n"
673            "      --dump-metadata             Display the metadata generated from the compiled file, "
674            "only support 'intf-type sa'\n"
675            "      --hash                      Generate hash info of idl files, only support 'intf-type hdi'\n"
676            "  -r <rootPackage>:<rootPath>     Set root path of root package, only support 'intf-type hdi'\n"
677            "  -c                              Compile the .idl file\n"
678            "  -D <directory>                  Directory of the idl file, only support 'intf-type hdi'\n"
679            "  -d <directory>                  Place generated codes into <directory>\n"
680            "  -o <file>                       Place the output into <file>, only support 'intf-type hdi'\n"
681            "  -s <file>                       Place the metadata into <file>, only support 'intf-type sa'\n"
682            "      --gen-c                     Generate C codes, only support 'intf-type hdi'\n"
683            "      --gen-cpp                   Generate C++ codes\n"
684            "      --gen-java                  Generate Java codes, only support 'intf-type hdi'\n"
685            "      --gen-rust                  Generate Rust codes, only support 'intf-type sa'\n"
686            "      --gen-ts                    Generate Ts codes, only support 'intf-type sa'\n"
687            "      --log-domainid <domainid>   Place the service domain in <domainid>, Enable log(Pair with -log-tag), "
688            "only support 'intf-type sa'\n"
689            "      --client-enable             Generate client codes, only support 'intf-type sa'\n"
690            "      --log-tag <tag>             Place the subsystem name in <tag>, Enable log(Pair with -log-domainid), "
691            "only support 'intf-type sa'\n"
692            "  -t <hitrace tag>                Place the constant name from hitrace_meter.h file in <hitrace tag>, "
693            "only support 'intf-type sa'\n"
694            "      --intf-type <tag>           Set type of generated codes 'sa' or 'hdi', default type is 'sa'\n");
695 }
696 
697 /*
698  * -r option: -r ohos.hdi:./drivers/interface
699  * package:ohos.hdi.foo.v1_0
700  * rootPackage:ohos.hdi
701  */
GetRootPackage(const std::string & package) const702 std::string Options::GetRootPackage(const std::string &package) const
703 {
704     const auto &packagePaths = GetPackagePathMap();
705     for (const auto &packageRoot : packagePaths) {
706         if (StringHelper::StartWith(package, packageRoot.first)) {
707             return packageRoot.first;
708         }
709     }
710 
711     return "";
712 }
713 
714 /*
715  * -r option: -r ohos.hdi:./drivers/interface
716  * package:ohos.hdi.foo.v1_0
717  * rootPath:./drivers/interface
718  */
GetRootPath(const std::string & package) const719 std::string Options::GetRootPath(const std::string &package) const
720 {
721     const auto &packagePaths = GetPackagePathMap();
722     for (const auto &packageRoot : packagePaths) {
723         if (StringHelper::StartWith(package, packageRoot.first)) {
724             return packageRoot.second;
725         }
726     }
727 
728     return "";
729 }
730 
731 /*
732  * -r option: -r ohos.hdi:./drivers/interface
733  * package:ohos.hdi.foo.v1_0
734  * subPackage:foo.v1_0
735  */
GetSubPackage(const std::string & package) const736 std::string Options::GetSubPackage(const std::string &package) const
737 {
738     if (interfaceType == InterfaceType::SM ||
739         interfaceType == InterfaceType::SM_UDS) {
740         return package;
741     }
742     std::string rootPackage = GetRootPackage(package);
743     if (rootPackage.empty()) {
744         return package;
745     }
746 
747     return package.substr(rootPackage.size() + 1);
748 }
749 
750 /*
751  * -r option: -r ohos.hdi:./drivers/interface
752  * package:ohos.hdi.foo.v1_0
753  * packagePath:./drivers/interface/foo/v1_0
754  */
GetPackagePath(const std::string & package) const755 std::string Options::GetPackagePath(const std::string &package) const
756 {
757     std::string rootPackage = "";
758     std::string rootPath = "";
759     const auto &packagePaths = GetPackagePathMap();
760     for (const auto &packageRoot : packagePaths) {
761         if (StringHelper::StartWith(package, packageRoot.first)) {
762             rootPackage = packageRoot.first;
763             rootPath = packageRoot.second;
764         }
765     }
766 
767     if (rootPackage.empty()) {
768         // The current path is the root path
769         std::string curPath = File::AdapterPath(StringHelper::Replace(package, '.', SEPARATOR));
770         return File::AdapterRealPath(curPath);
771     }
772 
773     if (StringHelper::EndWith(rootPath, SEPARATOR)) {
774         rootPath.pop_back();
775     }
776 
777     std::string subPath = StringHelper::Replace(package.substr(rootPackage.size() + 1), '.', SEPARATOR);
778     return File::AdapterPath(rootPath + "/" + subPath);
779 }
780 
781 /*
782  * -r option: -r ohos.hdi:./drivers/interface
783  * import: ohos.hdi.foo.v1_0.MyTypes
784  * packagePath:./drivers/interface/foo/v1_0/MyTypes.idl
785  */
GetImportFilePath(const std::string & import,const std::string & curPath) const786 std::string Options::GetImportFilePath(const std::string &import, const std::string &curPath) const
787 {
788     if (interfaceType == InterfaceType::SA && genLanguage == Language::CPP) {
789         size_t index = curPath.rfind(SEPARATOR);
790         if (index == std::string::npos || index == curPath.size() - 1) {
791             Logger::E(TAG, "currrent path:%s, is errno", curPath.c_str());
792             return "";
793         }
794         std::string retPath = curPath.substr(0, index + 1);
795         retPath += import + ".idl";
796         return File::AdapterRealPath(retPath);
797     }
798 
799     size_t index = import.rfind('.');
800     if (index == std::string::npos) {
801         return import;
802     }
803 
804     std::string dir = GetPackagePath(StringHelper::SubStr(import, 0, index));
805     std::string className = import.substr(index + 1);
806     return StringHelper::Format("%s%c%s.idl", dir.c_str(), SEPARATOR, className.c_str());
807 }
808 } // namespace Idl
809 } // namespace OHOS