*b = temp;
}
+void
+ds_put_hex(struct ds *ds, const void *buf_, size_t size)
+{
+ const uint8_t *buf = buf_;
+ bool printed = false;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ uint8_t val = buf[i];
+ if (val || printed) {
+ if (!printed) {
+ ds_put_format(ds, "0x%"PRIx8, val);
+ } else {
+ ds_put_format(ds, "%02"PRIx8, val);
+ }
+ printed = true;
+ }
+ }
+ if (!printed) {
+ ds_put_char(ds, '0');
+ }
+}
+
/* Writes the 'size' bytes in 'buf' to 'string' as hex bytes arranged 16 per
* line. Numeric offsets are also included, starting at 'ofs' for the first
* byte in 'buf'. If 'ascii' is true then the corresponding ASCII characters
void ds_put_format_valist(struct ds *, const char *, va_list)
OVS_PRINTF_FORMAT(2, 0);
void ds_put_printable(struct ds *, const char *, size_t);
+void ds_put_hex(struct ds *ds, const void *buf, size_t size);
void ds_put_hex_dump(struct ds *ds, const void *buf_, size_t size,
uintptr_t ofs, bool ascii);
int ds_get_line(struct ds *, FILE *);
learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
{
const char *full_s = s;
- const char *arrow = strstr(s, "->");
struct mf_subfield dst;
union mf_subvalue imm;
char *error;
+ int err;
- memset(&imm, 0, sizeof imm);
- if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && arrow) {
- const char *in = arrow - 1;
- uint8_t *out = imm.u8 + sizeof imm.u8 - 1;
- int n = arrow - (s + 2);
- int i;
-
- for (i = 0; i < n; i++) {
- int hexit = hexit_value(in[-i]);
- if (hexit < 0) {
- return xasprintf("%s: bad hex digit in value", full_s);
- }
- out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit;
- }
- s = arrow;
- } else {
- ovs_be64 *last_be64 = &imm.be64[ARRAY_SIZE(imm.be64) - 1];
- *last_be64 = htonll(strtoull(s, (char **) &s, 0));
+ err = parse_int_string(s, imm.u8, sizeof imm.u8, (char **) &s);
+ if (err) {
+ return xasprintf("%s: bad hex digit in value", full_s);
}
if (strncmp(s, "->", 2)) {
void
mf_format_subvalue(const union mf_subvalue *subvalue, struct ds *s)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(subvalue->u8); i++) {
- if (subvalue->u8[i]) {
- ds_put_format(s, "0x%"PRIx8, subvalue->u8[i]);
- for (i++; i < ARRAY_SIZE(subvalue->u8); i++) {
- ds_put_format(s, "%02"PRIx8, subvalue->u8[i]);
- }
- return;
- }
- }
- ds_put_char(s, '0');
+ ds_put_hex(s, subvalue->u8, sizeof subvalue->u8);
}
void
return value;
}
+/* Parses the string in 's' as an integer in either hex or decimal format and
+ * puts the result right justified in the array 'valuep' that is 'field_width'
+ * big. If the string is in hex format, the value may be arbitrarily large;
+ * integers are limited to 64-bit values. (The rationale is that decimal is
+ * likely to represent a number and 64 bits is a reasonable maximum whereas
+ * hex could either be a number or a byte string.)
+ *
+ * On return 'tail' points to the first character in the string that was
+ * not parsed as part of the value. ERANGE is returned if the value is too
+ * large to fit in the given field. */
+int
+parse_int_string(const char *s, uint8_t *valuep, int field_width, char **tail)
+{
+ unsigned long long int integer;
+ int i;
+
+ if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2)) {
+ uint8_t *hexit_str;
+ int len = 0;
+ int val_idx;
+ int err = 0;
+
+ s += 2;
+ hexit_str = xmalloc(field_width * 2);
+
+ for (;;) {
+ uint8_t hexit;
+ bool ok;
+
+ s += strspn(s, " \t\r\n");
+ hexit = hexits_value(s, 1, &ok);
+ if (!ok) {
+ *tail = CONST_CAST(char *, s);
+ break;
+ }
+
+ if (hexit != 0 || len) {
+ if (DIV_ROUND_UP(len + 1, 2) > field_width) {
+ err = ERANGE;
+ goto free;
+ }
+
+ hexit_str[len] = hexit;
+ len++;
+ }
+ s++;
+ }
+
+ val_idx = field_width;
+ for (i = len - 1; i >= 0; i -= 2) {
+ val_idx--;
+ valuep[val_idx] = hexit_str[i];
+ if (i > 0) {
+ valuep[val_idx] += hexit_str[i - 1] << 4;
+ }
+ }
+
+ memset(valuep, 0, val_idx);
+
+free:
+ free(hexit_str);
+ return err;
+ }
+
+ errno = 0;
+ integer = strtoull(s, tail, 0);
+ if (errno) {
+ return errno;
+ }
+
+ for (i = field_width - 1; i >= 0; i--) {
+ valuep[i] = integer;
+ integer >>= 8;
+ }
+ if (integer) {
+ return ERANGE;
+ }
+
+ return 0;
+}
+
/* Returns the current working directory as a malloc()'d string, or a null
* pointer if the current working directory cannot be determined. */
char *
int hexit_value(int c);
uintmax_t hexits_value(const char *s, size_t n, bool *ok);
+int parse_int_string(const char *s, uint8_t *valuep, int field_width,
+ char **tail);
+
const char *english_list_delimiter(size_t index, size_t total);
char *get_cwd(void);