blob: c3959407296bb2c5d9cf5de99db8261c9faaf757 [file] [log] [blame]
// Copyright 2019 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "iree/base/bitfield.h"
#include <stdlib.h>
#include <string.h>
static bool iree_bitfield_lookup_mapping(
iree_string_view_t value, iree_host_size_t mapping_count,
const iree_bitfield_string_mapping_t* mappings, uint32_t* out_bits) {
*out_bits = 0;
for (iree_host_size_t mapping_index = 0; mapping_index < mapping_count;
++mapping_index) {
const iree_bitfield_string_mapping_t mapping = mappings[mapping_index];
if (iree_string_view_equal_case(mapping.string, value)) {
*out_bits = mapping.bits;
return true;
}
}
return false;
}
static inline bool iree_isdigit(char c) { return (unsigned)c - '0' < 10; }
IREE_API_EXPORT iree_status_t iree_bitfield_parse(
iree_string_view_t value, iree_host_size_t mapping_count,
const iree_bitfield_string_mapping_t* mappings, uint32_t* out_value) {
uint32_t bits_value = 0;
while (!iree_string_view_is_empty(value)) {
// Slice off the next part (or the tail).
iree_string_view_t part = iree_string_view_empty();
iree_string_view_split(value, '|', &part, &value);
part = iree_string_view_trim(part);
if (iree_string_view_is_empty(part)) continue;
// Scan the mapping table and match case-insensitive.
uint32_t mapping_bits = 0;
if (iree_bitfield_lookup_mapping(part, mapping_count, mappings,
&mapping_bits)) {
bits_value |= mapping_bits;
continue;
}
// If it starts with a number we try to parse it like one.
if (iree_isdigit(part.data[0])) {
uint32_t int_bits = 0;
if (iree_string_view_atoi_uint32(part, &int_bits)) {
bits_value |= int_bits;
continue;
}
}
// Unknown bitfield value.
return iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
"unrecognized bitfield member '%.*s'",
(int)part.size, part.data);
}
*out_value = bits_value;
return iree_ok_status();
}
IREE_API_EXPORT iree_status_t
iree_bitfield_format(uint32_t value, iree_host_size_t mapping_count,
const iree_bitfield_string_mapping_t* mappings,
iree_string_builder_t* string_builder) {
uint32_t remaining_bits = value;
int i = 0;
for (iree_host_size_t mapping_index = 0; mapping_index < mapping_count;
++mapping_index) {
const iree_bitfield_string_mapping_t mapping = mappings[mapping_index];
if ((remaining_bits & mapping.bits) == mapping.bits) {
if (i > 0) {
IREE_RETURN_IF_ERROR(
iree_string_builder_append_string(string_builder, IREE_SV("|")));
}
IREE_RETURN_IF_ERROR(
iree_string_builder_append_string(string_builder, mapping.string));
remaining_bits &= ~mapping.bits;
++i;
}
}
if (remaining_bits != 0u) {
if (i > 0) {
IREE_RETURN_IF_ERROR(
iree_string_builder_append_string(string_builder, IREE_SV("|")));
}
IREE_RETURN_IF_ERROR(iree_string_builder_append_format(
string_builder, "%Xh", remaining_bits));
}
return iree_ok_status();
}
IREE_API_EXPORT iree_string_view_t
iree_bitfield_format_inline(uint32_t value, iree_host_size_t mapping_count,
const iree_bitfield_string_mapping_t* mappings,
iree_bitfield_string_temp_t* out_temp) {
iree_string_builder_t string_builder;
iree_string_builder_initialize_with_storage(
out_temp->buffer, IREE_ARRAYSIZE(out_temp->buffer), &string_builder);
iree_status_t status =
iree_bitfield_format(value, mapping_count, mappings, &string_builder);
if (iree_status_is_ok(status)) {
return iree_string_builder_view(&string_builder);
}
iree_status_ignore(status);
return IREE_SV("(error)");
}