]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_command_line_params.cpp
Initial vogl checkin
[vogl] / src / voglcore / vogl_command_line_params.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_command_line_params.cpp
28 #include "vogl_core.h"
29 #include "vogl_command_line_params.h"
30 #include "vogl_console.h"
31 #include "vogl_cfile_stream.h"
32 #include "vogl_strutils.h"
33
34 #ifdef WIN32
35 #define VOGL_CMD_LINE_ALLOW_SLASH_PARAMS 1
36 #endif
37
38 #ifdef VOGL_USE_WIN32_API
39 #include "vogl_winhdr.h"
40 #endif
41
42 #ifdef VOGL_USE_LINUX_API
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #endif
46
47 namespace vogl
48 {
49     command_line_params g_command_line_params;
50
51     dynamic_string_array get_command_line_params(int argc, char *argv[])
52     {
53         dynamic_string_array params;
54         for (int i = 0; i < argc; i++)
55             params.push_back(dynamic_string(argv[i]));
56         return params;
57     }
58
59     dynamic_string_array get_command_line_params()
60     {
61         dynamic_string_array params;
62
63 #ifdef VOGL_USE_WIN32_API
64         dynamic_string cmd_line;
65         split_command_line_params(get_command_line(), params);
66 #elif defined(VOGL_USE_LINUX_API)
67         pid_t proc_id = getpid();
68
69         char cmdline_filename[256];
70         sprintf(cmdline_filename, "/proc/%i/cmdline", proc_id);
71
72         FILE *pFile = vogl_fopen(cmdline_filename, "rb");
73         if (!pFile)
74         {
75             console::error("Failed reading command line parameters from file \"%s\"!\n", cmdline_filename);
76         }
77         else
78         {
79             dynamic_string tmp;
80
81             for (;;)
82             {
83                 int c = vogl_fgetc(pFile);
84                 if (c < 0)
85                     break;
86
87                 if (c)
88                     tmp.append_char(static_cast<char>(c));
89                 else
90                 {
91                     if (!tmp.get_len())
92                         break;
93
94                     params.push_back(tmp);
95                     tmp.truncate(0);
96                 }
97             }
98             vogl_fclose(pFile);
99         }
100 #else
101 #warning Unimplemented!
102 #endif
103
104         return params;
105     }
106
107     dynamic_string get_command_line()
108     {
109         dynamic_string cmd_line;
110
111 #ifdef VOGL_USE_WIN32_API
112         cmd_line.set(GetCommandLineA());
113 #elif defined(VOGL_USE_LINUX_API)
114         dynamic_string_array params(get_command_line_params());
115
116         for (uint i = 0; i < params.size(); i++)
117         {
118             dynamic_string tmp(params[i]);
119
120             // If the param is not already quoted, and it has any whitespace, then quote it. (The goal here is to ensure the split_command_line_params() method,
121             // which was unfortunately written for Windows where it's trivial to get the full unparsed cmd line as a string, doesn't split up this parameter.)
122             if ((tmp.front() != '\"') && (tmp.contains(' ') || tmp.contains('\t')))
123             {
124                 tmp = "\"" + tmp + "\"";
125             }
126
127             if (cmd_line.get_len())
128                 cmd_line += " ";
129
130             cmd_line += tmp;
131         }
132 #else
133 #warning Unimplemented!
134 #endif
135         return cmd_line;
136     }
137
138     dynamic_string get_command_line(int argc, char *argv[])
139     {
140         (void)argc, (void)argv;
141
142         dynamic_string cmd_line;
143
144 #ifdef VOGL_USE_WIN32_API
145         cmd_line.set(GetCommandLineA());
146 #else
147         cmd_line.clear();
148         for (int i = 0; i < argc; i++)
149         {
150             dynamic_string tmp(argv[i]);
151
152             // If the param is not already quoted, and it has any whitespace, then quote it.
153             if ((tmp.front() != '\"') && (tmp.contains(' ') || tmp.contains('\t')))
154             {
155                 tmp = "\"" + tmp + "\"";
156             }
157
158             if (cmd_line.get_len())
159                 cmd_line += " ";
160             cmd_line += tmp;
161         }
162 #endif
163         return cmd_line;
164     }
165
166     bool check_for_command_line_param(const char *pParam)
167     {
168 #ifdef VOGL_USE_WIN32_API
169         return (strstr(GetCommandLineA(), pParam) != NULL);
170 #elif defined(VOGL_USE_LINUX_API)
171         pid_t proc_id = getpid();
172
173         char cmdline_filename[256];
174         sprintf(cmdline_filename, "/proc/%i/cmdline", proc_id);
175
176         FILE *pFile = vogl_fopen(cmdline_filename, "rb");
177         if (!pFile)
178             return false;
179
180         vogl::vector<char> buf;
181
182         for (;;)
183         {
184             int c = vogl_fgetc(pFile);
185             if (c < 0)
186                 break;
187             buf.push_back(static_cast<char>(c));
188         }
189         vogl_fclose(pFile);
190
191         const char *pSrc = buf.get_ptr();
192         while (*pSrc)
193         {
194             if (!strcmp(pParam, pSrc))
195                 return true;
196             pSrc += strlen(pSrc) + 1;
197         }
198 #else
199 #warning Unimplemented!
200 #endif
201
202         return false;
203     }
204
205     bool split_command_line_params(const char *p, dynamic_string_array &params)
206     {
207         bool within_param = false;
208         bool within_quote = false;
209
210         uint ofs = 0;
211         dynamic_string str;
212
213         while (p[ofs])
214         {
215             const char c = p[ofs];
216
217             if (within_param)
218             {
219                 if (within_quote)
220                 {
221                     if (c == '"')
222                         within_quote = false;
223
224                     str.append_char(c);
225                 }
226                 else if ((c == ' ') || (c == '\t'))
227                 {
228                     if (!str.is_empty())
229                     {
230                         params.push_back(str);
231                         str.clear();
232                     }
233                     within_param = false;
234                 }
235                 else
236                 {
237                     if (c == '"')
238                         within_quote = true;
239
240                     str.append_char(c);
241                 }
242             }
243             else if ((c != ' ') && (c != '\t'))
244             {
245                 within_param = true;
246
247                 if (c == '"')
248                     within_quote = true;
249
250                 str.append_char(c);
251             }
252
253             ofs++;
254         }
255
256         if (within_quote)
257         {
258             console::error("Unmatched quote in command line \"%s\"\n", p);
259             return false;
260         }
261
262         if (!str.is_empty())
263             params.push_back(str);
264         return true;
265     }
266
267     void dump_command_line_info(uint n, const command_line_param_desc *pDesc, const char *prefix)
268     {
269         if (!prefix)
270             prefix = "";
271         for (uint i = 0; i < n; i++)
272         {
273             console::message("%s%s", prefix, pDesc[i].m_pName);
274             for (uint j = 0; j < pDesc[i].m_num_values; j++)
275                 console::message(" [value]");
276
277             if (pDesc[i].m_pDesc)
278                 console::printf(": %s", pDesc[i].m_pDesc);
279
280             console::printf("\n");
281         }
282     }
283
284     command_line_params::command_line_params()
285     {
286     }
287
288     void command_line_params::clear()
289     {
290         m_params.clear();
291
292         m_param_map.clear();
293     }
294
295     bool command_line_params::load_string_file(const char *pFilename, dynamic_string_array &strings)
296     {
297         cfile_stream in_stream;
298         if (!in_stream.open(pFilename, cDataStreamReadable | cDataStreamSeekable))
299         {
300             console::error("Unable to open file \"%s\" for reading!\n", pFilename);
301             return false;
302         }
303
304         dynamic_string ansi_str;
305
306         for (;;)
307         {
308             if (!in_stream.read_line(ansi_str))
309                 break;
310
311             ansi_str.trim();
312             if (ansi_str.is_empty())
313                 continue;
314
315             strings.push_back(dynamic_string(ansi_str.get_ptr()));
316         }
317
318         return true;
319     }
320
321     bool command_line_params::parse(const dynamic_string_array &params, uint total_param_descs, const command_line_param_desc *pParam_desc, const command_line_params::parse_config &config)
322     {
323         m_params = params;
324
325         command_line_param_desc desc;
326         desc.m_num_values = 0;
327         desc.m_support_listing_file = false;
328         desc.m_pName = "";
329         desc.m_pDesc = NULL;
330
331         uint arg_index = 0;
332         while (arg_index < params.size())
333         {
334             const uint cur_arg_index = arg_index;
335             const dynamic_string &src_param = params[arg_index++];
336
337             if (src_param.is_empty())
338                 continue;
339
340             bool is_param = false;
341             uint param_prefix_chars = 1;
342
343 #if VOGL_CMD_LINE_ALLOW_SLASH_PARAMS
344             is_param = (src_param[0] == '/');
345 #endif
346             if ((src_param[0] == '-') && ((config.m_single_minus_params) || (config.m_double_minus_params)))
347             {
348                 is_param = true;
349
350                 bool double_minus = (src_param[1] == '-');
351                 if (double_minus)
352                 {
353                     if (config.m_double_minus_params)
354                     {
355                         param_prefix_chars = 2;
356                     }
357                     else
358                     {
359                         if (config.m_ignore_unrecognized_params)
360                             continue;
361
362                         console::error("Unrecognized command line parameter: \"%s\"\n", src_param.get_ptr());
363                         return false;
364                     }
365                 }
366             }
367
368             if (is_param)
369             {
370                 if (src_param.get_len() < (param_prefix_chars + 1))
371                 {
372                     console::warning("Skipping invalid command line parameter: \"%s\"\n", src_param.get_ptr());
373                     continue;
374                 }
375
376                 dynamic_string key_str(src_param);
377
378                 key_str.right(param_prefix_chars);
379
380                 if (config.m_pParam_ignore_prefix)
381                 {
382                     if (key_str.begins_with(config.m_pParam_ignore_prefix, true))
383                         continue;
384                 }
385
386                 if (config.m_pParam_accept_prefix)
387                 {
388                     if (!key_str.begins_with(config.m_pParam_accept_prefix, true))
389                         continue;
390                 }
391
392                 int modifier = 0;
393                 char c = key_str[key_str.get_len() - 1];
394                 if (c == '+')
395                     modifier = 1;
396                 else if (c == '-')
397                     modifier = -1;
398
399                 if (modifier)
400                     key_str.left(key_str.get_len() - 1);
401
402                 if (total_param_descs)
403                 {
404                     uint param_index;
405                     for (param_index = 0; param_index < total_param_descs; param_index++)
406                         if (key_str == pParam_desc[param_index].m_pName)
407                             break;
408
409                     if (param_index == total_param_descs)
410                     {
411                         if (config.m_ignore_unrecognized_params)
412                             continue;
413
414                         console::error("Unrecognized command line parameter: \"%s\"\n", src_param.get_ptr());
415                         return false;
416                     }
417
418                     desc = pParam_desc[param_index];
419                 }
420
421                 const uint cMaxValues = 16;
422                 dynamic_string val_str[cMaxValues];
423                 uint num_val_strs = 0;
424                 if (desc.m_num_values)
425                 {
426                     VOGL_ASSERT(desc.m_num_values <= cMaxValues);
427
428                     if ((arg_index + desc.m_num_values) > params.size())
429                     {
430                         console::error("Expected %u value(s) after command line parameter: \"%s\"\n", desc.m_num_values, src_param.get_ptr());
431                         return false;
432                     }
433
434                     for (uint v = 0; v < desc.m_num_values; v++)
435                     {
436                         val_str[num_val_strs++] = params[arg_index++];
437                     }
438                 }
439
440                 dynamic_string_array strings;
441
442                 if ((desc.m_support_listing_file) && (val_str[0].get_len() >= 2) && (val_str[0][0] == '@'))
443                 {
444                     dynamic_string filename(val_str[0]);
445                     filename.right(1);
446                     filename.unquote();
447
448                     if (!load_string_file(filename.get_ptr(), strings))
449                     {
450                         console::error("Failed loading listing file \"%s\"!\n", filename.get_ptr());
451                         return false;
452                     }
453                 }
454                 else
455                 {
456                     for (uint v = 0; v < num_val_strs; v++)
457                     {
458                         val_str[v].unquote();
459                         strings.push_back(val_str[v]);
460                     }
461                 }
462
463                 param_value pv;
464                 pv.m_values.swap(strings);
465                 pv.m_split_param_index = cur_arg_index;
466                 pv.m_modifier = (int8)modifier;
467                 m_param_map.insert(std::make_pair(key_str, pv));
468             }
469             else if (!config.m_ignore_non_params)
470             {
471                 if ((config.m_fail_on_non_params) && (cur_arg_index))
472                 {
473                     console::error("Unrecognized command line argument: \"%s\"!\n", src_param.get_ptr());
474                     return false;
475                 }
476
477                 param_value pv;
478                 pv.m_values.push_back(src_param);
479                 pv.m_values.back().unquote();
480                 pv.m_split_param_index = cur_arg_index;
481                 m_param_map.insert(std::make_pair(g_empty_dynamic_string, pv));
482             }
483         }
484
485         return true;
486     }
487
488     bool command_line_params::parse(const char *pCmd_line, uint total_param_descs, const command_line_param_desc *pParam_desc, const command_line_params::parse_config &config)
489     {
490         dynamic_string_array p;
491         if (!split_command_line_params(pCmd_line, p))
492             return 0;
493
494         if (p.is_empty())
495             return 0;
496
497         if (config.m_skip_first_param)
498             p.erase(0U);
499
500         return parse(p, total_param_descs, pParam_desc, config);
501     }
502
503     bool command_line_params::is_split_param_an_option(uint split_param_array_index) const
504     {
505         VOGL_ASSERT(split_param_array_index < m_params.size());
506         if (split_param_array_index >= m_params.size())
507             return false;
508
509         const dynamic_string &w = m_params[split_param_array_index];
510         if (w.is_empty())
511             return false;
512
513 #if VOGL_CMD_LINE_ALLOW_SLASH_PARAMS
514         return (w.get_len() >= 2) && ((w[0] == '-') || (w[0] == '/'));
515 #else
516         return (w.get_len() >= 2) && (w[0] == '-');
517 #endif
518     }
519
520     bool command_line_params::find(const char *pKey, param_map_const_iterator &begin, param_map_const_iterator &end) const
521     {
522         dynamic_string key(pKey);
523         begin = m_param_map.lower_bound(key);
524         end = m_param_map.upper_bound(key);
525         return begin != end;
526     }
527
528     uint command_line_params::get_count(const char *pKey) const
529     {
530         param_map_const_iterator begin, end;
531         find(pKey, begin, end);
532
533         uint n = 0;
534
535         while (begin != end)
536         {
537             n++;
538             begin++;
539         }
540
541         return n;
542     }
543
544     command_line_params::param_map_const_iterator command_line_params::get_param(const char *pKey, uint key_index) const
545     {
546         param_map_const_iterator begin, end;
547         find(pKey, begin, end);
548
549         if (begin == end)
550             return m_param_map.end();
551
552         uint n = 0;
553
554         while ((begin != end) && (n != key_index))
555         {
556             n++;
557             begin++;
558         }
559
560         if (begin == end)
561             return m_param_map.end();
562
563         return begin;
564     }
565
566     bool command_line_params::has_value(const char *pKey, uint key_index) const
567     {
568         return get_num_values(pKey, key_index) != 0;
569     }
570
571     uint command_line_params::get_num_values(const char *pKey, uint key_index) const
572     {
573         param_map_const_iterator it = get_param(pKey, key_index);
574
575         if (it == end())
576             return 0;
577
578         return it->second.m_values.size();
579     }
580
581     bool command_line_params::get_value_as_bool(const char *pKey, uint key_index, bool def) const
582     {
583         param_map_const_iterator it = get_param(pKey, key_index);
584         if (it == end())
585             return def;
586
587         if (it->second.m_modifier)
588             return it->second.m_modifier > 0;
589         else
590             return true;
591     }
592
593     int command_line_params::get_value_as_int(const char *pKey, uint key_index, int def, int l, int h, uint value_index, bool *pSuccess) const
594     {
595         if (pSuccess)
596             *pSuccess = false;
597
598         param_map_const_iterator it = get_param(pKey, key_index);
599         if (it == end())
600             return def;
601         if (value_index >= it->second.m_values.size())
602         {
603             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
604             return def;
605         }
606
607         int val;
608         const char *p = it->second.m_values[value_index].get_ptr();
609         if (!string_ptr_to_int(p, val))
610         {
611             if (!pKey[0])
612                 vogl::console::warning("Non-integer value specified for parameter at index %u, using default value of %i\n", key_index, def);
613             else
614                 vogl::console::warning("Non-integer value specified for parameter \"%s\" at index %u, using default value of %i\n", pKey, key_index, def);
615             return def;
616         }
617
618         if (val < l)
619         {
620             vogl::console::warning("Value %i for parameter \"%s\" at index %u is out of range, clamping to %i\n", val, pKey, key_index, l);
621             val = l;
622         }
623         else if (val > h)
624         {
625             vogl::console::warning("Value %i for parameter \"%s\" at index %u is out of range, clamping to %i\n", val, pKey, key_index, h);
626             val = h;
627         }
628
629         if (pSuccess)
630             *pSuccess = true;
631
632         return val;
633     }
634
635     int64_t command_line_params::get_value_as_int64(const char *pKey, uint key_index, int64_t def, int64_t l, int64_t h, uint value_index, bool *pSuccess) const
636     {
637         if (pSuccess)
638             *pSuccess = false;
639
640         param_map_const_iterator it = get_param(pKey, key_index);
641         if (it == end())
642             return def;
643         if (value_index >= it->second.m_values.size())
644         {
645             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
646             return def;
647         }
648
649         int64_t val;
650         const char *p = it->second.m_values[value_index].get_ptr();
651         if (!string_ptr_to_int64(p, val))
652         {
653             if (!pKey[0])
654                 vogl::console::warning("Non-integer value specified for parameter at index %u, using default value of %" PRIi64 "\n", key_index, def);
655             else
656                 vogl::console::warning("Non-integer value specified for parameter \"%s\" at index %u, using default value of %" PRIi64 "\n", pKey, key_index, def);
657             return def;
658         }
659
660         if (val < l)
661         {
662             vogl::console::warning("Value %" PRIi64 " for parameter \"%s\" at index %u is out of range, clamping to %" PRIi64 "\n", val, pKey, key_index, l);
663             val = l;
664         }
665         else if (val > h)
666         {
667             vogl::console::warning("Value %" PRIi64 " for parameter \"%s\" at index %u is out of range, clamping to %" PRIi64 "\n", val, pKey, key_index, h);
668             val = h;
669         }
670
671         if (pSuccess)
672             *pSuccess = true;
673
674         return val;
675     }
676
677     uint command_line_params::get_value_as_uint(const char *pKey, uint key_index, uint def, uint l, uint h, uint value_index, bool *pSuccess) const
678     {
679         if (pSuccess)
680             *pSuccess = false;
681
682         param_map_const_iterator it = get_param(pKey, key_index);
683         if (it == end())
684             return def;
685         if (value_index >= it->second.m_values.size())
686         {
687             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
688             return def;
689         }
690
691         uint val;
692         const char *p = it->second.m_values[value_index].get_ptr();
693         if (!string_ptr_to_uint(p, val))
694         {
695             if (!pKey[0])
696                 vogl::console::warning("Non-integer value specified for parameter at index %u, using default value of %u\n", key_index, def);
697             else
698                 vogl::console::warning("Non-integer value specified for parameter \"%s\" at index %u, using default value of %u\n", pKey, key_index, def);
699             return def;
700         }
701
702         if (val < l)
703         {
704             vogl::console::warning("Value %u for parameter \"%s\" at index %u is out of range, clamping to %u\n", val, pKey, key_index, l);
705             val = l;
706         }
707         else if (val > h)
708         {
709             vogl::console::warning("Value %u for parameter \"%s\" at index %u is out of range, clamping to %u\n", val, pKey, key_index, h);
710             val = h;
711         }
712
713         if (pSuccess)
714             *pSuccess = true;
715
716         return val;
717     }
718
719     uint64_t command_line_params::get_value_as_uint64(const char *pKey, uint key_index, uint64_t def, uint64_t l, uint64_t h, uint value_index, bool *pSuccess) const
720     {
721         if (pSuccess)
722             *pSuccess = false;
723
724         param_map_const_iterator it = get_param(pKey, key_index);
725         if (it == end())
726             return def;
727         if (value_index >= it->second.m_values.size())
728         {
729             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
730             return def;
731         }
732
733         uint64_t val;
734         const char *p = it->second.m_values[value_index].get_ptr();
735         if (!string_ptr_to_uint64(p, val))
736         {
737             if (!pKey[0])
738                 vogl::console::warning("Non-integer value specified for parameter at index %u, using default value of %" PRIu64 "\n", key_index, def);
739             else
740                 vogl::console::warning("Non-integer value specified for parameter \"%s\" at index %u, using default value of %" PRIu64 "\n", pKey, key_index, def);
741             return def;
742         }
743
744         if (val < l)
745         {
746             vogl::console::warning("Value %" PRIu64 " for parameter \"%s\" at index %u is out of range, clamping to %" PRIu64 "\n", val, pKey, key_index, l);
747             val = l;
748         }
749         else if (val > h)
750         {
751             vogl::console::warning("Value %" PRIu64 " for parameter \"%s\" at index %u is out of range, clamping to %" PRIu64 "\n", val, pKey, key_index, h);
752             val = h;
753         }
754
755         if (pSuccess)
756             *pSuccess = true;
757
758         return val;
759     }
760
761     float command_line_params::get_value_as_float(const char *pKey, uint key_index, float def, float l, float h, uint value_index, bool *pSuccess) const
762     {
763         if (pSuccess)
764             *pSuccess = false;
765
766         param_map_const_iterator it = get_param(pKey, key_index);
767         if (it == end())
768             return def;
769         if (value_index >= it->second.m_values.size())
770         {
771             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
772             return def;
773         }
774
775         float val;
776         const char *p = it->second.m_values[value_index].get_ptr();
777         if (!string_ptr_to_float(p, val))
778         {
779             vogl::console::warning("Invalid value specified for float parameter \"%s\", using default value of %f\n", pKey, def);
780             return def;
781         }
782
783         // Let's assume +-cNearlyInfinite implies no clamping.
784         if ((l != -math::cNearlyInfinite) && (val < l))
785         {
786             vogl::console::warning("Value %f for parameter \"%s\" is out of range, clamping to %f\n", val, pKey, l);
787             val = l;
788         }
789         else if ((h != math::cNearlyInfinite) && (val > h))
790         {
791             vogl::console::warning("Value %f for parameter \"%s\" is out of range, clamping to %f\n", val, pKey, h);
792             val = h;
793         }
794
795         if (pSuccess)
796             *pSuccess = true;
797
798         return val;
799     }
800
801     bool command_line_params::get_value_as_string(dynamic_string &value, const char *pKey, uint key_index, const char *pDef, uint value_index) const
802     {
803         param_map_const_iterator it = get_param(pKey, key_index);
804         if (it == end())
805             return false;
806         if (value_index >= it->second.m_values.size())
807         {
808             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
809             value.set(pDef);
810             return false;
811         }
812
813         value = it->second.m_values[value_index];
814         return true;
815     }
816
817     dynamic_string command_line_params::get_value_as_string(const char *pKey, uint key_index, const char *pDef, uint value_index) const
818     {
819         param_map_const_iterator it = get_param(pKey, key_index);
820         if (it == end())
821             return dynamic_string(pDef);
822         if (value_index >= it->second.m_values.size())
823         {
824             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
825             return dynamic_string(pDef);
826         }
827
828         return it->second.m_values[value_index];
829     }
830
831     const dynamic_string &command_line_params::get_value_as_string_or_empty(const char *pKey, uint key_index, uint value_index) const
832     {
833         param_map_const_iterator it = get_param(pKey, key_index);
834         if (it == end())
835             return g_empty_dynamic_string;
836
837         if (value_index >= it->second.m_values.size())
838         {
839             vogl::console::debug("%s: Trying to retrieve value %u of command line parameter %s, but this parameter only has %u values\n", VOGL_METHOD_NAME, value_index, pKey, it->second.m_values.size());
840             return g_empty_dynamic_string;
841         }
842
843         return it->second.m_values[value_index];
844     }
845
846 } // namespace vogl