Merge "Enable atspi" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / common / command-line-options.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/system/common/command-line-options.h>
20
21 // EXTERNAL INCLUDES
22 #include <stdlib.h>
23 #include <string.h>
24 #include <iostream>
25
26 #include <dali/public-api/common/dali-vector.h>
27 #include <getopt.h>
28
29 namespace Dali
30 {
31 namespace Internal
32 {
33 namespace Adaptor
34 {
35 namespace
36 {
37 struct Argument
38 {
39   const char* const opt;
40   const char* const optDescription;
41
42   void Print()
43   {
44     const std::ios_base::fmtflags flags = std::cout.flags();
45     std::cout << std::left << "  --";
46     std::cout.width(18);
47     std::cout << opt;
48     std::cout << optDescription;
49     std::cout << std::endl;
50     std::cout.flags(flags);
51   }
52 };
53
54 Argument EXPECTED_ARGS[] =
55   {
56     {"width", "Stage Width"},
57     {"height", "Stage Height"},
58     {"dpi", "Emulated DPI"},
59     {"help", "Help"},
60     {NULL, NULL}};
61
62 enum Option
63 {
64   OPTION_STAGE_WIDTH = 0,
65   OPTION_STAGE_HEIGHT,
66   OPTION_DPI,
67   OPTION_HELP
68 };
69
70 typedef Dali::Vector<int32_t> UnhandledContainer;
71
72 void ShowHelp()
73 {
74   std::cout << "Available options:" << std::endl;
75   Argument* arg = EXPECTED_ARGS;
76   while(arg->opt)
77   {
78     arg->Print();
79     ++arg;
80   }
81 }
82
83 } // unnamed namespace
84
85 CommandLineOptions::CommandLineOptions(int32_t* argc, char** argv[])
86 : stageWidth(0),
87   stageHeight(0)
88 {
89   // Exit gracefully if no arguments provided
90   if(!argc || !argv)
91   {
92     return;
93   }
94
95   if(*argc > 1)
96   {
97     // We do not want to print out errors.
98     int32_t origOptErrValue(opterr);
99     opterr = 0;
100
101     int32_t help(0);
102
103     const struct option options[] =
104       {
105         {EXPECTED_ARGS[OPTION_STAGE_WIDTH].opt, required_argument, NULL, 'w'},  // "--width"
106         {EXPECTED_ARGS[OPTION_STAGE_HEIGHT].opt, required_argument, NULL, 'h'}, // "--height"
107         {EXPECTED_ARGS[OPTION_DPI].opt, required_argument, NULL, 'd'},          // "--dpi"
108         {EXPECTED_ARGS[OPTION_HELP].opt, no_argument, &help, '?'},              // "--help"
109         {0, 0, 0, 0}                                                            // end of options
110       };
111
112     int32_t shortOption(0);
113     int32_t optionIndex(0);
114
115     const char* optString = "-w:h:d:"; // The '-' ensures that argv is NOT permuted
116     bool        optionProcessed(false);
117
118     UnhandledContainer unhandledOptions; // We store indices of options we do not handle here
119
120     do
121     {
122       shortOption = getopt_long(*argc, *argv, optString, options, &optionIndex);
123
124       switch(shortOption)
125       {
126         case 0:
127         {
128           // Check if we want help
129           if(help)
130           {
131             ShowHelp();
132             optionProcessed = true;
133           }
134           break;
135         }
136
137         case 'w':
138         {
139           if(optarg)
140           {
141             stageWidth      = atoi(optarg);
142             optionProcessed = true;
143           }
144           break;
145         }
146
147         case 'h':
148         {
149           if(optarg)
150           {
151             stageHeight     = atoi(optarg);
152             optionProcessed = true;
153           }
154           break;
155         }
156
157         case 'd':
158         {
159           if(optarg)
160           {
161             stageDPI.assign(optarg);
162             optionProcessed = true;
163           }
164           break;
165         }
166
167         case -1:
168         {
169           // All command-line options have been parsed.
170           break;
171         }
172
173         default:
174         {
175           unhandledOptions.PushBack(optind - 1);
176           break;
177         }
178       }
179     } while(shortOption != -1);
180
181     // Take out the options we have processed
182     if(optionProcessed)
183     {
184       if(unhandledOptions.Count() > 0)
185       {
186         int32_t index(1);
187
188         // Overwrite the argv with the values from the unhandled indices
189         const UnhandledContainer::ConstIterator endIter = unhandledOptions.End();
190         for(UnhandledContainer::Iterator iter = unhandledOptions.Begin(); iter != endIter; ++iter)
191         {
192           (*argv)[index++] = (*argv)[*iter];
193         }
194         *argc = unhandledOptions.Count() + 1; // +1 for the program name
195       }
196       else
197       {
198         // There are no unhandled options, so we should just have the program name
199         *argc = 1;
200       }
201
202       optind = 1; // Reset to start
203     }
204
205     opterr = origOptErrValue; // Reset opterr value.
206   }
207 }
208
209 CommandLineOptions::~CommandLineOptions()
210 {
211 }
212
213 } // namespace Adaptor
214
215 } // namespace Internal
216
217 } // namespace Dali