1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5 
6 #ifndef TOOLS_ARGS_H_
7 #define TOOLS_ARGS_H_
8 
9 // Helpers for parsing command line arguments. No include guard needed.
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <string>
15 #include <vector>
16 
17 #include "lib/extras/color_hints.h"
18 #include "lib/jxl/base/override.h"
19 #include "lib/jxl/base/status.h"
20 #include "lib/jxl/codec_in_out.h"  // DecoderHints
21 #include "lib/jxl/gaborish.h"
22 #include "lib/jxl/modular/options.h"
23 
24 namespace jpegxl {
25 namespace tools {
26 
ParseOverride(const char * arg,jxl::Override * out)27 static inline bool ParseOverride(const char* arg, jxl::Override* out) {
28   const std::string s_arg(arg);
29   if (s_arg == "1") {
30     *out = jxl::Override::kOn;
31     return true;
32   }
33   if (s_arg == "0") {
34     *out = jxl::Override::kOff;
35     return true;
36   }
37   fprintf(stderr, "Invalid flag, %s must be 0 or 1\n", arg);
38   return JXL_FAILURE("Args");
39 }
40 
ParseUnsigned(const char * arg,size_t * out)41 static inline bool ParseUnsigned(const char* arg, size_t* out) {
42   char* end;
43   *out = static_cast<size_t>(strtoull(arg, &end, 0));
44   if (end[0] != '\0') {
45     fprintf(stderr, "Unable to interpret as unsigned integer: %s.\n", arg);
46     return JXL_FAILURE("Args");
47   }
48   return true;
49 }
50 
ParseUint32(const char * arg,uint32_t * out)51 static inline bool ParseUint32(const char* arg, uint32_t* out) {
52   size_t value = 0;
53   bool ret = ParseUnsigned(arg, &value);
54   if (ret) *out = value;
55   return ret;
56 }
57 
ParseSigned(const char * arg,int * out)58 static inline bool ParseSigned(const char* arg, int* out) {
59   char* end;
60   *out = static_cast<int>(strtol(arg, &end, 0));
61   if (end[0] != '\0') {
62     fprintf(stderr, "Unable to interpret as signed integer: %s.\n", arg);
63     return JXL_FAILURE("Args");
64   }
65   return true;
66 }
67 
ParseFloat(const char * arg,float * out)68 static inline bool ParseFloat(const char* arg, float* out) {
69   char* end;
70   *out = static_cast<float>(strtod(arg, &end));
71   if (end[0] != '\0') {
72     fprintf(stderr, "Unable to interpret as float: %s.\n", arg);
73     return JXL_FAILURE("Args");
74   }
75   return true;
76 }
77 
ParseFloatPair(const char * arg,std::pair<float,float> * out)78 static inline bool ParseFloatPair(const char* arg,
79                                   std::pair<float, float>* out) {
80   int parsed = sscanf(arg, "%f,%f", &out->first, &out->second);
81   if (parsed == 1) {
82     out->second = out->first;
83   } else if (parsed != 2) {
84     fprintf(stderr,
85             "Unable to interpret as float pair separated by a comma: %s.\n",
86             arg);
87     return JXL_FAILURE("Args");
88   }
89   return true;
90 }
91 
ParseDouble(const char * arg,double * out)92 static inline bool ParseDouble(const char* arg, double* out) {
93   char* end;
94   *out = static_cast<double>(strtod(arg, &end));
95   if (end[0] != '\0') {
96     fprintf(stderr, "Unable to interpret as double: %s.\n", arg);
97     return JXL_FAILURE("Args");
98   }
99   return true;
100 }
101 
ParseAndAppendKeyValue(const char * arg,jxl::ColorHints * out)102 static inline bool ParseAndAppendKeyValue(const char* arg,
103                                           jxl::ColorHints* out) {
104   const char* eq = strchr(arg, '=');
105   if (!eq) {
106     fprintf(stderr, "Expected argument as 'key=value' but received '%s'\n",
107             arg);
108     return false;
109   }
110   std::string key(arg, eq);
111   out->Add(key, std::string(eq + 1));
112   return true;
113 }
114 
ParsePredictor(const char * arg,jxl::Predictor * out)115 static inline bool ParsePredictor(const char* arg, jxl::Predictor* out) {
116   char* end;
117   size_t p = static_cast<size_t>(strtoull(arg, &end, 0));
118   if (end[0] != '\0') {
119     fprintf(stderr, "Invalid predictor: %s.\n", arg);
120     return JXL_FAILURE("Args");
121   }
122   if (p >= jxl::kNumModularPredictors) {
123     fprintf(stderr, "Invalid predictor value %zu, must be less than %zu.\n", p,
124             jxl::kNumModularPredictors);
125     return JXL_FAILURE("Args");
126   }
127   *out = static_cast<jxl::Predictor>(p);
128   return true;
129 }
130 
ParseString(const char * arg,std::string * out)131 static inline bool ParseString(const char* arg, std::string* out) {
132   out->assign(arg);
133   return true;
134 }
135 
ParseCString(const char * arg,const char ** out)136 static inline bool ParseCString(const char* arg, const char** out) {
137   *out = arg;
138   return true;
139 }
140 
SetBooleanTrue(bool * out)141 static inline bool SetBooleanTrue(bool* out) {
142   *out = true;
143   return true;
144 }
145 
SetBooleanFalse(bool * out)146 static inline bool SetBooleanFalse(bool* out) {
147   *out = false;
148   return true;
149 }
150 
IncrementUnsigned(size_t * out)151 static inline bool IncrementUnsigned(size_t* out) {
152   (*out)++;
153   return true;
154 }
155 
156 }  // namespace tools
157 }  // namespace jpegxl
158 
159 #endif  // TOOLS_ARGS_H_
160