Skip to content

Commit b153475

Browse files
authored
add transform functions for integer in jerryx/arg (#1883)
JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang [email protected]
1 parent e4eecc2 commit b153475

File tree

6 files changed

+471
-62
lines changed

6 files changed

+471
-62
lines changed

docs/09.EXT-REFERENCE-ARG.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,42 @@ Enum that indicates whether an argument is optional or required.
122122
- [jerryx_arg_function](#jerryx_arg_function)
123123
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
124124
125+
## jerryx_arg_round_t
126+
127+
Enum that indicates the rounding policy which will be chosen to transform an integer.
128+
129+
- JERRYX_ARG_ROUND - use round() method.
130+
- JERRYX_ARG_FLOOR - use floor() method.
131+
- JERRYX_ARG_CEIL - use ceil() method.
132+
133+
**See also**
134+
135+
- [jerryx_arg_uint8](#jerryx_arg_uint8)
136+
- [jerryx_arg_uint16](#jerryx_arg_uint16)
137+
- [jerryx_arg_uint32](#jerryx_arg_uint32)
138+
- [jerryx_arg_int8](#jerryx_arg_int8)
139+
- [jerryx_arg_int16](#jerryx_arg_int16)
140+
- [jerryx_arg_int32](#jerryx_arg_int32)
141+
142+
143+
## jerryx_arg_clamp_t
144+
145+
Indicates the clamping policy which will be chosen to transform an integer.
146+
If the policy is NO_CLAMP, and the number is out of range,
147+
then the transformer will throw a range error.
148+
149+
- JERRYX_ARG_CLAMP - clamp the number when it is out of range
150+
- JERRYX_ARG_NO_CLAMP - throw a range error
151+
152+
**See also**
153+
154+
- [jerryx_arg_uint8](#jerryx_arg_uint8)
155+
- [jerryx_arg_uint16](#jerryx_arg_uint16)
156+
- [jerryx_arg_uint32](#jerryx_arg_uint32)
157+
- [jerryx_arg_int8](#jerryx_arg_int8)
158+
- [jerryx_arg_int16](#jerryx_arg_int16)
159+
- [jerryx_arg_int32](#jerryx_arg_int32)
160+
125161
# Main functions
126162
127163
## jerryx_arg_transform_this_and_args
@@ -270,6 +306,49 @@ jerryx_arg_transform_object_properties (const jerry_value_t obj_val,
270306
271307
# Helpers for commonly used validations
272308
309+
## jerryx_arg_uint8
310+
311+
## jerryx_arg_uint16
312+
313+
## jerryx_arg_uint32
314+
315+
## jerryx_arg_int8
316+
317+
## jerryx_arg_int16
318+
319+
## jerryx_arg_int32
320+
321+
**Summary**
322+
323+
All above jerryx_arg_[u]intX functions are used to create a validation/transformation step
324+
(`jerryx_arg_t`) that expects to consume one `number` JS argument
325+
and stores it into a C integer (uint8, int8, uint16, ...)
326+
327+
**Prototype**
328+
329+
Take jerryx_arg_int32 as an example
330+
331+
```c
332+
static inline jerryx_arg_t
333+
jerryx_arg_int32 (int32_t *dest,
334+
jerryx_arg_round_t round_flag,
335+
jerryx_arg_clamp_t clamp_flag,
336+
jerryx_arg_coerce_t coerce_flag,
337+
jerryx_arg_optional_t opt_flag);
338+
```
339+
340+
- return value - the created `jerryx_arg_t` instance.
341+
- `dest` - pointer to the `int32_t` where the result should be stored.
342+
- `round_flag` - the rounding policy.
343+
- `clamp_flag` - the clamping policy.
344+
- `coerce_flag` - whether type coercion is allowed.
345+
- `opt_flag` - whether the argument is optional.
346+
347+
**See also**
348+
349+
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
350+
351+
273352
## jerryx_arg_number
274353

275354
**Summary**

jerry-ext/arg/arg-transform-functions.c

Lines changed: 142 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* limitations under the License.
1414
*/
1515

16+
#include <math.h>
17+
1618
#include "jerryscript-ext/arg.h"
1719
#include "jerryscript.h"
1820

@@ -39,14 +41,15 @@ jerryx_arg_transform_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< ava
3941
} /* jerryx_arg_transform_optional */
4042

4143
/**
42-
* Tranform a JS argument to a double. Type coercion is not allowed.
44+
* The common part in transforming a JS argument to a number (double or certain int) type.
45+
* Type coercion is not allowed.
4346
*
4447
* @return jerry undefined: the transformer passes,
4548
* jerry error: the transformer fails.
4649
*/
47-
jerry_value_t
48-
jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
49-
const jerryx_arg_t *c_arg_p) /**< the native arg */
50+
static jerry_value_t
51+
jerryx_arg_transform_number_strict_common (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
52+
double *number_p) /**< [out] the number in JS arg */
5053
{
5154
jerry_value_t js_arg = jerryx_arg_js_iterator_pop (js_arg_iter_p);
5255

@@ -56,21 +59,21 @@ jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /**
5659
(jerry_char_t *) "It is not a number.");
5760
}
5861

59-
double *dest = c_arg_p->dest;
60-
*dest = jerry_get_number_value (js_arg);
62+
*number_p = jerry_get_number_value (js_arg);
6163

6264
return jerry_create_undefined ();
63-
} /* jerryx_arg_transform_number_strict */
65+
} /* jerryx_arg_transform_number_strict_common */
6466

6567
/**
66-
* Transform a JS argument to a double. Type coercion is allowed.
68+
* The common part in transforming a JS argument to a number (double or certain int) type.
69+
* Type coercion is allowed.
6770
*
6871
* @return jerry undefined: the transformer passes,
6972
* jerry error: the transformer fails.
7073
*/
71-
jerry_value_t
72-
jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
73-
const jerryx_arg_t *c_arg_p) /**< the native arg */
74+
static jerry_value_t
75+
jerryx_arg_transform_number_common (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
76+
double *number_p) /**< [out] the number in JS arg */
7477
{
7578
jerry_value_t js_arg = jerryx_arg_js_iterator_pop (js_arg_iter_p);
7679

@@ -84,13 +87,118 @@ jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< avail
8487
(jerry_char_t *) "It can not be converted to a number.");
8588
}
8689

87-
double *dest = c_arg_p->dest;
88-
*dest = jerry_get_number_value (to_number);
90+
*number_p = jerry_get_number_value (to_number);
8991
jerry_release_value (to_number);
9092

9193
return jerry_create_undefined ();
94+
} /* jerryx_arg_transform_number_common */
95+
96+
/**
97+
* Transform a JS argument to a double. Type coercion is not allowed.
98+
*
99+
* @return jerry undefined: the transformer passes,
100+
* jerry error: the transformer fails.
101+
*/
102+
jerry_value_t
103+
jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
104+
const jerryx_arg_t *c_arg_p) /**< the native arg */
105+
{
106+
return jerryx_arg_transform_number_strict_common (js_arg_iter_p, c_arg_p->dest);
107+
} /* jerryx_arg_transform_number_strict */
108+
109+
/**
110+
* Tranform a JS argument to a double. Type coercion is allowed.
111+
*
112+
* @return jerry undefined: the transformer passes,
113+
* jerry error: the transformer fails.
114+
*/
115+
jerry_value_t
116+
jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */
117+
const jerryx_arg_t *c_arg_p) /**< the native arg */
118+
{
119+
return jerryx_arg_transform_number_common (js_arg_iter_p, c_arg_p->dest);
92120
} /* jerryx_arg_transform_number */
93121

122+
/**
123+
* Helper function to process a double number before converting it
124+
* to an integer.
125+
*
126+
* @return jerry undefined: the transformer passes,
127+
* jerry error: the transformer fails.
128+
*/
129+
static jerry_value_t
130+
jerryx_arg_helper_process_double (double *d, /**< [in, out] the number to be processed */
131+
double min, /**< the min value for clamping */
132+
double max, /**< the max value for clamping */
133+
jerryx_arg_int_option_t option) /**< the converting policies */
134+
{
135+
if (option.clamp == JERRYX_ARG_NO_CLAMP)
136+
{
137+
if (*d > max || *d < min)
138+
{
139+
return jerry_create_error (JERRY_ERROR_TYPE,
140+
(jerry_char_t *) "The number is out of range.");
141+
}
142+
}
143+
else
144+
{
145+
*d = *d < min ? min : *d;
146+
*d = *d > max ? max : *d;
147+
}
148+
149+
if (option.round == JERRYX_ARG_ROUND)
150+
{
151+
*d = (*d >= 0.0) ? floor (*d + 0.5) : ceil (*d - 0.5);
152+
}
153+
else if (option.round == JERRYX_ARG_FLOOR)
154+
{
155+
*d = floor (*d);
156+
}
157+
else
158+
{
159+
*d = ceil (*d);
160+
}
161+
162+
return jerry_create_undefined ();
163+
} /* jerryx_arg_helper_process_double */
164+
165+
/**
166+
* Use the macro to define thr transform functions for int type.
167+
*/
168+
#define JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE(type, suffix, min, max) \
169+
jerry_value_t jerryx_arg_transform_ ## type ## suffix (jerryx_arg_js_iterator_t *js_arg_iter_p, \
170+
const jerryx_arg_t *c_arg_p) \
171+
{ \
172+
double tmp; \
173+
jerry_value_t rv = jerryx_arg_transform_number ## suffix ## _common (js_arg_iter_p, &tmp); \
174+
if (jerry_value_has_error_flag (rv)) \
175+
{ \
176+
return rv; \
177+
} \
178+
jerry_release_value (rv); \
179+
jerryx_arg_int_option_t *options_p = (jerryx_arg_int_option_t *) &c_arg_p->extra_info; \
180+
rv = jerryx_arg_helper_process_double (&tmp, min, max, *options_p); \
181+
if (jerry_value_has_error_flag (rv)) \
182+
{ \
183+
return rv; \
184+
} \
185+
*(type ## _t *) c_arg_p->dest = (type ## _t) tmp; \
186+
return rv; \
187+
}
188+
189+
#define JERRYX_ARG_TRANSFORM_FUNC_FOR_INT(type, min, max) \
190+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE (type, _strict, min, max) \
191+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE (type, , min, max)
192+
193+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (uint8, 0, UINT8_MAX)
194+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (int8, INT8_MIN, INT8_MAX)
195+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (uint16, 0, UINT16_MAX)
196+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (int16, INT16_MIN, INT16_MAX)
197+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (uint32, 0, UINT32_MAX)
198+
JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (int32, INT32_MIN, INT32_MAX)
199+
200+
#undef JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE
201+
#undef JERRYX_ARG_TRANSFORM_FUNC_FOR_INT
94202
/**
95203
* Tranform a JS argument to a boolean. Type coercion is not allowed.
96204
*
@@ -294,12 +402,12 @@ jerryx_arg_transform_object_props (jerryx_arg_js_iterator_t *js_arg_iter_p, /**<
294402
* Define transformer for optional argument.
295403
*/
296404
#define JERRYX_ARG_TRANSFORM_OPTIONAL(type) \
297-
jerry_value_t \
298-
jerryx_arg_transform_ ## type ## _optional (jerryx_arg_js_iterator_t *js_arg_iter_p, \
299-
const jerryx_arg_t *c_arg_p) \
300-
{ \
301-
return jerryx_arg_transform_optional (js_arg_iter_p, c_arg_p, jerryx_arg_transform_ ## type); \
302-
}
405+
jerry_value_t \
406+
jerryx_arg_transform_ ## type ## _optional (jerryx_arg_js_iterator_t *js_arg_iter_p, \
407+
const jerryx_arg_t *c_arg_p) \
408+
{ \
409+
return jerryx_arg_transform_optional (js_arg_iter_p, c_arg_p, jerryx_arg_transform_ ## type); \
410+
}
303411

304412
JERRYX_ARG_TRANSFORM_OPTIONAL (number)
305413
JERRYX_ARG_TRANSFORM_OPTIONAL (number_strict)
@@ -311,6 +419,21 @@ JERRYX_ARG_TRANSFORM_OPTIONAL (function)
311419
JERRYX_ARG_TRANSFORM_OPTIONAL (native_pointer)
312420
JERRYX_ARG_TRANSFORM_OPTIONAL (object_props)
313421

422+
JERRYX_ARG_TRANSFORM_OPTIONAL (uint8)
423+
JERRYX_ARG_TRANSFORM_OPTIONAL (uint16)
424+
JERRYX_ARG_TRANSFORM_OPTIONAL (uint32)
425+
JERRYX_ARG_TRANSFORM_OPTIONAL (int8)
426+
JERRYX_ARG_TRANSFORM_OPTIONAL (int16)
427+
JERRYX_ARG_TRANSFORM_OPTIONAL (int32)
428+
JERRYX_ARG_TRANSFORM_OPTIONAL (int8_strict)
429+
JERRYX_ARG_TRANSFORM_OPTIONAL (int16_strict)
430+
JERRYX_ARG_TRANSFORM_OPTIONAL (int32_strict)
431+
JERRYX_ARG_TRANSFORM_OPTIONAL (uint8_strict)
432+
JERRYX_ARG_TRANSFORM_OPTIONAL (uint16_strict)
433+
JERRYX_ARG_TRANSFORM_OPTIONAL (uint32_strict)
434+
435+
#undef JERRYX_ARG_TRANSFORM_OPTIONAL
436+
314437
/**
315438
* Ignore the JS argument.
316439
*

jerry-ext/arg/arg.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717
#include "jerryscript-ext/arg.h"
1818
#include "jerryscript.h"
1919

20+
21+
#define JERRYX_STATIC_ASSERT(x, msg) \
22+
enum { static_assertion_failed_ ## msg = 1 / (!!(x)) }
23+
24+
JERRYX_STATIC_ASSERT (sizeof (jerryx_arg_int_option_t) <= sizeof (((jerryx_arg_t *) 0)->extra_info),
25+
jerryx_arg_number_options_t_must_fit_into_extra_info);
26+
27+
#undef JERRYX_STATIC_ASSERT
28+
2029
/**
2130
* Validate the JS arguments and assign them to the native arguments.
2231
*

jerry-ext/include/jerryscript-ext/arg.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,52 @@ typedef enum
106106
JERRYX_ARG_REQUIRED
107107
} jerryx_arg_optional_t;
108108

109+
/**
110+
* Indicates the rounding policy which will be chosen to transform an integer.
111+
*/
112+
typedef enum
113+
{
114+
JERRYX_ARG_ROUND, /**< round */
115+
JERRYX_ARG_FLOOR, /**< floor */
116+
JERRYX_ARG_CEIL /**< ceil */
117+
} jerryx_arg_round_t;
118+
119+
/**
120+
* Indicates the clamping policy which will be chosen to transform an integer.
121+
* If the policy is NO_CLAMP, and the number is out of range,
122+
* then the transformer will throw a range error.
123+
*/
124+
typedef enum
125+
{
126+
JERRYX_ARG_CLAMP,/**< clamp the number when it is out of range */
127+
JERRYX_ARG_NO_CLAMP /**< throw a range error */
128+
} jerryx_arg_clamp_t;
129+
109130
/* Inline functions for initializing jerryx_arg_t */
131+
132+
#define JERRYX_ARG_INTEGER(type) \
133+
static inline jerryx_arg_t \
134+
jerryx_arg_ ## type (type ## _t *dest, \
135+
jerryx_arg_round_t round_flag, \
136+
jerryx_arg_clamp_t clamp_flag, \
137+
jerryx_arg_coerce_t coerce_flag, \
138+
jerryx_arg_optional_t opt_flag);
139+
140+
JERRYX_ARG_INTEGER (uint8)
141+
JERRYX_ARG_INTEGER (int8)
142+
JERRYX_ARG_INTEGER (uint16)
143+
JERRYX_ARG_INTEGER (int16)
144+
JERRYX_ARG_INTEGER (uint32)
145+
JERRYX_ARG_INTEGER (int32)
146+
147+
#undef JERRYX_ARG_INTEGER
148+
110149
static inline jerryx_arg_t
111-
jerryx_arg_number (double *dest, jerryx_arg_coerce_t conv_flag, jerryx_arg_optional_t opt_flag);
150+
jerryx_arg_number (double *dest, jerryx_arg_coerce_t coerce_flag, jerryx_arg_optional_t opt_flag);
112151
static inline jerryx_arg_t
113-
jerryx_arg_boolean (bool *dest, jerryx_arg_coerce_t conv_flag, jerryx_arg_optional_t opt_flag);
152+
jerryx_arg_boolean (bool *dest, jerryx_arg_coerce_t coerce_flag, jerryx_arg_optional_t opt_flag);
114153
static inline jerryx_arg_t
115-
jerryx_arg_string (char *dest, uint32_t size, jerryx_arg_coerce_t conv_flag, jerryx_arg_optional_t opt_flag);
154+
jerryx_arg_string (char *dest, uint32_t size, jerryx_arg_coerce_t coerce_flag, jerryx_arg_optional_t opt_flag);
116155
static inline jerryx_arg_t
117156
jerryx_arg_function (jerry_value_t *dest, jerryx_arg_optional_t opt_flag);
118157
static inline jerryx_arg_t

0 commit comments

Comments
 (0)