1 /*
2  * Copyright (c) 2023 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 "CommandParser.h"
17 #include <cstring>
18 #include <algorithm>
19 #include <cstdlib>
20 #include <regex>
21 #include "FileSystem.h"
22 #include "PreviewerEngineLog.h"
23 #include "TraceTool.h"
24 
25 CommandParser* CommandParser::example = nullptr;
CommandParser()26 CommandParser::CommandParser()
27     : isSendJSHeap(true),
28       orignalResolutionWidth(0),
29       orignalResolutionHeight(0),
30       compressionResolutionWidth(0),
31       compressionResolutionHeight(0),
32       jsHeapSize(MAX_JSHEAPSIZE),
33       deviceType("liteWearable"),
34       screenShape("circle"),
35       appName("undefined"),
36       configPath(""),
37       isRegionRefresh(false),
38       isCardDisplay(false),
39       projectID(""),
40       screenMode(CommandParser::ScreenMode::DYNAMIC),
41       configChanges(""),
42       appResourcePath(""),
43       projectModel("FA"),
44       pages("main_pages"),
45       containerSdkPath(""),
46       isComponentMode(false),
47       abilityPath(""),
48 #ifdef COMPONENT_TEST_ENABLED
49       componentTestConfig(""),
50 #endif // COMPONENT_TEST_ENABLED
51       staticCard(false)
52 {
53     Register("-j", 1, "Launch the js app in <directory>.");
54     Register("-n", 1, "Set the js app name show on <window title>.");
55     Register("-d", 0, "Run in debug mode and start debug server.");
56     Register("-p", 1, "Config debug server to listen <port>.");
57     Register("-s", 1, "Local socket name <socket-name> for command line interface.");
58     Register("-v", 0, "Print the periviewer engine version.");
59     Register("-h", 0, "Print the usage help.");
60     Register("-or", 2, "Original resolution <width> <height>"); // 2 arguments
61     Register("-cr", 2, "Compression resolution <width> <height>"); // 2 arguments
62     Register("-f", 1, "config path <path>");
63     Register("-hs", 1, "JS Heap <size>");
64     Register("-hf", 1, "JS Send Heap <flag>");
65     Register("-shape", 1, "Screen shape <shape>");
66     Register("-device", 1, "Device type <type>");
67     Register("-url", 1, "temp url");
68     Register("-refresh", 1, "Screen <refresh mode>, support region and full");
69     Register("-card", 1, "Controls the display <type> to switch between the app and card.");
70     Register("-projectID", 1, "the ID of current project.");
71     Register("-ts", 1, "Trace socket name");
72     Register("-cm", 1, "Set colormode for the theme.");
73     Register("-o", 1, "Set orientation for the display.");
74     Register("-lws", 1, "Listening port of WebSocket");
75     Register("-av", 1, "Set ace version.");
76     Register("-l", 1, "Set language for startParam.");
77     Register("-sd", 1, "Set screenDensity for Previewer.");
78     Register("-sm", 1, "Set Screen picture transport mode, support dynamic and static");
79     Register("-cc", 1, "Set Resource configChanges.");
80     Register("-arp", 1, "Set App ResourcePath.");
81     Register("-fs", 1, "Select Fonts sources.");
82     Register("-pm", 1, "Set project model type.");
83     Register("-pages", 1, "Set project's router config file path.");
84     Register("-hsp", 1, "Set container sdk path.");
85     Register("-cpm", 1, "Set previewer start mode.");
86     Register("-abp", 1, "Set abilityPath for debug.");
87     Register("-abn", 1, "Set abilityName for debug.");
88     Register("-staticCard", 1, "Set card mode.");
89     Register("-foldable", 1, "Set foldable for Previewer.");
90     Register("-foldStatus", 1, "Set fold status for Previewer.");
91     Register("-fr", 2, "Fold resolution <width> <height>"); // 2 arguments
92     Register("-ljPath", 1, "Set loader.json path for Previewer");
93 #ifdef COMPONENT_TEST_ENABLED
94     Register("-componentTest", 1, "Set component test config");
95 #endif // COMPONENT_TEST_ENABLED
96 }
97 
GetInstance()98 CommandParser& CommandParser::GetInstance()
99 {
100     static CommandParser instance;
101     return instance;
102 }
103 
104 /*
105  * Parse user input and check parameter validity
106  */
ProcessCommand(std::vector<std::string> strs)107 bool CommandParser::ProcessCommand(std::vector<std::string> strs)
108 {
109     ProcessingCommand(strs);
110 
111     if (IsSet("v")) {
112         ELOG("ProcessCommand Set -v!");
113         return false;
114     }
115 
116     if (IsSet("h")) {
117         ELOG("ProcessCommand Set -h!");
118         ELOG(HelpText().c_str());
119         return false;
120     }
121 
122     return true;
123 }
124 
IsCommandValid()125 bool CommandParser::IsCommandValid()
126 {
127     bool partRet = IsDebugPortValid() && IsAppPathValid() && IsAppNameValid() && IsResolutionValid();
128     partRet = partRet && IsConfigPathValid() && IsJsHeapValid() && IsJsHeapFlagValid() && IsScreenShapeValid();
129     partRet = partRet && IsDeviceValid() && IsUrlValid() && IsRefreshValid() && IsCardValid() && IsProjectIDValid();
130     partRet = partRet && IsColorModeValid() && IsOrientationValid() && IsWebSocketPortValid() && IsAceVersionValid();
131     partRet = partRet && IsScreenModeValid() && IsAppResourcePathValid() && IsLoaderJsonPathValid();
132     partRet = partRet && IsProjectModelValid() && IsPagesValid() && IsContainerSdkPathValid();
133     partRet = partRet && IsComponentModeValid() && IsAbilityPathValid() && IsStaticCardValid();
134     partRet = partRet && IsFoldableValid() && IsFoldStatusValid() && IsFoldResolutionValid();
135     partRet = partRet && IsAbilityNameValid() && IsLanguageValid() && IsTracePipeNameValid();
136     partRet = partRet && IsLocalSocketNameValid() && IsConfigChangesValid() && IsScreenDensityValid();
137     if (partRet) {
138         return true;
139     }
140     ELOG(errorInfo.c_str());
141     ILOG(HelpText().c_str());
142     TraceTool::GetInstance().HandleTrace("Invalid startup parameters");
143     return false;
144 }
145 
IsSet(std::string key)146 bool CommandParser::IsSet(std::string key)
147 {
148     if (argsMap.find(std::string("-") + key) == argsMap.end()) {
149         return false;
150     }
151     return true;
152 }
153 
Value(std::string key)154 std::string CommandParser::Value(std::string key)
155 {
156     auto args = argsMap[std::string("-") + key];
157     if (args.size() > 0) {
158         return args[0];
159     }
160     return std::string();
161 }
162 
Values(std::string key)163 std::vector<std::string> CommandParser::Values(std::string key)
164 {
165     if (argsMap.find(key) == argsMap.end()) {
166         return std::vector<std::string>();
167     }
168     std::vector<std::string> args = argsMap[key];
169     return args;
170 }
171 
Register(std::string key, uint32_t argc, std::string help)172 void CommandParser::Register(std::string key, uint32_t argc, std::string help)
173 {
174     regsArgsCountMap[key] = argc;
175     regsHelpMap[key] = help;
176 }
177 
IsResolutionValid(int32_t resolution) const178 bool CommandParser::IsResolutionValid(int32_t resolution) const
179 {
180     if (resolution >= MIN_RESOLUTION && resolution <= MAX_RESOLUTION) {
181         return true;
182     }
183     return false;
184 }
185 
GetDeviceType() const186 std::string CommandParser::GetDeviceType() const
187 {
188     return deviceType;
189 }
190 
IsRegionRefresh() const191 bool CommandParser::IsRegionRefresh() const
192 {
193     return isRegionRefresh;
194 }
195 
IsCardDisplay() const196 bool CommandParser::IsCardDisplay() const
197 {
198     return isCardDisplay;
199 }
200 
GetConfigPath() const201 std::string CommandParser::GetConfigPath() const
202 {
203     return configPath;
204 }
205 
GetProjectID() const206 std::string CommandParser::GetProjectID() const
207 {
208     return projectID;
209 }
210 
GetAppResourcePath() const211 std::string CommandParser::GetAppResourcePath() const
212 {
213     return appResourcePath;
214 }
215 
GetScreenShape() const216 std::string CommandParser::GetScreenShape() const
217 {
218     return screenShape;
219 }
220 
GetProjectModel() const221 std::string CommandParser::GetProjectModel() const
222 {
223     return projectModel;
224 }
225 
GetPages() const226 std::string CommandParser::GetPages() const
227 {
228     return pages;
229 }
230 
GetContainerSdkPath() const231 std::string CommandParser::GetContainerSdkPath() const
232 {
233     return containerSdkPath;
234 }
235 
GetScreenMode() const236 CommandParser::ScreenMode CommandParser::GetScreenMode() const
237 {
238     return screenMode;
239 }
240 
GetConfigChanges() const241 std::string CommandParser::GetConfigChanges() const
242 {
243     return configChanges;
244 }
245 
GetOrignalResolutionWidth() const246 int32_t CommandParser::GetOrignalResolutionWidth() const
247 {
248     return orignalResolutionWidth;
249 }
250 
GetOrignalResolutionHeight() const251 int32_t CommandParser::GetOrignalResolutionHeight() const
252 {
253     return orignalResolutionHeight;
254 }
255 
GetCompressionResolutionWidth() const256 int32_t CommandParser::GetCompressionResolutionWidth() const
257 {
258     return compressionResolutionWidth;
259 }
260 
GetCompressionResolutionHeight() const261 int32_t CommandParser::GetCompressionResolutionHeight() const
262 {
263     return compressionResolutionHeight;
264 }
265 
GetJsHeapSize() const266 uint32_t CommandParser::GetJsHeapSize() const
267 {
268     return jsHeapSize;
269 }
270 
GetAppName() const271 std::string CommandParser::GetAppName() const
272 {
273     return appName;
274 }
275 
IsSendJSHeap() const276 bool CommandParser::IsSendJSHeap() const
277 {
278     return isSendJSHeap;
279 }
280 
IsComponentMode() const281 bool CommandParser::IsComponentMode() const
282 {
283     return isComponentMode;
284 }
285 
GetAbilityPath() const286 std::string CommandParser::GetAbilityPath() const
287 {
288     return abilityPath;
289 }
290 
GetAbilityName() const291 std::string CommandParser::GetAbilityName() const
292 {
293     return abilityName;
294 }
295 
IsStaticCard() const296 bool CommandParser::IsStaticCard() const
297 {
298     return staticCard;
299 }
300 
IsDebugPortValid()301 bool CommandParser::IsDebugPortValid()
302 {
303     if (IsSet("p")) {
304         if (CheckParamInvalidity(Value("p"), true)) {
305             errorInfo = "Launch -p parameters is not match regex.";
306             return false;
307         }
308         int port = atoi(Value("p").c_str());
309         if (port < MIN_PORT || port > MAX_PORT) {
310             errorInfo =
311                 std::string("Debug server port out of range: " + std::to_string(MIN_PORT) + "-" +
312                 std::to_string(MAX_PORT) + ".");
313             ELOG("Launch -p parameters abnormal!");
314             return false;
315         }
316     }
317     ILOG("CommandParser debug port: %s", Value("p").c_str());
318     return true;
319 }
320 
IsAppPathValid()321 bool CommandParser::IsAppPathValid()
322 {
323     if (!IsSet("j")) {
324         errorInfo = std::string("No app path specified.");
325         ELOG("Launch -j parameters abnormal!");
326         return false;
327     }
328     std::string path = Value("j");
329     if (!FileSystem::IsDirectoryExists(path)) {
330         errorInfo = std::string("Js app path not exist.");
331         ELOG("Launch -j parameters abnormal!");
332         return false;
333     }
334 
335     return true;
336 }
337 
IsAppNameValid()338 bool CommandParser::IsAppNameValid()
339 {
340     if (IsSet("n")) {
341         if (CheckParamInvalidity(Value("n"), false)) {
342             errorInfo = "Launch -n parameters is not match regex.";
343             return false;
344         }
345         size_t size = Value("n").size();
346         if (size > MAX_NAME_LENGTH) {
347             errorInfo = std::string("Js app name it too long, max: " + std::to_string(MAX_NAME_LENGTH) + ".");
348             return false;
349         }
350         appName = Value("n");
351     }
352     ILOG("CommandParser app name: %s", appName.c_str());
353     return true;
354 }
355 
IsResolutionValid()356 bool CommandParser::IsResolutionValid()
357 {
358     if (IsSet("or") && IsSet("cr")) {
359         if (IsResolutionArgValid(std::string("-or")) && IsResolutionArgValid(std::string("-cr"))) {
360             orignalResolutionWidth = atoi(Values("-or")[0].c_str());
361             orignalResolutionHeight = atoi(Values("-or")[1].c_str());
362             compressionResolutionWidth = atoi(Values("-cr")[0].c_str());
363             compressionResolutionHeight = atoi(Values("-cr")[1].c_str());
364             ILOG("CommandParser resolution: %d %d %d %d", orignalResolutionWidth, orignalResolutionHeight,
365                  compressionResolutionWidth, compressionResolutionHeight);
366             return true;
367         }
368         ELOG("Launch -cr/-or parameters abnormal!");
369         return false;
370     }
371     ELOG("Launch -cr/-or parameters abnormal!");
372     errorInfo = std::string("Origin resolution and compress resolution must be setted.");
373     return false;
374 }
375 
IsJsHeapValid()376 bool CommandParser::IsJsHeapValid()
377 {
378     if (IsSet("hs")) {
379         if (CheckParamInvalidity(Value("hs"), true)) {
380             errorInfo = "Launch -hs parameters is not match regex.";
381             return false;
382         }
383         int size = atoi(Value("hs").c_str());
384         if (size < MIN_JSHEAPSIZE || size > MAX_JSHEAPSIZE) {
385             errorInfo = std::string("JS heap size out of range: " + std::to_string(MIN_JSHEAPSIZE) + "-" +
386                 std::to_string(MAX_JSHEAPSIZE) + ".");
387             ELOG("Launch -hs parameters abnormal!");
388             return false;
389         }
390         jsHeapSize = static_cast<uint32_t>(size);
391     }
392     ILOG("CommandParser js heap: %d", jsHeapSize);
393     return true;
394 }
395 
IsJsHeapFlagValid()396 bool CommandParser::IsJsHeapFlagValid()
397 {
398     if (IsSet("hf")) {
399         std::string flag = Value("hf");
400         if (flag != "true" && flag != "false") {
401             errorInfo = std::string("JS heap flag suported: true or false");
402             ELOG("Launch -hs parameters abnormal!");
403             return false;
404         }
405         isSendJSHeap = (flag == "true");
406     }
407     ILOG("CommandParser is send JS heap: %d", isSendJSHeap);
408     return true;
409 }
410 
IsScreenShapeValid()411 bool CommandParser::IsScreenShapeValid()
412 {
413     if (IsSet("shape")) {
414         std::string shape = Value("shape");
415         if (shape != "rect" && shape != "circle") {
416             errorInfo = std::string("Screen shape suported: rect or circle");
417             ELOG("The current device does not support, please upgrade the SDK!");
418             return false;
419         }
420         screenShape = shape;
421     }
422     ILOG("CommandParser screen shape: %s", screenShape.c_str());
423     return true;
424 }
425 
IsDeviceValid()426 bool CommandParser::IsDeviceValid()
427 {
428     if (IsSet("device")) {
429         auto iter = find(supportedDevices.begin(), supportedDevices.end(), Value("device"));
430         if (iter == supportedDevices.end()) {
431             errorInfo += std::string("Device type unsupport, please upgrade the Previewer SDK!");
432             ELOG("Device type unsupport!");
433             return false;
434         }
435     }
436     deviceType = Value("device");
437     ILOG("CommandParser device: %s", deviceType.c_str());
438     return true;
439 }
440 
IsUrlValid()441 bool CommandParser::IsUrlValid()
442 {
443     urlPath = Value("url");
444     if (urlPath.empty()) {
445         errorInfo = "Launch -url parameters is empty.";
446         return false;
447     }
448     ILOG("CommandParser url: %s", urlPath.c_str());
449     return true;
450 }
451 
IsConfigPathValid()452 bool CommandParser::IsConfigPathValid()
453 {
454     if (!IsSet("f")) {
455         return true;
456     }
457 
458     std::string path = Value("f");
459     if (!FileSystem::IsFileExists(path)) {
460         errorInfo = std::string("The configuration file path does not exist.");
461         ELOG("Launch -f parameters abnormal!");
462         return false;
463     }
464     configPath = path;
465     return true;
466 }
467 
IsAppResourcePathValid()468 bool CommandParser::IsAppResourcePathValid()
469 {
470     if (!IsSet("arp")) {
471         return true;
472     }
473 
474     std::string path = Value("arp");
475     if (!FileSystem::IsDirectoryExists(path)) {
476         errorInfo = std::string("The configuration appResource path does not exist.");
477         ELOG("Launch -arp parameters abnormal!");
478         return false;
479     }
480     appResourcePath = path;
481     return true;
482 }
483 
IsProjectModelValid()484 bool CommandParser::IsProjectModelValid()
485 {
486     if (!IsSet("pm")) {
487         return true;
488     }
489 
490     std::string projectModelStr = Value("pm");
491     auto iter = find(projectModels.begin(), projectModels.end(), projectModelStr);
492     if (iter == projectModels.end()) {
493         errorInfo = std::string("The project model does not exist.");
494         ELOG("Launch -pm parameters abnormal!");
495         return false;
496     }
497 
498     projectModel = projectModelStr;
499     ILOG("CommandParser projectModel: %s", projectModelStr.c_str());
500     return true;
501 }
502 
IsPagesValid()503 bool CommandParser::IsPagesValid()
504 {
505     if (!IsSet("pages")) {
506         return true;
507     }
508     pages = Value("pages");
509     if (CheckParamInvalidity(pages, false)) {
510         errorInfo = "Launch -pages parameters is not match regex.";
511         return false;
512     }
513     ILOG("CommandParser pages: %s", pages.c_str());
514     return true;
515 }
516 
IsResolutionArgValid(std::string command)517 bool CommandParser::IsResolutionArgValid(std::string command)
518 {
519     std::vector<std::string> value = Values(command);
520     uint32_t size = regsArgsCountMap[command];
521     if (value.size() != size) {
522         errorInfo = std::string("Invalid argument's count.");
523         return false;
524     }
525     if (IsResolutionRangeValid(value[0]) && IsResolutionRangeValid(value[1])) {
526         return true;
527     }
528     return false;
529 }
530 
IsResolutionRangeValid(std::string value)531 bool CommandParser::IsResolutionRangeValid(std::string value)
532 {
533     if (CheckParamInvalidity(value, true)) {
534         errorInfo = "Launch -or/-cr or -fr parameters is not match regex.";
535         return false;
536     }
537     int32_t temp = atoi(value.c_str());
538     if (!IsResolutionValid(temp)) {
539         errorInfo = std::string("Resolution range " + std::to_string(MIN_RESOLUTION) + "-" +
540             std::to_string(MAX_RESOLUTION) + ".");
541         return false;
542     }
543     return true;
544 }
545 
IsRefreshValid()546 bool CommandParser::IsRefreshValid()
547 {
548     if (!IsSet("refresh")) {
549         return true;
550     }
551 
552     std::string refresh = Value("refresh");
553     if (refresh != "region" && refresh != "full") {
554         errorInfo = std::string("The refresh argument unsupported.");
555         ELOG("Launch -refresh parameters abnormal!");
556         return false;
557     }
558     if (refresh == "region") {
559         isRegionRefresh = true;
560     }
561     return true;
562 }
563 
IsCardValid()564 bool CommandParser::IsCardValid()
565 {
566     if (!IsSet("card")) {
567         return true;
568     }
569 
570     std::string card = Value("card");
571     if (card != "true" && card != "false") {
572         errorInfo = std::string("The card argument unsupported.");
573         ELOG("Launch -card parameters abnormal!");
574         return false;
575     }
576 
577     std::string devicetype = GetDeviceType();
578     auto iter = find(cardDisplayDevices.begin(), cardDisplayDevices.end(), devicetype);
579     if (iter != cardDisplayDevices.end() && card == "true") {
580         isCardDisplay = true;
581     }
582     return true;
583 }
584 
IsProjectIDValid()585 bool CommandParser::IsProjectIDValid()
586 {
587     if (IsSet("projectID")) {
588         projectID = Value("projectID");
589         if (CheckParamInvalidity(projectID, false)) {
590             errorInfo = "Launch -projectID parameters is not match regex.";
591             return false;
592         }
593     }
594     return true;
595 }
596 
IsColorModeValid()597 bool CommandParser::IsColorModeValid()
598 {
599     if (!IsSet("cm")) {
600         return true;
601     }
602 
603     std::string colorMode = Value("cm");
604     if (colorMode != "dark" && colorMode != "light") {
605         errorInfo = std::string("The colormode argument unsupported.");
606         ELOG("Launch -cm parameters abnormal!");
607         return false;
608     }
609     return true;
610 }
611 
IsAceVersionValid()612 bool CommandParser::IsAceVersionValid()
613 {
614     if (!IsSet("av")) {
615         return true;
616     }
617 
618     std::string aceVersion = Value("av");
619     if (aceVersion != "ACE_1_0" && aceVersion != "ACE_2_0") {
620         errorInfo = std::string("The aceVersion argument unsupported.");
621         ELOG("Launch -av parameters abnormal!");
622         return false;
623     }
624     return true;
625 }
626 
IsOrientationValid()627 bool CommandParser::IsOrientationValid()
628 {
629     if (!IsSet("o")) {
630         return true;
631     }
632 
633     std::string orientation = Value("o");
634     if (orientation != "portrait" && orientation != "landscape") {
635         errorInfo = std::string("The orientation argument unsupported.");
636         ELOG("Launch -o parameters abnormal!");
637         return false;
638     }
639     return true;
640 }
641 
IsWebSocketPortValid()642 bool CommandParser::IsWebSocketPortValid()
643 {
644     if (IsSet("lws")) {
645         if (CheckParamInvalidity(Value("lws"), true)) {
646             errorInfo = "Launch -lws parameters is not match regex.";
647             return false;
648         }
649         int port = atoi(Value("lws").c_str());
650         if (port < MIN_PORT || port > MAX_PORT) {
651             errorInfo = std::string("WebSocket listening port out of range: " + std::to_string(MIN_PORT) + "-" +
652                 std::to_string(MAX_PORT) + ".");
653             ELOG("Launch -lws parameters abnormal!");
654             return false;
655         }
656     }
657     ILOG("CommandParser WebSocket listening port: %s", Value("lws").c_str());
658     return true;
659 }
660 
IsScreenModeValid()661 bool CommandParser::IsScreenModeValid()
662 {
663     std::string mode("dynamic");
664     if (IsSet("sm")) {
665         mode = Value("sm");
666         if (mode != "dynamic" && mode != "static") {
667             errorInfo = std::string("Screen picture transport mode suported: dynamic or static");
668             ELOG("Launch -sm parameters abnormal!");
669             return false;
670         }
671         screenMode = (mode == "static" ? CommandParser::ScreenMode::STATIC :
672                       CommandParser::ScreenMode::DYNAMIC);
673     }
674     ILOG("CommandParser screen mode: %s", mode.c_str());
675     return true;
676 }
677 
IsLanguageValid()678 bool CommandParser::IsLanguageValid()
679 {
680     if (!IsSet("l")) {
681         return true;
682     }
683     std::string lan = Value("l");
684     if (CheckParamInvalidity(lan, false)) {
685         errorInfo = "Launch -l parameters is not match regex.";
686         return false;
687     }
688     ILOG("CommandParser l: %s", lan.c_str());
689     return true;
690 }
691 
IsTracePipeNameValid()692 bool CommandParser::IsTracePipeNameValid()
693 {
694     if (!IsSet("ts")) {
695         return true;
696     }
697     std::string tsName = Value("ts");
698     if (CheckParamInvalidity(tsName, false)) {
699         errorInfo = "Launch -ts parameters is not match regex.";
700         return false;
701     }
702     ILOG("CommandParser ts: %s", tsName.c_str());
703     return true;
704 }
705 
IsLocalSocketNameValid()706 bool CommandParser::IsLocalSocketNameValid()
707 {
708     if (!IsSet("s")) {
709         return true;
710     }
711     std::string socketName = Value("s");
712     std::string regexStr = "^(?:[a-zA-Z0-9-_./\\s*]+)$";
713     std::regex reg(regexStr);
714     if (!std::regex_match(socketName.cbegin(), socketName.cend(), reg)) {
715         errorInfo = "Launch -s parameters is not match regex.";
716         return false;
717     }
718     ILOG("CommandParser s: %s", socketName.c_str());
719     return true;
720 }
721 
IsConfigChangesValid()722 bool CommandParser::IsConfigChangesValid()
723 {
724     if (!IsSet("cc")) {
725         return true;
726     }
727     std::string configChange = Value("cc");
728     if (CheckParamInvalidity(configChange, false)) {
729         ELOG("Launch -cc parameters is not match regex.");
730         return false;
731     }
732     ILOG("CommandParser cc: %s", configChange.c_str());
733     return true;
734 }
735 
IsScreenDensityValid()736 bool CommandParser::IsScreenDensityValid()
737 {
738     if (!IsSet("sd")) {
739         return true;
740     }
741     std::string density = Value("sd");
742     if (CheckParamInvalidity(density, true)) {
743         errorInfo = "Launch -sd parameters is not match regex.";
744         return false;
745     }
746     ILOG("CommandParser sd: %s", density.c_str());
747     return true;
748 }
749 
IsContainerSdkPathValid()750 bool CommandParser::IsContainerSdkPathValid()
751 {
752     if (!IsSet("hsp")) {
753         return true;
754     }
755 
756     std::string path = Value("hsp");
757     if (!FileSystem::IsDirectoryExists(path)) {
758         errorInfo = std::string("The container sdk path does not exist.");
759         ELOG("Launch -hsp parameters abnormal!");
760         return false;
761     }
762     containerSdkPath = path;
763     return true;
764 }
765 
HelpText()766 std::string CommandParser::HelpText()
767 {
768     std::string helpText = "Usage:\n";
769     for (auto index = regsHelpMap.begin(); index != regsHelpMap.end(); index++) {
770         helpText += "-" + index->first + " ";
771         helpText += index->second + "\n";
772     }
773     return helpText;
774 }
775 
ProcessingCommand(const std::vector<std::string>& strs)776 void CommandParser::ProcessingCommand(const std::vector<std::string>& strs)
777 {
778     for (unsigned int i = 0; i < strs.size(); ++i) {
779         std::string index = strs[i];
780         auto regInfo = regsArgsCountMap.find(strs[i]);
781         if (regInfo == regsArgsCountMap.end()) {
782             continue;
783         }
784 
785         std::vector<std::string> args;
786         for (uint32_t j = 0; j < regInfo->second; ++j) {
787             if (i == strs.size() - 1  || strs[i + 1][0] == '-') {
788                 args.push_back("");
789                 break;
790             }
791             args.push_back(strs[++i]);
792         }
793         argsMap[index] = args;
794     }
795 }
796 
GetProjectModelEnumValue() const797 int CommandParser::GetProjectModelEnumValue() const
798 {
799     auto idxVal = std::distance(projectModels.begin(),
800                                 find(projectModels.begin(), projectModels.end(), projectModel));
801     idxVal = (idxVal >= projectModels.size()) ? 0 : idxVal;
802     return idxVal;
803 }
804 
GetProjectModelEnumName(int enumValue) const805 std::string CommandParser::GetProjectModelEnumName(int enumValue) const
806 {
807     if (enumValue < 0 || enumValue >= projectModels.size()) {
808         enumValue = 0;
809     }
810     return projectModels[enumValue];
811 }
812 
CheckParamInvalidity(std::string param, bool isNum = false)813 bool CommandParser::CheckParamInvalidity(std::string param, bool isNum = false)
814 {
815     std::regex reg(isNum ? regex4Num : regex4Str);
816     return !std::regex_match(param.cbegin(), param.cend(), reg);
817 }
818 
IsComponentModeValid()819 bool CommandParser::IsComponentModeValid()
820 {
821     if (!IsSet("cpm")) {
822         return true;
823     }
824 
825     std::string cpm = Value("cpm");
826     if (cpm != "true" && cpm != "false") {
827         errorInfo = std::string("The component mode argument unsupported.");
828         ELOG("Launch -cpm parameters abnormal!");
829         return false;
830     }
831 
832     isComponentMode = cpm == "true" ? true : false;
833     return true;
834 }
835 
IsAbilityPathValid()836 bool CommandParser::IsAbilityPathValid()
837 {
838     if (!IsSet("d")) {
839         return true;
840     }
841     if (deviceType == "liteWearable" || deviceType == "smartVision") {
842         return true;
843     }
844     if (!IsSet("abp")) {
845         errorInfo = "Launch -d parameters without -abp parameters.";
846         return false;
847     }
848     std::string path = Value("abp");
849     if (path.empty()) {
850         errorInfo = std::string("The ability path is empty.");
851         ELOG("Launch -abp parameters abnormal!");
852         return false;
853     }
854     abilityPath = path;
855     return true;
856 }
857 
IsAbilityNameValid()858 bool CommandParser::IsAbilityNameValid()
859 {
860     if (!IsSet("d")) {
861         return true;
862     }
863     if (deviceType == "liteWearable" || deviceType == "smartVision") {
864         return true;
865     }
866     if (!IsSet("abn")) {
867         ELOG("Launch -d parameters without -abn parameters.");
868         return true; // 兼容老版本IDE(沒有abn参数)
869     }
870     std::string name = Value("abn");
871     if (name.empty()) {
872         errorInfo = std::string("The ability name is empty.");
873         ELOG("Launch -abn parameters abnormal!");
874         return false;
875     }
876     abilityName = name;
877     return true;
878 }
879 
IsStaticCardValid()880 bool CommandParser::IsStaticCardValid()
881 {
882     if (!IsSet("staticCard")) {
883         return true;
884     }
885     std::string val = Value("staticCard");
886     if (val != "true" && val != "false") {
887         errorInfo = std::string("The staticCard argument unsupported.");
888         ELOG("Launch -staticCard parameters abnormal!");
889         return false;
890     }
891     if (val == "true") {
892         staticCard = true;
893     }
894     return true;
895 }
896 
IsMainArgLengthInvalid(const char* str) const897 bool CommandParser::IsMainArgLengthInvalid(const char* str) const
898 {
899     size_t argLength = strlen(str);
900     if (argLength > maxMainArgLength) {
901         ELOG("param size is more than %d", maxMainArgLength);
902         return true;
903     }
904     return false;
905 }
906 
IsFoldableValid()907 bool CommandParser::IsFoldableValid()
908 {
909     if (!IsSet("foldable")) {
910         return true;
911     }
912     std::string val = Value("foldable");
913     if (val != "true" && val != "false") {
914         errorInfo = std::string("The foldable argument unsupported.");
915         ELOG("Launch -foldable parameters abnormal!");
916         return false;
917     }
918     if (val == "true") {
919         foldable = true;
920     }
921     return true;
922 }
923 
IsFoldStatusValid()924 bool CommandParser::IsFoldStatusValid()
925 {
926     if ((!IsSet("foldable")) || Value("foldable") != "true") {
927         return true;
928     }
929     if (IsSet("foldStatus")) {
930         if (Value("foldStatus") == "fold" || Value("foldStatus") == "unfold" ||
931             Value("foldStatus") == "unknown" || Value("foldStatus") == "half_fold") {
932             foldStatus = Value("foldStatus");
933             return true;
934         }
935     }
936     ELOG("Launch -foldStatus parameters abnormal!");
937     return false;
938 }
939 
IsFoldResolutionValid()940 bool CommandParser::IsFoldResolutionValid()
941 {
942     if ((!IsSet("foldable")) || Value("foldable") != "true") {
943         return true;
944     }
945     if (IsSet("fr")) {
946         if (IsResolutionArgValid(std::string("-fr"))) {
947             foldResolutionWidth = atoi(Values("-fr")[0].c_str());
948             foldResolutionHeight = atoi(Values("-fr")[1].c_str());
949             ILOG("CommandParser fold resolution: %d %d", foldResolutionWidth, foldResolutionHeight);
950             return true;
951         }
952         ELOG("Launch -fr parameters abnormal!");
953         return false;
954     }
955     ELOG("Launch -fr parameters abnormal!");
956     errorInfo = std::string("Fold resolution must be setted.");
957     return false;
958 }
959 
IsFoldable() const960 bool CommandParser::IsFoldable() const
961 {
962     return foldable;
963 }
964 
GetFoldStatus() const965 std::string CommandParser::GetFoldStatus() const
966 {
967     return foldStatus;
968 }
969 
GetFoldResolutionWidth() const970 int32_t CommandParser::GetFoldResolutionWidth() const
971 {
972     return foldResolutionWidth;
973 }
974 
GetFoldResolutionHeight() const975 int32_t CommandParser::GetFoldResolutionHeight() const
976 {
977     return foldResolutionHeight;
978 }
979 
GetLoaderJsonPath() const980 std::string CommandParser::GetLoaderJsonPath() const
981 {
982     return loaderJsonPath;
983 }
984 
IsLoaderJsonPathValid()985 bool CommandParser::IsLoaderJsonPathValid()
986 {
987     if (!IsSet("ljPath")) {
988         return true;
989     }
990     std::string path = Value("ljPath");
991     if (!FileSystem::IsFileExists(path)) {
992         errorInfo = std::string("The configuration loader.json path does not exist.");
993         ELOG("Launch -ljPath parameters abnormal!");
994         return false;
995     }
996     loaderJsonPath = path;
997     return true;
998 }
999 
ParseArgs(int argc, char* argv[])1000 int CommandParser::ParseArgs(int argc, char* argv[])
1001 {
1002     int startParamInvalidCode = 11;
1003     int defaultReturnVal = -1;
1004     std::vector<std::string> strs;
1005     for (int i = 1; i < argc; ++i) {
1006         if (IsMainArgLengthInvalid(argv[i])) {
1007             return startParamInvalidCode;
1008         }
1009         strs.push_back(argv[i]);
1010     }
1011     if (!ProcessCommand(strs)) {
1012         return 0;
1013     }
1014     if (!IsCommandValid()) {
1015         FLOG("Start args is invalid.");
1016         return startParamInvalidCode;
1017     }
1018     return defaultReturnVal;
1019 }
1020 
GetCommandInfo(CommandInfo& info) const1021 void CommandParser::GetCommandInfo(CommandInfo& info) const
1022 {
1023     info.deviceType = GetDeviceType();
1024     info.pages = GetPages();
1025     info.appResourcePath = GetAppResourcePath();
1026     info.isCardDisplay = IsCardDisplay();
1027     info.containerSdkPath = GetContainerSdkPath();
1028     info.isComponentMode = IsComponentMode();
1029     info.loaderJsonPath = GetLoaderJsonPath();
1030     info.abilityPath = GetAbilityPath();
1031     info.abilityName = GetAbilityName();
1032     info.configPath = GetConfigPath();
1033     info.screenShape = GetScreenShape();
1034     info.orignalResolutionWidth = GetOrignalResolutionWidth();
1035     info.orignalResolutionHeight = GetOrignalResolutionHeight();
1036     info.compressionResolutionWidth = GetCompressionResolutionWidth();
1037     info.compressionResolutionHeight = GetCompressionResolutionHeight();
1038 }
1039 
GetFoldInfo(FoldInfo& info) const1040 void CommandParser::GetFoldInfo(FoldInfo& info) const
1041 {
1042     info.foldable = IsFoldable();
1043     info.foldStatus = GetFoldStatus();
1044     info.foldResolutionWidth = GetFoldResolutionWidth();
1045     info.foldResolutionHeight = GetFoldResolutionHeight();
1046 }
1047 
1048 #ifdef COMPONENT_TEST_ENABLED
GetComponentTestConfig() const1049 std::string CommandParser::GetComponentTestConfig() const
1050 {
1051     return componentTestConfig;
1052 }
1053 #endif // COMPONENT_TEST_ENABLED