mirror of
https://github.com/Telecominfraproject/oopt-tai.git
synced 2026-01-27 02:21:53 +00:00
meta: initial TAI metadata implementation
Signed-off-by: Wataru Ishida <ishida@nel-america.com>
This commit is contained in:
committed by
Wataru Ishida
parent
85af48f174
commit
efadaf9199
3
meta/.gitignore
vendored
Normal file
3
meta/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.so
|
||||
taimetadata.c
|
||||
taimetadata.h
|
||||
5
meta/Dockerfile
Normal file
5
meta/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -qy wget python3 python3-pip libclang1-6.0
|
||||
RUN pip3 install clang jinja2
|
||||
20
meta/Makefile
Normal file
20
meta/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
.PHONY: test
|
||||
|
||||
all: taimetadata.c taimetadata.h taiserialize.c taimetadatautils.c
|
||||
gcc -shared -fPIC -I ../inc taiserialize.c taimetadatautils.c taimetadata.c -o libmetatai.so
|
||||
|
||||
taimetadata.c taimetadata.h: main.py
|
||||
python3 main.py ../inc/tai.h
|
||||
|
||||
docker-image:
|
||||
docker build -t taimeta-builder .
|
||||
|
||||
docker:
|
||||
cd ../; docker run -v `pwd`:/data -w /data -u `id -u`:`id -g` taimeta-builder make -C meta
|
||||
|
||||
test:
|
||||
make -C test
|
||||
LD_LIBRARY_PATH=. ./test/test
|
||||
|
||||
clean:
|
||||
rm libmetatai.so taimetadata.c taimetadata.h
|
||||
38
meta/README.md
Normal file
38
meta/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
Metadata for TAI
|
||||
================
|
||||
|
||||
Metadata for TAI is a set of auto generated (based on TAI headers) data
|
||||
and functions which allow TAI attributes serialization and more.
|
||||
|
||||
Metadata is generated as ANSI C source and header.
|
||||
|
||||
Parser also forces headers to be well formated when adding new code.
|
||||
|
||||
As same as TAI itself, TAI metadata is based upon and quite common to the
|
||||
SAI metadata.
|
||||
|
||||
|
||||
## How to build
|
||||
|
||||
### native build
|
||||
|
||||
#### prerequisite
|
||||
|
||||
- gcc
|
||||
- python3
|
||||
- libclang6.0
|
||||
|
||||
```sh
|
||||
$ make
|
||||
```
|
||||
|
||||
### Docker build
|
||||
|
||||
#### prerequisite
|
||||
|
||||
- docker
|
||||
|
||||
```sh
|
||||
$ make docker-image
|
||||
$ make docker
|
||||
```
|
||||
463
meta/main.py
Normal file
463
meta/main.py
Normal file
@@ -0,0 +1,463 @@
|
||||
#
|
||||
# Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
|
||||
import clang.cindex
|
||||
from clang.cindex import Index
|
||||
from clang.cindex import Config
|
||||
from optparse import OptionParser
|
||||
from enum import Enum
|
||||
from jinja2 import Environment
|
||||
|
||||
|
||||
class TAIAttributeFlag(Enum):
|
||||
READ_ONLY = 0
|
||||
IS_FLAG = 1
|
||||
CREATE_ONLY = 2
|
||||
MANDATORY_ON_CREATE = 3
|
||||
|
||||
|
||||
class TAIEnum(object):
|
||||
def __init__(self, name_node, value_nodes):
|
||||
self.name_node = name_node
|
||||
value_nodes.sort(key = lambda l : l.enum_value)
|
||||
self.value_nodes = value_nodes
|
||||
# displayname starts with '_'. remove it
|
||||
self.typename = self.name_node.displayname[1:]
|
||||
|
||||
def value_names(self):
|
||||
return [v.displayname for v in self.value_nodes if not v.displayname.endswith('_START') and not v.displayname.endswith('_END')]
|
||||
|
||||
|
||||
class TAIAttribute(object):
|
||||
def __init__(self, node, taiobject):
|
||||
self.node = node
|
||||
self.id = node.enum_value
|
||||
self.name = node.displayname
|
||||
self.taiobject = taiobject
|
||||
self.object_type = taiobject.object_type
|
||||
self.object_name = taiobject.name
|
||||
|
||||
rm = ' /*'
|
||||
cmt = [l.strip(rm).split(' ') for l in node.raw_comment.split('\n') if l.strip(rm).startswith('@')] # this omits long description from the comment
|
||||
s = { l[0][1:]: ' '.join(l[1:]) for l in cmt }
|
||||
self.cmt = s
|
||||
flags = self.cmt.get('flags', '').split('|')
|
||||
if flags[0] != '':
|
||||
self.flags = set(TAIAttributeFlag[e.strip()] for e in flags)
|
||||
else:
|
||||
self.flags = None
|
||||
t = self.cmt['type']
|
||||
ts = [v.strip('#') for v in t.split(' ')]
|
||||
self.enum_type = None
|
||||
if len(ts) == 1:
|
||||
self.type = ts[0]
|
||||
elif len(ts) == 2 and ts[0] == 'tai_s32_list_t':
|
||||
self.type = ts[0]
|
||||
self.enum_type = ts[1]
|
||||
else:
|
||||
raise Exception("unsupported type format: {}".format(t))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return '{}[{}:{}]'.format(self.name, self.type, self.flags)
|
||||
|
||||
|
||||
class TAIObject(object):
|
||||
OBJECT_MAP = {
|
||||
'module' : 'TAI_OBJECT_TYPE_MODULE',
|
||||
'host_interface' : 'TAI_OBJECT_TYPE_HOSTIF',
|
||||
'network_interface': 'TAI_OBJECT_TYPE_NETWORKIF',
|
||||
}
|
||||
|
||||
def __init__(self, name, header):
|
||||
self.name = name
|
||||
index = Index.create()
|
||||
tu = index.parse(header)
|
||||
self.tu = tu
|
||||
self.object_type = self.OBJECT_MAP.get(name, None)
|
||||
|
||||
self.enum_map = {}
|
||||
|
||||
m = {n.displayname:n for n in self.kinds('ENUM_DECL')}
|
||||
n = {n.displayname:n for n in self.kinds('ENUM_CONSTANT_DECL')}
|
||||
|
||||
for k, v in m.items():
|
||||
prefix = k[1:-2].upper()
|
||||
l = [vv for vv in n.values() if vv.displayname.startswith(prefix)]
|
||||
e = TAIEnum(v, l)
|
||||
self.enum_map[e.typename] = e
|
||||
|
||||
v = self.get_name('_tai_attribute_value_t')
|
||||
m = {}
|
||||
for f in v.get_children():
|
||||
# bool needs special handling since its type.spelling appear as 'int'
|
||||
key = 'bool' if f.displayname == 'booldata' else f.type.spelling
|
||||
m[key] = f.displayname
|
||||
|
||||
enums = set()
|
||||
|
||||
a = self.get_enum('tai_{}_attr_t'.format(self.name))
|
||||
attrs = [ TAIAttribute(e, self) for e in a.value_nodes if not e.displayname.endswith('_START') and not e.displayname.endswith('_END') ]
|
||||
|
||||
for attr in attrs:
|
||||
field = m.get(attr.type, None)
|
||||
if field:
|
||||
if getattr(attr, 'enum_type', None):
|
||||
enum = self.get_enum(attr.enum_type)
|
||||
if not enum:
|
||||
raise Exception("{} not found".format(attr.enum_type))
|
||||
enums.add(attr.enum_type)
|
||||
attr.value_field = field
|
||||
else:
|
||||
enum = self.get_enum(attr.type)
|
||||
enums.add(attr.type)
|
||||
if not enum:
|
||||
raise Exception("{} not found".format(attr.type))
|
||||
attr.value_field = 's32'
|
||||
attr.enum_type = attr.type
|
||||
|
||||
self.enum_names = enums
|
||||
self.attrs = attrs
|
||||
|
||||
def kinds(self, kind):
|
||||
node = self.tu.cursor
|
||||
out = []
|
||||
self.get_kinds(node, kind, out)
|
||||
return out
|
||||
|
||||
def get_name(self, name):
|
||||
node = self.tu.cursor
|
||||
return self._get_name(node, name)
|
||||
|
||||
def _get_name(self, node, name):
|
||||
if node.displayname == name:
|
||||
return node
|
||||
for child in node.get_children():
|
||||
n = self._get_name(child, name)
|
||||
if n:
|
||||
return n
|
||||
return None
|
||||
|
||||
def get_kinds(self, node, kind, out=[]):
|
||||
if node.kind.name == kind:
|
||||
out.append(node)
|
||||
return
|
||||
for child in node.get_children():
|
||||
self.get_kinds(child, kind, out)
|
||||
|
||||
def get_enum(self, name):
|
||||
return self.enum_map.get(name, None)
|
||||
|
||||
def get_enums(self):
|
||||
return [self.enum_map[n] for n in self.enum_names]
|
||||
|
||||
def get_attributes(self):
|
||||
return self.attrs
|
||||
|
||||
|
||||
class Generator(object):
|
||||
HEADER_TEMPLATE = ''
|
||||
|
||||
def __init__(self, env=Environment()):
|
||||
self.env = env
|
||||
|
||||
def implementation(self):
|
||||
if not getattr(self, 'env', None):
|
||||
self.env = Environment()
|
||||
return self.env.from_string(self.IMPL_TEMPLATE).render(self.data)
|
||||
|
||||
def header(self):
|
||||
if not getattr(self, 'env', None):
|
||||
self.env = Environment()
|
||||
return self.env.from_string(self.HEADER_TEMPLATE).render(self.data)
|
||||
|
||||
|
||||
class ObjectMetadataGenerator(Generator):
|
||||
HEADER_TEMPLATE = '''
|
||||
extern const tai_object_type_info_t tai_metadata_object_type_info_{{ name }};
|
||||
'''
|
||||
|
||||
IMPL_TEMPLATE = '''
|
||||
const tai_attr_metadata_t* const tai_metadata_object_type_tai_{{ name }}_attr_t[] = {
|
||||
{% for a in attrs -%}
|
||||
&tai_metadata_attr_{{ a }},
|
||||
{% endfor -%}
|
||||
NULL
|
||||
};
|
||||
|
||||
const tai_object_type_info_t tai_metadata_object_type_info_{{ name }} = {
|
||||
.objecttype = {{ object_type }},
|
||||
.objecttypename = "{{ object_type }}",
|
||||
.enummetadata = &tai_metadata_enum_tai_{{ name }}_attr_t,
|
||||
.attrmetadata = tai_metadata_object_type_tai_{{ name }}_attr_t,
|
||||
.attrmetadatalength = {{ attrs | count }},
|
||||
};
|
||||
'''
|
||||
|
||||
def __init__(self, obj):
|
||||
self.data = {'name': obj.name,
|
||||
'object_type' : obj.object_type,
|
||||
'attrs': [a.name for a in obj.get_attributes()]}
|
||||
|
||||
|
||||
class AttrMetadataGenerator(Generator):
|
||||
IMPL_TEMPLATE = '''
|
||||
const tai_attr_metadata_t tai_metadata_attr_{{ typename }} = {
|
||||
.objecttype = {{ object }},
|
||||
.attrid = {{ typename }},
|
||||
.attridname = "{{ typename }}",
|
||||
.attridshortname = "{{ shorttypename }}",
|
||||
.attrvaluetype = {{ attr_type }},
|
||||
{%- if attr_flags %}
|
||||
.flags = {{ attr_flags }},
|
||||
{%- else %}
|
||||
.flags = 0,
|
||||
{%- endif %}
|
||||
.isenum = {{ is_enum }},
|
||||
{%- if enum_meta_data %}
|
||||
.enummetadata = &{{ enum_meta_data }},
|
||||
{%- else %}
|
||||
.enummetadata = NULL,
|
||||
{%- endif %}
|
||||
};
|
||||
'''
|
||||
|
||||
def __init__(self, attr):
|
||||
obj = attr.object_type
|
||||
objname = attr.object_name
|
||||
typename = attr.name
|
||||
prefix = 'TAI_{}_ATTR_'.format(objname.upper())
|
||||
if not typename.startswith(prefix):
|
||||
raise Exception("invalid attr type name: {}, obj: {}".format(typename, obj))
|
||||
shorttypename = typename[len(prefix):].lower().replace('_', '-')
|
||||
attr_type = 'TAI_ATTR_VALUE_TYPE_{}'.format(attr.value_field.upper())
|
||||
is_enum = 'false'
|
||||
enum_meta_data = None
|
||||
if attr.enum_type:
|
||||
is_enum = 'true'
|
||||
enum_meta_data = 'tai_metadata_enum_{}'.format(attr.enum_type)
|
||||
attr_flags = None
|
||||
if attr.flags:
|
||||
attr_flags = '|'.join('TAI_ATTR_FLAGS_{}'.format(e.name) for e in list(attr.flags))
|
||||
|
||||
self.data = {'object': obj,
|
||||
'typename': typename,
|
||||
'shorttypename': shorttypename,
|
||||
'attr_type': attr_type,
|
||||
'attr_flags': attr_flags,
|
||||
'is_enum': is_enum,
|
||||
'enum_meta_data': enum_meta_data}
|
||||
|
||||
|
||||
class EnumMetadataGenerator(Generator):
|
||||
HEADER_TEMPLATE = '''int tai_serialize_{{ typename | simplify }}( _Out_ char *buffer, _In_ {{ typename }} {{ typename | simplify }}, _In_ const tai_serialize_option_t *option);;
|
||||
int tai_deserialize_{{ typename | simplify }}( _In_ const char *buffer, _Out_ int32_t *value, _In_ const tai_serialize_option_t *option);
|
||||
'''
|
||||
|
||||
|
||||
IMPL_TEMPLATE = '''const {{ typename }} tai_metadata_{{ typename }}_enum_values[] = {
|
||||
{% for t in enums -%}
|
||||
{{ t }},
|
||||
{% endfor -%}
|
||||
-1
|
||||
};
|
||||
|
||||
const char* const tai_metadata_{{ typename }}_enum_values_names[] = {
|
||||
{% for t in enums -%}
|
||||
"{{ t }}",
|
||||
{% endfor -%}
|
||||
NULL
|
||||
};
|
||||
|
||||
const char* const tai_metadata_{{ typename }}_enum_values_short_names[] = {
|
||||
{% for t in enums -%}
|
||||
"{{ t | shorten(typename) }}",
|
||||
{% endfor -%}
|
||||
NULL
|
||||
};
|
||||
|
||||
const tai_enum_metadata_t tai_metadata_enum_{{ typename }} = {
|
||||
.name = "{{ typename }}",
|
||||
.valuescount = {{ enums | count }},
|
||||
.values = (const int*)tai_metadata_{{ typename }}_enum_values,
|
||||
.valuesnames = tai_metadata_{{ typename }}_enum_values_names,
|
||||
.valuesshortnames = tai_metadata_{{ typename }}_enum_values_short_names,
|
||||
.containsflags = false,
|
||||
};
|
||||
|
||||
int tai_serialize_{{ typename | simplify }}(
|
||||
_Out_ char *buffer,
|
||||
_In_ {{ typename }} {{ typename | simplify }},
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
return tai_serialize_enum(buffer, &tai_metadata_enum_{{ typename }}, {{ typename | simplify }}, option);
|
||||
}
|
||||
|
||||
int tai_deserialize_{{ typename | simplify }}(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int32_t *value,
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
return tai_deserialize_enum(buffer, &tai_metadata_enum_{{ typename }}, value, option);
|
||||
}
|
||||
'''
|
||||
|
||||
def __init__(self, enum):
|
||||
typename = enum.typename
|
||||
enums = enum.value_names()
|
||||
|
||||
env = Environment()
|
||||
def shorten(v, typename):
|
||||
if not typename.endswith('_t'):
|
||||
raise Exception("invalid type name: {}".format(typename))
|
||||
t = typename[:-1].upper()
|
||||
if not v.startswith(t):
|
||||
raise Exception("invalid enum value name: {}".format(v))
|
||||
return v[len(t):].lower().replace('_', '-')
|
||||
|
||||
def simplify(typename):
|
||||
return typename[4:-2]
|
||||
env.filters['shorten'] = shorten
|
||||
env.filters['simplify'] = simplify
|
||||
super(EnumMetadataGenerator, self).__init__(env)
|
||||
self.data = {'typename': typename, 'enums': enums}
|
||||
|
||||
|
||||
class TAIMetadataGenerator(Generator):
|
||||
HEADER_TEMPLATE = '''/* AUTOGENERATED FILE! DO NOT EDIT */
|
||||
#ifndef __TAI_METADATA_H__
|
||||
#define __TAI_METADATA_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <tai.h>
|
||||
#include "taimetadatatypes.h"
|
||||
#include "taimetadatautils.h"
|
||||
#include "taimetadatalogger.h"
|
||||
#include "taiserialize.h"
|
||||
|
||||
{% for e in headers -%}
|
||||
{{ e }}
|
||||
{% endfor -%}
|
||||
|
||||
extern const tai_attr_metadata_t* const* const tai_metadata_attr_by_object_type[];
|
||||
extern const size_t tai_metadata_attr_by_object_type_count;
|
||||
|
||||
/* Object infos table */
|
||||
|
||||
extern const tai_object_type_info_t* const tai_metadata_all_object_type_infos[];
|
||||
|
||||
/* List of all attributes */
|
||||
|
||||
extern const tai_attr_metadata_t* const tai_metadata_attr_sorted_by_id_name[];
|
||||
extern const size_t tai_metadata_attr_sorted_by_id_name_count;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif'''
|
||||
|
||||
IMPL_TEMPLATE = '''/* AUTOGENERATED FILE! DO NOT EDIT */
|
||||
#include <stdio.h>
|
||||
#include "taimetadata.h"
|
||||
|
||||
{% for e in impls -%}
|
||||
{{ e }}
|
||||
{% endfor -%}
|
||||
|
||||
volatile tai_log_level_t tai_metadata_log_level = TAI_LOG_LEVEL_NOTICE;
|
||||
volatile tai_metadata_log_fn tai_metadata_log = NULL;
|
||||
|
||||
const tai_attr_metadata_t* const* const tai_metadata_attr_by_object_type[] = {
|
||||
NULL,
|
||||
{% for o in object_names -%}
|
||||
tai_metadata_object_type_tai_{{ o }}_attr_t,
|
||||
{% endfor -%}
|
||||
NULL
|
||||
};
|
||||
const size_t tai_metadata_attr_by_object_type_count = {{ object_names | count }};
|
||||
|
||||
const tai_object_type_info_t* const tai_metadata_all_object_type_infos[] = {
|
||||
NULL,
|
||||
{% for o in object_names -%}
|
||||
&tai_metadata_object_type_info_{{ o }},
|
||||
{% endfor -%}
|
||||
NULL
|
||||
};
|
||||
|
||||
const tai_attr_metadata_t* const tai_metadata_attr_sorted_by_id_name[] = {
|
||||
{% for a in attrs -%}
|
||||
&tai_metadata_attr_{{ a }},
|
||||
{% endfor -%}
|
||||
NULL
|
||||
};
|
||||
|
||||
const size_t tai_metadata_attr_sorted_by_id_name_count = {{ attrs | count }};
|
||||
|
||||
'''
|
||||
|
||||
def __init__(self, objects):
|
||||
generators = []
|
||||
all_attrs = []
|
||||
for obj in objects:
|
||||
attrs = obj.get_attributes()
|
||||
enums = obj.get_enums()
|
||||
|
||||
for e in enums:
|
||||
g = EnumMetadataGenerator(e)
|
||||
generators.append(g)
|
||||
|
||||
for a in attrs:
|
||||
g = AttrMetadataGenerator(a)
|
||||
generators.append(g)
|
||||
|
||||
e = obj.get_enum('tai_{}_attr_t'.format(obj.name))
|
||||
g = EnumMetadataGenerator(e)
|
||||
generators.append(g)
|
||||
|
||||
g = ObjectMetadataGenerator(obj)
|
||||
generators.append(g)
|
||||
|
||||
all_attrs += [a.name for a in attrs]
|
||||
|
||||
self.data = {'impls': [g.implementation() for g in generators],
|
||||
'headers': [x for x in [g.header() for g in generators] if len(x) > 0],
|
||||
'object_names': [o.name for o in objects],
|
||||
'attrs': sorted(all_attrs)}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = OptionParser()
|
||||
parser.add_option('--clang-lib', default='/usr/lib/llvm-6.0/lib/libclang.so.1')
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
Config.set_library_file(options.clang_lib)
|
||||
|
||||
objects = [TAIObject(t, args[0]) for t in TAIObject.OBJECT_MAP.keys()]
|
||||
|
||||
g = TAIMetadataGenerator(objects)
|
||||
with open('taimetadata.h', 'w') as f:
|
||||
f.write(g.header())
|
||||
|
||||
with open('taimetadata.c', 'w') as f:
|
||||
f.write(g.implementation())
|
||||
105
meta/taimetadatalogger.h
Normal file
105
meta/taimetadatalogger.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @file taimetadatalogger.h
|
||||
*
|
||||
* @brief This module defines TAI Metadata Logger
|
||||
*
|
||||
* @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc.
|
||||
* @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation
|
||||
*
|
||||
* @remark Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||
* may not use this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* @remark THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
*
|
||||
* @remark See the Apache Version 2.0 License for specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* @remark Microsoft would like to thank the following companies for their
|
||||
* review and assistance with these files: Intel Corporation, Mellanox
|
||||
* Technologies Ltd, Dell Products, L.P., Facebook, Inc., Marvell
|
||||
* International Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __TAIMETADATALOGGER_H_
|
||||
#define __TAIMETADATALOGGER_H_
|
||||
|
||||
/**
|
||||
* @defgroup TAIMETADATALOGGER TAI - Metadata Logger Definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Log level function definition.
|
||||
*
|
||||
* User can specify his own function that will be called when message log level
|
||||
* will be greater or equal to #tai_metadata_log_level.
|
||||
*
|
||||
* @param[in] log_level Log level
|
||||
* @param[in] file Source file
|
||||
* @param[in] line Line number in file
|
||||
* @param[in] function Function name
|
||||
* @param[in] format Format of logging
|
||||
* @param[in] ... Variable parameters
|
||||
*/
|
||||
typedef void (*tai_metadata_log_fn)(
|
||||
_In_ tai_log_level_t log_level,
|
||||
_In_ const char *file,
|
||||
_In_ int line,
|
||||
_In_ const char *function,
|
||||
_In_ const char *format,
|
||||
_In_ ...);
|
||||
|
||||
/**
|
||||
* @brief User specified log function.
|
||||
*
|
||||
* TODO: add a set function to update this?
|
||||
*/
|
||||
extern volatile tai_metadata_log_fn tai_metadata_log;
|
||||
|
||||
/**
|
||||
* @brief Log level for TAI metadata macros.
|
||||
*
|
||||
* Log level can be changed by user at any time.
|
||||
*
|
||||
* TODO: add a set function to update this?
|
||||
*/
|
||||
extern volatile tai_log_level_t tai_metadata_log_level;
|
||||
|
||||
/**
|
||||
* @brief Helper log macro definition
|
||||
*
|
||||
* If logger function is NULL, stderr is used to print messages. Also, fprintf
|
||||
* function will validate parameters at compilation time.
|
||||
*/
|
||||
#define TAI_META_LOG(loglevel,format,...)\
|
||||
if (loglevel >= tai_metadata_log_level)\
|
||||
{\
|
||||
if (tai_metadata_log == NULL) /* or syslog? */ \
|
||||
fprintf(stderr, "%s:%d %s: " format "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);\
|
||||
else\
|
||||
tai_metadata_log(loglevel, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__);\
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define TAI_META_LOG_ENTER() TAI_META_LOG(TAI_LOG_LEVEL_DEBUG, ":> enter");
|
||||
#define TAI_META_LOG_DEBUG(format,...) TAI_META_LOG(TAI_LOG_LEVEL_DEBUG, ":- " format, ##__VA_ARGS__)
|
||||
#define TAI_META_LOG_INFO(format,...) TAI_META_LOG(TAI_LOG_LEVEL_INFO, ":- " format, ##__VA_ARGS__)
|
||||
#define TAI_META_LOG_NOTICE(format,...) TAI_META_LOG(TAI_LOG_LEVEL_NOTICE, ":- " format, ##__VA_ARGS__)
|
||||
#define TAI_META_LOG_WARN(format,...) TAI_META_LOG(TAI_LOG_LEVEL_WARN, ":- " format, ##__VA_ARGS__)
|
||||
#define TAI_META_LOG_ERROR(format,...) TAI_META_LOG(TAI_LOG_LEVEL_ERROR, ":- " format, ##__VA_ARGS__)
|
||||
#define TAI_META_LOG_CRITICAL(format,...) TAI_META_LOG(TAI_LOG_LEVEL_CRITICAL, ":- " format, ##__VA_ARGS__)
|
||||
#define TAI_META_LOG_EXIT() TAI_META_LOG(TAI_LOG_LEVEL_DEBUG, ":< exit");
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /** __TAIMETADATALOGGER_H_ */
|
||||
914
meta/taimetadatatypes.h
Normal file
914
meta/taimetadatatypes.h
Normal file
@@ -0,0 +1,914 @@
|
||||
/**
|
||||
* @file taimetadatatypes.h
|
||||
*
|
||||
* @brief This module defines TAI Metadata Types
|
||||
*
|
||||
* @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc.
|
||||
* @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation
|
||||
*
|
||||
* @remark Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||
* may not use this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* @remark THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
*
|
||||
* @remark See the Apache Version 2.0 License for specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* @remark Microsoft would like to thank the following companies for their
|
||||
* review and assistance with these files: Intel Corporation, Mellanox
|
||||
* Technologies Ltd, Dell Products, L.P., Facebook, Inc., Marvell
|
||||
* International Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __TAIMETADATATYPES_H_
|
||||
#define __TAIMETADATATYPES_H_
|
||||
|
||||
/**
|
||||
* @defgroup TAIMETADATATYPES TAI - Metadata Types Definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def TAI_INVALID_ATTRIBUTE_ID
|
||||
*/
|
||||
#define TAI_INVALID_ATTRIBUTE_ID ((tai_attr_id_t)-1)
|
||||
|
||||
/**
|
||||
* @brief Defines attribute value type.
|
||||
* Can be used when serializing attributes.
|
||||
*/
|
||||
typedef enum _tai_attr_value_type_t
|
||||
{
|
||||
/**
|
||||
* @brief Attribute value is bool.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_BOOLDATA,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is char data.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_CHARDATA,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 8 bit unsigned integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U8,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 8 bit signed integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S8,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 16 bit unsigned integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U16,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 16 bit signed integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S16,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 32 bit unsigned integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U32,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 32 bit signed integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S32,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 64 bit unsigned integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U64,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 64 bit signed integer.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S64,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is float.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_FLT,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is pointer address.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_PTR,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is object id.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_OID,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is object list.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_OBJLIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of char.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_CHARLIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of 8 bit unsigned integers.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U8LIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of 8 bit signed integers.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S8LIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of 16 bit unsigned integers.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U16LIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of 16 bit signed integers.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S16LIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of 32 bit unsigned integers.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U32LIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of 32 bit signed integers.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S32LIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is list of float.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_FLOATLIST,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 32 bit unsigned integer range.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_U32RANGE,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is 32 bit signed integer range.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_S32RANGE,
|
||||
|
||||
/**
|
||||
* @brief Attribute value is object map list.
|
||||
*/
|
||||
TAI_ATTR_VALUE_TYPE_OBJMAPLIST,
|
||||
|
||||
} tai_attr_value_type_t;
|
||||
|
||||
/**
|
||||
* @brief Attribute flags.
|
||||
*
|
||||
* @flags Contains flags
|
||||
*/
|
||||
typedef enum _tai_attr_flags_t
|
||||
{
|
||||
/**
|
||||
* @brief Mandatory on create flag.
|
||||
*
|
||||
* Attribute with this flag is mandatory when calling CREATE API, unless
|
||||
* this attribute is marked as conditional. Must be combined with
|
||||
* CREATE_ONLY or CREATE_AND_SET flag.
|
||||
*/
|
||||
TAI_ATTR_FLAGS_MANDATORY_ON_CREATE = (1 << 0),
|
||||
|
||||
/**
|
||||
* @brief Create only flag.
|
||||
*
|
||||
* Attribute with this flag can only be created and its value cannot be
|
||||
* changed by SET API. Can be combined with MANDATORY flag. If
|
||||
* attribute is not combined with MANDATORY flag then DEFAULT value must be
|
||||
* provided for this attribute.
|
||||
*/
|
||||
TAI_ATTR_FLAGS_CREATE_ONLY = (1 << 1),
|
||||
|
||||
/**
|
||||
* @brief Create and set flag.
|
||||
*
|
||||
* Attribute with this flag can be created and after creation value may be
|
||||
* modified using SET API. Can be combined with MANDATORY flag. If
|
||||
* attribute is not combined with MANDATORY flag then DEFAULT value must be
|
||||
* provided for this attribute.
|
||||
*/
|
||||
TAI_ATTR_FLAGS_CREATE_AND_SET = (1 << 2),
|
||||
|
||||
/**
|
||||
* @brief Read only flag.
|
||||
*
|
||||
* Attribute with this flag can only be read using GET API. Creation and
|
||||
* modification is not possible. Can be combined with DYNAMIC flag for
|
||||
* example counter attribute.
|
||||
*/
|
||||
TAI_ATTR_FLAGS_READ_ONLY = (1 << 3),
|
||||
|
||||
/**
|
||||
* @brief Key flag.
|
||||
*
|
||||
* Attribute with this flag is treated as unique key (can only be combined
|
||||
* with MANDATORY and CREATE_ONLY flags. This flag will indicate that
|
||||
* creating new object with the same key will fail (for example VLAN).
|
||||
* There may be more than one key in attributes when creating object. Key
|
||||
* should be used only on primitive attribute values (like enum or int).
|
||||
* In some cases it may be supported on list (for port lanes) but then
|
||||
* extra logic is needed to compute and handle that key.
|
||||
*
|
||||
* If multiple keys are provided, meta key is created as combination of
|
||||
* keys in order attribute ids are declared (internal details).
|
||||
*/
|
||||
TAI_ATTR_FLAGS_KEY = (1 << 4),
|
||||
|
||||
/**
|
||||
* @brief Dynamic flag.
|
||||
*
|
||||
* Attribute with this flag indicates that value of the attribute is
|
||||
* dynamic and can change in time (like an attribute counter value, or port
|
||||
* operational status). Change may happen independently or when other
|
||||
* attribute was created or modified (creating vlan member will change vlan
|
||||
* member list). Can be combined with READ_ONLY flag.
|
||||
*/
|
||||
TAI_ATTR_FLAGS_DYNAMIC = (1 << 5),
|
||||
|
||||
/**
|
||||
* @brief Special flag.
|
||||
*
|
||||
* Attribute with this flag will indicate that this attribute is special
|
||||
* and it needs extended logic to be handled. This flag can only be
|
||||
* standalone.
|
||||
*/
|
||||
TAI_ATTR_FLAGS_SPECIAL = (1 << 6),
|
||||
|
||||
} tai_attr_flags_t;
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if mandatory on create flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_MANDATORY_ON_CREATE(x) (((x) & TAI_ATTR_FLAGS_MANDATORY_ON_CREATE) == TAI_ATTR_FLAGS_MANDATORY_ON_CREATE)
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if create only flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_CREATE_ONLY(x) (((x) & TAI_ATTR_FLAGS_CREATE_ONLY) == TAI_ATTR_FLAGS_CREATE_ONLY)
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if create and set flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_CREATE_AND_SET(x) (((x) & TAI_ATTR_FLAGS_CREATE_AND_SET) == TAI_ATTR_FLAGS_CREATE_AND_SET)
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if read only flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_READ_ONLY(x) (((x) & TAI_ATTR_FLAGS_READ_ONLY) == TAI_ATTR_FLAGS_READ_ONLY)
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if key flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_KEY(x) (((x) & TAI_ATTR_FLAGS_KEY) == TAI_ATTR_FLAGS_KEY)
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if dynamic flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_DYNAMIC(x) (((x) & TAI_ATTR_FLAGS_DYNAMIC) == TAI_ATTR_FLAGS_DYNAMIC)
|
||||
|
||||
/**
|
||||
* @def Defines helper to check if special flag is set.
|
||||
*/
|
||||
#define TAI_HAS_FLAG_SPECIAL(x) (((x) & TAI_ATTR_FLAGS_SPECIAL) == TAI_ATTR_FLAGS_SPECIAL)
|
||||
|
||||
/**
|
||||
* @brief Defines default value type.
|
||||
*/
|
||||
typedef enum _tai_default_value_type_t
|
||||
{
|
||||
/**
|
||||
* @brief There is no default value.
|
||||
*
|
||||
* This must be assigned on MANDATORY_ON_CREATE
|
||||
* attributes.
|
||||
*/
|
||||
TAI_DEFAULT_VALUE_TYPE_NONE = 0,
|
||||
|
||||
/**
|
||||
* @brief Default value is just a const value.
|
||||
*/
|
||||
TAI_DEFAULT_VALUE_TYPE_CONST,
|
||||
|
||||
/**
|
||||
* @brief Value must be in range provided by other attribute.
|
||||
*
|
||||
* Usually value is provided by switch object.
|
||||
* Range can be obtained by GET API.
|
||||
* Usually default value is minimum of range.
|
||||
*/
|
||||
TAI_DEFAULT_VALUE_TYPE_ATTR_RANGE,
|
||||
|
||||
/**
|
||||
* @brief Default value is equal to other attribute value.
|
||||
*
|
||||
* Usually value is provided by switch object.
|
||||
* Can be obtained using GET API.
|
||||
*/
|
||||
TAI_DEFAULT_VALUE_TYPE_ATTR_VALUE,
|
||||
|
||||
/**
|
||||
* @brief Default value is just empty list.
|
||||
*/
|
||||
TAI_DEFAULT_VALUE_TYPE_EMPTY_LIST,
|
||||
|
||||
/**
|
||||
* @brief Default value is vendor specific.
|
||||
*
|
||||
* This value is assigned by switch vendor
|
||||
* like default switch MAC address.
|
||||
*
|
||||
* It can also be default created object
|
||||
* like default hash.
|
||||
*
|
||||
* Vendor specific should be different
|
||||
* from default objects that are created
|
||||
* by default.
|
||||
*/
|
||||
TAI_DEFAULT_VALUE_TYPE_VENDOR_SPECIFIC,
|
||||
|
||||
} tai_default_value_type_t;
|
||||
|
||||
/**
|
||||
* @brief Defines attribute condition type.
|
||||
*/
|
||||
typedef enum _tai_attr_condition_type_t
|
||||
{
|
||||
/**
|
||||
* @brief This attribute is not conditional attribute
|
||||
*/
|
||||
TAI_ATTR_CONDITION_TYPE_NONE = 0,
|
||||
|
||||
/**
|
||||
* @brief Any condition that will be true will make
|
||||
* this attribute mandatory.
|
||||
*/
|
||||
TAI_ATTR_CONDITION_TYPE_OR,
|
||||
|
||||
/**
|
||||
* @brief All conditions must meet for this attribute
|
||||
* to be mandatory on create.
|
||||
*/
|
||||
TAI_ATTR_CONDITION_TYPE_AND,
|
||||
|
||||
} tai_attr_condition_type_t;
|
||||
|
||||
/**
|
||||
* @brief Defines attribute condition.
|
||||
*/
|
||||
typedef struct _tai_attr_condition_t
|
||||
{
|
||||
/**
|
||||
* @brief Specifies valid attribute id for this object type.
|
||||
* Attribute is for the same object type.
|
||||
*/
|
||||
tai_attr_id_t attrid;
|
||||
|
||||
/**
|
||||
* @brief Condition value that attribute will be mandatory
|
||||
* then default value must be provided for attribute.
|
||||
*/
|
||||
const tai_attribute_value_t condition;
|
||||
|
||||
/*
|
||||
* In future we can add condition operator like equal, not equal, etc.
|
||||
*/
|
||||
|
||||
} tai_attr_condition_t;
|
||||
|
||||
/**
|
||||
* @brief Defines enum metadata information.
|
||||
*/
|
||||
typedef struct _tai_enum_metadata_t
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
_tai_enum_metadata_t(): name(nullptr),
|
||||
valuescount(0),
|
||||
values(nullptr),
|
||||
valuesnames(nullptr),
|
||||
valuesshortnames(nullptr){}
|
||||
#endif
|
||||
/**
|
||||
* @brief String representation of enum type definition.
|
||||
*/
|
||||
const char* const name;
|
||||
|
||||
/**
|
||||
* @brief Values count in enum.
|
||||
*/
|
||||
const size_t valuescount;
|
||||
|
||||
/**
|
||||
* @brief Array of enum values.
|
||||
*/
|
||||
const int* const values;
|
||||
|
||||
/**
|
||||
* @brief Array of enum values string names.
|
||||
*/
|
||||
const char* const* const valuesnames;
|
||||
|
||||
/**
|
||||
* @brief Array of enum values string short names.
|
||||
*/
|
||||
const char* const* const valuesshortnames;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether enumeration contains flags.
|
||||
*
|
||||
* When set to true numbers of enumeration are not continuous.
|
||||
*/
|
||||
bool containsflags;
|
||||
|
||||
} tai_enum_metadata_t;
|
||||
|
||||
/**
|
||||
* @brief Defines attribute metadata.
|
||||
*/
|
||||
typedef struct _tai_attr_metadata_t
|
||||
{
|
||||
/**
|
||||
* @brief Specifies valid TAI object type.
|
||||
*/
|
||||
tai_object_type_t objecttype;
|
||||
|
||||
/**
|
||||
* @brief Specifies valid attribute id for this object type.
|
||||
*/
|
||||
tai_attr_id_t attrid;
|
||||
|
||||
/**
|
||||
* @brief Specifies valid attribute id name for this object type.
|
||||
*/
|
||||
const char* const attridname;
|
||||
|
||||
/**
|
||||
* @brief Specifies valid short attribute id name for this object type.
|
||||
*/
|
||||
const char* const attridshortname;
|
||||
|
||||
/**
|
||||
* @brief Extracted brief description from Doxygen comment.
|
||||
*/
|
||||
const char* const brief;
|
||||
|
||||
/**
|
||||
* @brief Specifies attribute value type for this attribute.
|
||||
*/
|
||||
tai_attr_value_type_t attrvaluetype;
|
||||
|
||||
/**
|
||||
* @brief Specifies flags for this attribute.
|
||||
*/
|
||||
tai_attr_flags_t flags;
|
||||
|
||||
/**
|
||||
* @brief Specified allowed object types.
|
||||
*
|
||||
* If object attr value type is OBJECT_ID
|
||||
* this list specifies what object type can be used.
|
||||
*/
|
||||
const tai_object_type_t* const allowedobjecttypes;
|
||||
|
||||
/**
|
||||
* @brief Length of allowed object types.
|
||||
*/
|
||||
size_t allowedobjecttypeslength;
|
||||
|
||||
/**
|
||||
* @brief Allows repetitions on object list.
|
||||
*
|
||||
* Can be useful when using object id list.
|
||||
*/
|
||||
bool allowrepetitiononlist;
|
||||
|
||||
/**
|
||||
* @brief Allows mixed object id types on list
|
||||
* like port and LAG.
|
||||
*/
|
||||
bool allowmixedobjecttypes;
|
||||
|
||||
/**
|
||||
* @brief Allows empty list to be set on list value type.
|
||||
*/
|
||||
bool allowemptylist;
|
||||
|
||||
/**
|
||||
* @brief Allows null object id to be passed.
|
||||
*
|
||||
* If object attr value type is OBJECT_ID
|
||||
* it tells whether TAI_NULL_OBJECT_ID can be used
|
||||
* as actual id.
|
||||
*/
|
||||
bool allownullobjectid;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute contains OIDs
|
||||
*/
|
||||
bool isoidattribute;
|
||||
|
||||
/**
|
||||
* @brief Specifies default value type.
|
||||
*
|
||||
* Default value can be a const assigned by switch
|
||||
* (which is not known at compile), can be obtained
|
||||
* by GET API, or a min/max value in specific
|
||||
* range also assigned by switch at run time.
|
||||
*
|
||||
* Default value can be also an object id.
|
||||
*/
|
||||
const tai_default_value_type_t defaultvaluetype;
|
||||
|
||||
/**
|
||||
* @brief Provides default value.
|
||||
*
|
||||
* If creation flag is CREATE_ONLY or CREATE_AND_SET
|
||||
* then default value must be provided for attribute.
|
||||
*
|
||||
* @note Default value may not apply for ACL field
|
||||
* or ACL entry, need special care.
|
||||
*/
|
||||
const tai_attribute_value_t* const defaultvalue;
|
||||
|
||||
/**
|
||||
* @brief Default value object type.
|
||||
*
|
||||
* Required when default value type is pointing to
|
||||
* different object type.
|
||||
*/
|
||||
tai_object_type_t defaultvalueobjecttype;
|
||||
|
||||
/**
|
||||
* @brief Default value object id.
|
||||
*
|
||||
* Required when default value type is pointing to
|
||||
* different object attribute.
|
||||
*/
|
||||
tai_attr_id_t defaultvalueattrid;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether default value needs to be saved.
|
||||
*
|
||||
* When switch is created some objects are created internally like vlan 1,
|
||||
* vlan members, bridge port, virtual router etc. Some of those objects
|
||||
* has attributes assigned by vendor like switch MAC address. When user
|
||||
* changes that value then there is no way to go back and set it's previous
|
||||
* value if user didn't query it first. This member will indicate whether
|
||||
* user needs to query it first (and store) before change, if he wants to
|
||||
* bring original attribute value later.
|
||||
*
|
||||
* Some of those attributes can be OID attributes with flags
|
||||
* MANDATORY_ON_CREATE and CREATE_AND_SET.
|
||||
*/
|
||||
bool storedefaultvalue;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether attribute is enum value.
|
||||
*
|
||||
* Attribute type must be set as INT32.
|
||||
*
|
||||
* @note Could be deduced from enum type string or
|
||||
* enum vector values and attr value type.
|
||||
*/
|
||||
bool isenum;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether attribute is enum list value.
|
||||
*
|
||||
* Attribute value must be set INT32 LIST.
|
||||
*
|
||||
* @note Could be deduced from enum type string or
|
||||
* enum vector values and attr value type.
|
||||
*/
|
||||
bool isenumlist;
|
||||
|
||||
/**
|
||||
* @brief Provides enum metadata if attribute
|
||||
* is enum or enum list.
|
||||
*/
|
||||
const tai_enum_metadata_t* const enummetadata;
|
||||
|
||||
/**
|
||||
* @brief Specifies condition type of attribute.
|
||||
*
|
||||
* @note Currently all conditions are "OR" conditions
|
||||
* so we can deduce if this is conditional type
|
||||
* if any conditions are defined.
|
||||
*/
|
||||
tai_attr_condition_type_t conditiontype;
|
||||
|
||||
/**
|
||||
* @brief Provide conditions for attribute under
|
||||
* which this attribute will be mandatory on create.
|
||||
*/
|
||||
const tai_attr_condition_t* const* const conditions;
|
||||
|
||||
/**
|
||||
* @brief Length of the conditions.
|
||||
*/
|
||||
size_t conditionslength;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether attribute is conditional.
|
||||
*/
|
||||
bool isconditional;
|
||||
|
||||
/**
|
||||
* @brief Specifies valid only type of attribute.
|
||||
*
|
||||
* @note Currently all valid only are "OR" conditions
|
||||
* so we can deduce if this is conditional type
|
||||
* if any conditions are defined.
|
||||
*/
|
||||
tai_attr_condition_type_t validonlytype;
|
||||
|
||||
/**
|
||||
* @brief Provides conditions when this attribute is valid.
|
||||
*
|
||||
* If conditions are specified (OR condition assumed)
|
||||
* then this attribute is only valid when different
|
||||
* attribute has condition value set. Valid only
|
||||
* attribute (against we check) can be dynamic so
|
||||
* this attribute can't be marked as MANDATORY on
|
||||
* create since default value will be required.
|
||||
*
|
||||
* @note There is only handful of attributes with
|
||||
* valid only mark. For now we will check that in
|
||||
* specific attribute logic.
|
||||
*/
|
||||
const tai_attr_condition_t* const* const validonly;
|
||||
|
||||
/**
|
||||
* @brief Length of the valid only when conditions.
|
||||
*/
|
||||
size_t validonlylength;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether attribute is valid only.
|
||||
*/
|
||||
bool isvalidonly;
|
||||
|
||||
/**
|
||||
* @brief When calling GET API result will be put
|
||||
* in local db for future use (extra logic).
|
||||
*
|
||||
* This flag must be taken with care, since when set
|
||||
* on dynamic attribute it may provide inconsistent data.
|
||||
*
|
||||
* Value should be updated after successful set or remove.
|
||||
*/
|
||||
bool getsave;
|
||||
|
||||
/**
|
||||
* @brief Determines whether value is vlan.
|
||||
*
|
||||
* Can only be set on tai_uint16_t value type.
|
||||
*/
|
||||
bool isvlan;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is ACL field
|
||||
*
|
||||
* This will become handy for fast determination whether
|
||||
* default value is present.
|
||||
*/
|
||||
bool isaclfield;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is ACL action
|
||||
*
|
||||
* This will become handy for fast determination whether
|
||||
* default value is present.
|
||||
*/
|
||||
bool isaclaction;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is mandatory on create
|
||||
*/
|
||||
bool ismandatoryoncreate;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is create only
|
||||
*/
|
||||
bool iscreateonly;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is create and set
|
||||
*/
|
||||
bool iscreateandset;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is read only
|
||||
*/
|
||||
bool isreadonly;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute is key
|
||||
*/
|
||||
bool iskey;
|
||||
|
||||
/**
|
||||
* @brief Determines whether attribute value is primitive.
|
||||
*
|
||||
* Primitive values will not contain any pointers so value can be
|
||||
* transferred by regular assignment operator.
|
||||
*/
|
||||
bool isprimitive;
|
||||
|
||||
/**
|
||||
* @brief Notification type
|
||||
*
|
||||
* If attribute value type is POINTER then attribute
|
||||
* value is pointer to switch notification.
|
||||
* Enum tai_switch_notification_type_t is auto generated
|
||||
* so it can't be used here, int will be used instead.
|
||||
*/
|
||||
int notificationtype;
|
||||
|
||||
} tai_attr_metadata_t;
|
||||
|
||||
/**
|
||||
* @brief Defines struct member info for
|
||||
* non object id object type
|
||||
*/
|
||||
typedef struct _tai_struct_member_info_t
|
||||
{
|
||||
/**
|
||||
* @brief Member value type
|
||||
*/
|
||||
tai_attr_value_type_t membervaluetype;
|
||||
|
||||
/**
|
||||
* @brief Member name
|
||||
*/
|
||||
const char* const membername;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether field is vlan
|
||||
*/
|
||||
bool isvlan;
|
||||
|
||||
/**
|
||||
* @brief Specified allowed object types.
|
||||
*
|
||||
* If object attr value type is OBJECT_ID
|
||||
* this list specifies what object type can be used.
|
||||
*/
|
||||
const tai_object_type_t* const allowedobjecttypes;
|
||||
|
||||
/**
|
||||
* @brief Length of allowed object types.
|
||||
*/
|
||||
size_t allowedobjecttypeslength;
|
||||
|
||||
/**
|
||||
* @brief Indicates whether member is enum value.
|
||||
*
|
||||
* Type must be set as INT32.
|
||||
*
|
||||
* @note Could be deduced from enum type string or
|
||||
* enum vector values and attr value type.
|
||||
*/
|
||||
bool isenum;
|
||||
|
||||
/**
|
||||
* @brief Provides enum metadata if member is enum
|
||||
*/
|
||||
const tai_enum_metadata_t* const enummetadata;
|
||||
|
||||
} tai_struct_member_info_t;
|
||||
|
||||
/**
|
||||
* @brief TAI reverse graph member
|
||||
*/
|
||||
typedef struct _tai_rev_graph_member_t
|
||||
{
|
||||
/**
|
||||
* @brief Defines main object type which is used
|
||||
* by dependency object type.
|
||||
*/
|
||||
tai_object_type_t objecttype;
|
||||
|
||||
/**
|
||||
* @brief Defines dependency object type on which
|
||||
* is object type defined above is used.
|
||||
*/
|
||||
tai_object_type_t depobjecttype;
|
||||
|
||||
/**
|
||||
* @brief Defines attribute metadata for object type
|
||||
*
|
||||
* This can be NULL if dependency object type
|
||||
* is non object id type and dependency is on
|
||||
* defined struct.
|
||||
*/
|
||||
const tai_attr_metadata_t* const attrmetadata;
|
||||
|
||||
/**
|
||||
* @brief Defines struct member for non object
|
||||
* id object type.
|
||||
*
|
||||
* This member can be NULL if dependency object type
|
||||
* is object attribute, and is not NULL id object
|
||||
* dependency is non object id struct member.
|
||||
*/
|
||||
const tai_struct_member_info_t* const structmember;
|
||||
|
||||
} tai_rev_graph_member_t;
|
||||
|
||||
/**
|
||||
* @brief TAI object type information
|
||||
*/
|
||||
typedef struct _tai_object_type_info_t
|
||||
{
|
||||
/**
|
||||
* @brief Object Type
|
||||
*/
|
||||
tai_object_type_t objecttype;
|
||||
|
||||
/**
|
||||
* @brief Object Type name
|
||||
*/
|
||||
const char* const objecttypename;
|
||||
|
||||
/**
|
||||
* @brief Start of attributes *_START
|
||||
*/
|
||||
tai_attr_id_t attridstart;
|
||||
|
||||
/**
|
||||
* @brief End of attributes *_END
|
||||
*/
|
||||
tai_attr_id_t attridend;
|
||||
|
||||
/**
|
||||
* @brief Provides enum metadata if attribute
|
||||
* is enum or enum list.
|
||||
*/
|
||||
const tai_enum_metadata_t* const enummetadata;
|
||||
|
||||
/**
|
||||
* @brief Attributes metadata
|
||||
*/
|
||||
const tai_attr_metadata_t* const* const attrmetadata;
|
||||
|
||||
/**
|
||||
* @brief Attributes metadata length.
|
||||
*/
|
||||
size_t attrmetadatalength;
|
||||
|
||||
/**
|
||||
* @brief Indicates if object is using struct
|
||||
* instead of actual object id
|
||||
*/
|
||||
bool isnonobjectid;
|
||||
|
||||
/**
|
||||
* @brief Indicates if object is OID object
|
||||
*/
|
||||
bool isobjectid;
|
||||
|
||||
/**
|
||||
* @brief Defines all struct members
|
||||
*/
|
||||
const tai_struct_member_info_t* const* const structmembers;
|
||||
|
||||
/**
|
||||
* @brief Defines count of struct members
|
||||
*/
|
||||
size_t structmemberscount;
|
||||
|
||||
/**
|
||||
* @brief Defines reverse dependency graph members
|
||||
*/
|
||||
const tai_rev_graph_member_t* const* const revgraphmembers;
|
||||
|
||||
/**
|
||||
* @brief Defines reverse dependency graph members count.
|
||||
*/
|
||||
size_t revgraphmemberscount;
|
||||
|
||||
} tai_object_type_info_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /** __TAIMETADATATYPES_H_ */
|
||||
332
meta/taimetadatautils.c
Normal file
332
meta/taimetadatautils.c
Normal file
@@ -0,0 +1,332 @@
|
||||
/**
|
||||
* @file taimetadatautils.c
|
||||
*
|
||||
* @brief This module implements TAI Metadata Utilities
|
||||
*
|
||||
* @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc.
|
||||
* @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation
|
||||
*
|
||||
* @remark Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||
* may not use this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* @remark THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
*
|
||||
* @remark See the Apache Version 2.0 License for specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* @remark Microsoft would like to thank the following companies for their
|
||||
* review and assistance with these files: Intel Corporation, Mellanox
|
||||
* Technologies Ltd, Dell Products, L.P., Facebook, Inc., Marvell
|
||||
* International Ltd.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <tai.h>
|
||||
#include "taimetadatautils.h"
|
||||
#include "taimetadata.h"
|
||||
|
||||
bool tai_metadata_is_allowed_object_type(
|
||||
_In_ const tai_attr_metadata_t* metadata,
|
||||
_In_ tai_object_type_t object_type)
|
||||
{
|
||||
if (metadata == NULL || metadata->allowedobjecttypes == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < metadata->allowedobjecttypeslength; ++i)
|
||||
{
|
||||
if (metadata->allowedobjecttypes[i] == object_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tai_metadata_is_allowed_enum_value(
|
||||
_In_ const tai_attr_metadata_t* metadata,
|
||||
_In_ int value)
|
||||
{
|
||||
if (metadata == NULL || metadata->enummetadata == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
const tai_enum_metadata_t *emd = metadata->enummetadata;
|
||||
|
||||
for (; i < emd->valuescount; ++i)
|
||||
{
|
||||
if (emd->values[i] == value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const tai_attr_metadata_t* tai_metadata_get_attr_metadata(
|
||||
_In_ tai_object_type_t objecttype,
|
||||
_In_ tai_attr_id_t attrid)
|
||||
{
|
||||
if (tai_metadata_is_object_type_valid(objecttype))
|
||||
{
|
||||
const tai_attr_metadata_t* const* const md = tai_metadata_attr_by_object_type[objecttype];
|
||||
|
||||
/*
|
||||
* Most obejct attributes are not flags, so we can use direct index to
|
||||
* find attribute metadata, this should speed up search.
|
||||
*/
|
||||
|
||||
const tai_object_type_info_t* oi = tai_metadata_all_object_type_infos[objecttype];
|
||||
|
||||
if (!oi->enummetadata->containsflags && attrid < oi->enummetadata->valuescount)
|
||||
{
|
||||
return md[attrid];
|
||||
}
|
||||
|
||||
/* otherwise search one by one */
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
for (; md[index] != NULL; index++)
|
||||
{
|
||||
if (md[index]->attrid == attrid)
|
||||
{
|
||||
return md[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const tai_attr_metadata_t* tai_metadata_get_attr_metadata_by_attr_id_name(
|
||||
_In_ const char *attr_id_name)
|
||||
{
|
||||
if (attr_id_name == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* use binary search */
|
||||
|
||||
ssize_t first = 0;
|
||||
ssize_t last = (ssize_t)(tai_metadata_attr_sorted_by_id_name_count - 1);
|
||||
|
||||
while (first <= last)
|
||||
{
|
||||
ssize_t middle = (first + last) / 2;
|
||||
|
||||
int res = strcmp(attr_id_name, tai_metadata_attr_sorted_by_id_name[middle]->attridname);
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
first = middle + 1;
|
||||
}
|
||||
else if (res < 0)
|
||||
{
|
||||
last = middle - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* found */
|
||||
|
||||
return tai_metadata_attr_sorted_by_id_name[middle];
|
||||
}
|
||||
}
|
||||
|
||||
/* not found */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* tai_metadata_get_enum_value_name(
|
||||
_In_ const tai_enum_metadata_t* metadata,
|
||||
_In_ int value)
|
||||
{
|
||||
if (metadata == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < metadata->valuescount; ++i)
|
||||
{
|
||||
if (metadata->values[i] == value)
|
||||
{
|
||||
return metadata->valuesnames[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const tai_attribute_t* tai_metadata_get_attr_by_id(
|
||||
_In_ tai_attr_id_t id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list)
|
||||
{
|
||||
if (attr_list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
for (; i < attr_count; ++i)
|
||||
{
|
||||
if (attr_list[i].id == id)
|
||||
{
|
||||
return &attr_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const tai_object_type_info_t* tai_metadata_get_object_type_info(
|
||||
_In_ tai_object_type_t object_type)
|
||||
{
|
||||
if (tai_metadata_is_object_type_valid(object_type))
|
||||
{
|
||||
return tai_metadata_all_object_type_infos[object_type];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool tai_metadata_is_object_type_valid(
|
||||
_In_ tai_object_type_t object_type)
|
||||
{
|
||||
return object_type > TAI_OBJECT_TYPE_NULL && object_type < TAI_OBJECT_TYPE_MAX;
|
||||
}
|
||||
|
||||
bool tai_metadata_is_condition_met(
|
||||
_In_ const tai_attr_metadata_t *metadata,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list)
|
||||
{
|
||||
if (metadata == NULL || !metadata->isconditional || attr_list == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
|
||||
bool met = (metadata->conditiontype == TAI_ATTR_CONDITION_TYPE_AND);
|
||||
|
||||
for (; idx < metadata->conditionslength; ++idx)
|
||||
{
|
||||
const tai_attr_condition_t *condition = metadata->conditions[idx];
|
||||
|
||||
/*
|
||||
* Conditons may only be on the same object type.
|
||||
*
|
||||
* Default value may not exists if conditional object is marked as
|
||||
* MANDATORY_ON_CREATE.
|
||||
*/
|
||||
|
||||
const tai_attr_metadata_t *cmd = tai_metadata_get_attr_metadata(metadata->objecttype, condition->attrid);
|
||||
|
||||
const tai_attribute_t *cattr = tai_metadata_get_attr_by_id(condition->attrid, attr_count, attr_list);
|
||||
|
||||
const tai_attribute_value_t* cvalue = NULL;
|
||||
|
||||
if (cattr == NULL)
|
||||
{
|
||||
/*
|
||||
* User didn't passed conditional attribute, so check if there is
|
||||
* default value.
|
||||
*/
|
||||
|
||||
cvalue = cmd->defaultvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
cvalue = &cattr->value;
|
||||
}
|
||||
|
||||
if (cvalue == NULL)
|
||||
{
|
||||
/*
|
||||
* There is no default value and user didn't passed attribute.
|
||||
*/
|
||||
|
||||
if (metadata->conditiontype == TAI_ATTR_CONDITION_TYPE_AND)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
bool current = false;
|
||||
|
||||
switch (cmd->attrvaluetype)
|
||||
{
|
||||
case TAI_ATTR_VALUE_TYPE_BOOLDATA:
|
||||
current = (condition->condition.booldata == cvalue->booldata);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_S8:
|
||||
current = (condition->condition.s8 == cvalue->s8);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_S16:
|
||||
current = (condition->condition.s16 == cvalue->s16);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_S32:
|
||||
current = (condition->condition.s32 == cvalue->s32);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_S64:
|
||||
current = (condition->condition.s64 == cvalue->s64);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_U8:
|
||||
current = (condition->condition.u8 == cvalue->u8);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_U16:
|
||||
current = (condition->condition.u16 == cvalue->u16);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_U32:
|
||||
current = (condition->condition.u32 == cvalue->u32);
|
||||
break;
|
||||
case TAI_ATTR_VALUE_TYPE_U64:
|
||||
current = (condition->condition.u64 == cvalue->u64);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/*
|
||||
* We should never get here since sanity check tests all
|
||||
* attributes and all conditions.
|
||||
*/
|
||||
|
||||
TAI_META_LOG_ERROR("condition value type %d is not supported, FIXME", cmd->attrvaluetype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (metadata->conditiontype == TAI_ATTR_CONDITION_TYPE_AND)
|
||||
{
|
||||
met &= current;
|
||||
}
|
||||
else /* OR */
|
||||
{
|
||||
met |= current;
|
||||
}
|
||||
}
|
||||
|
||||
return met;
|
||||
}
|
||||
161
meta/taimetadatautils.h
Normal file
161
meta/taimetadatautils.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @file taimetadatautils.h
|
||||
*
|
||||
* @brief This module defines TAI Metadata Utilities
|
||||
*
|
||||
* @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc.
|
||||
* @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation
|
||||
*
|
||||
* @remark Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||
* may not use this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* @remark THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
*
|
||||
* @remark See the Apache Version 2.0 License for specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* @remark Microsoft would like to thank the following companies for their
|
||||
* review and assistance with these files: Intel Corporation, Mellanox
|
||||
* Technologies Ltd, Dell Products, L.P., Facebook, Inc., Marvell
|
||||
* International Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __TAIMETADATAUTILS_H_
|
||||
#define __TAIMETADATAUTILS_H_
|
||||
|
||||
#include "taimetadatatypes.h"
|
||||
|
||||
/**
|
||||
* @defgroup TAIMETADATAUTILS TAI - Metadata Utilities Definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Is allowed object type
|
||||
*
|
||||
* @param[in] metadata Attribute metadata
|
||||
* @param[in] object_type Object type to be checked
|
||||
*
|
||||
* @return True if object is allowed on this attribute, false otherwise
|
||||
*/
|
||||
extern bool tai_metadata_is_allowed_object_type(
|
||||
_In_ const tai_attr_metadata_t *metadata,
|
||||
_In_ tai_object_type_t object_type);
|
||||
|
||||
/**
|
||||
* @brief Is allowed enum value
|
||||
*
|
||||
* @param[in] metadata Attribute metadata
|
||||
* @param[in] value Enum value to be checked
|
||||
*
|
||||
* @return True if enum value is allowed on this attribute, false otherwise
|
||||
*/
|
||||
extern bool tai_metadata_is_allowed_enum_value(
|
||||
_In_ const tai_attr_metadata_t *metadata,
|
||||
_In_ int value);
|
||||
|
||||
/**
|
||||
* @brief Gets attribute metadata based on object type and attribute id
|
||||
*
|
||||
* @param[in] object_type Object type
|
||||
* @param[in] attr_id Attribute Id
|
||||
*
|
||||
* @return Pointer to object metadata or NULL in case of failure
|
||||
*/
|
||||
extern const tai_attr_metadata_t* tai_metadata_get_attr_metadata(
|
||||
_In_ tai_object_type_t object_type,
|
||||
_In_ tai_attr_id_t attr_id);
|
||||
|
||||
/**
|
||||
* @brief Gets attribute metadata based on attribute id name
|
||||
*
|
||||
* @param[in] attr_id_name Attribute id name
|
||||
*
|
||||
* @return Pointer to object metadata or NULL in case of failure
|
||||
*/
|
||||
extern const tai_attr_metadata_t* tai_metadata_get_attr_metadata_by_attr_id_name(
|
||||
_In_ const char *attr_id_name);
|
||||
|
||||
/**
|
||||
* @brief Gets string representation of enum value
|
||||
*
|
||||
* @param[in] metadata Enum metadata
|
||||
* @param[in] value Enum value to be converted to string
|
||||
*
|
||||
* @return String representation of enum value or NULL if value was not found
|
||||
*/
|
||||
extern const char* tai_metadata_get_enum_value_name(
|
||||
_In_ const tai_enum_metadata_t *metadata,
|
||||
_In_ int value);
|
||||
|
||||
/**
|
||||
* @brief Gets attribute from attribute list by attribute id.
|
||||
*
|
||||
* @param[in] id Attribute id to be found.
|
||||
* @param[in] attr_count Total number of attributes.
|
||||
* @param[in] attr_list List of attributes to search.
|
||||
*
|
||||
* @return Attribute pointer with requested ID or NULL if not found.
|
||||
* When multiple attributes with the same id are passed, only first
|
||||
* attribute is returned.
|
||||
*/
|
||||
extern const tai_attribute_t* tai_metadata_get_attr_by_id(
|
||||
_In_ tai_attr_id_t id,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
/**
|
||||
* @brief Gets object type info
|
||||
*
|
||||
* @param[in] object_type Object type
|
||||
*
|
||||
* @return Object type info structure or NULL if not found
|
||||
*/
|
||||
extern const tai_object_type_info_t* tai_metadata_get_object_type_info(
|
||||
_In_ tai_object_type_t object_type);
|
||||
|
||||
/**
|
||||
* @brief Checks if object type is valid
|
||||
*
|
||||
* @param[in] object_type Object type
|
||||
*
|
||||
* @return True if object type is valid, false otherwise
|
||||
*/
|
||||
extern bool tai_metadata_is_object_type_valid(
|
||||
_In_ tai_object_type_t object_type);
|
||||
|
||||
/**
|
||||
* @brief Check if condition met.
|
||||
*
|
||||
* List of attributes will be examined in terms of conditions. This is
|
||||
* convenient since user can pass list when calling create API. If
|
||||
* condition attribute is not on the list, then default value will be
|
||||
* examined.
|
||||
*
|
||||
* NOTE: When multiple attributes with the same ID are passed,
|
||||
* tai_metadata_get_attr_by_id will select only first one.
|
||||
* Function will not be able to handle multiple attributes
|
||||
*
|
||||
* @param[in] metadata Metadata of attribute that we need to check.
|
||||
* @param[in] attr_count Number of attributes.
|
||||
* @param[in] attr_list Attribute list to check. All attributes must
|
||||
* belong to the same object type as metadata parameter.
|
||||
*
|
||||
* @return True if condition is in force, false otherwise. False will be also
|
||||
* returned if any of input pointers is NULL or attribute is not conditional.
|
||||
*/
|
||||
extern bool tai_metadata_is_condition_met(
|
||||
_In_ const tai_attr_metadata_t *metadata,
|
||||
_In_ uint32_t attr_count,
|
||||
_In_ const tai_attribute_t *attr_list);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /** __TAIMETADATAUTILS_H_ */
|
||||
740
meta/taiserialize.c
Normal file
740
meta/taiserialize.c
Normal file
@@ -0,0 +1,740 @@
|
||||
/**
|
||||
* @file taiserialize.c
|
||||
*
|
||||
* @brief This file implements basic serialization functions for
|
||||
* TAI attributes
|
||||
*
|
||||
* @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc.
|
||||
* @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation
|
||||
*
|
||||
* @remark Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||
* may not use this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* @remark THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
*
|
||||
* @remark See the Apache Version 2.0 License for specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* @remark Microsoft would like to thank the following companies for their
|
||||
* review and assistance with these files: Intel Corporation, Mellanox
|
||||
* Technologies Ltd, Dell Products, L.P., Facebook, Inc., Marvell
|
||||
* International Ltd.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <byteswap.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <tai.h>
|
||||
#include "taimetadatautils.h"
|
||||
#include "taimetadatalogger.h"
|
||||
#include "taiserialize.h"
|
||||
|
||||
#define PRIMITIVE_BUFFER_SIZE 128
|
||||
#define MAX_CHARS_PRINT 25
|
||||
|
||||
bool tai_serialize_is_char_allowed(
|
||||
_In_ char c)
|
||||
{
|
||||
/*
|
||||
* When we will perform deserialize, we allow buffer string to be
|
||||
* terminated not only by zero, but also with json characters like:
|
||||
*
|
||||
* - end of quote
|
||||
* - comma, next item in array
|
||||
* - end of array
|
||||
*
|
||||
* This will be handy when performing deserialize.
|
||||
*/
|
||||
|
||||
return c == 0 || c == '"' || c == ',' || c == ']' || c == '}';
|
||||
}
|
||||
|
||||
int tai_serialize_bool(
|
||||
_Out_ char *buffer,
|
||||
_In_ bool flag)
|
||||
{
|
||||
return sprintf(buffer, "%s", flag ? "true" : "false");
|
||||
}
|
||||
|
||||
#define TAI_TRUE_LENGTH 4
|
||||
#define TAI_FALSE_LENGTH 5
|
||||
|
||||
int tai_deserialize_bool(
|
||||
_In_ const char *buffer,
|
||||
_Out_ bool *flag)
|
||||
{
|
||||
if (strncmp(buffer, "true", TAI_TRUE_LENGTH) == 0 &&
|
||||
tai_serialize_is_char_allowed(buffer[TAI_TRUE_LENGTH]))
|
||||
{
|
||||
*flag = true;
|
||||
return TAI_TRUE_LENGTH;
|
||||
}
|
||||
|
||||
if (strncmp(buffer, "false", TAI_FALSE_LENGTH) == 0 &&
|
||||
tai_serialize_is_char_allowed(buffer[TAI_FALSE_LENGTH]))
|
||||
{
|
||||
*flag = false;
|
||||
return TAI_FALSE_LENGTH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit printf to maximum "false" length + 1 if there is invalid character
|
||||
* after "false" string.
|
||||
*/
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as bool",
|
||||
TAI_FALSE_LENGTH + 1,
|
||||
buffer);
|
||||
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_chardata(
|
||||
_Out_ char *buffer,
|
||||
_In_ const char data[TAI_CHARDATA_LENGTH])
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < TAI_CHARDATA_LENGTH; ++idx)
|
||||
{
|
||||
char c = data[idx];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (isprint(c) && c != '\\' && c != '"')
|
||||
{
|
||||
buffer[idx] = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("invalid character 0x%x in chardata", c);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
buffer[idx] = 0;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
int tai_deserialize_chardata(
|
||||
_In_ const char *buffer,
|
||||
_Out_ char data[TAI_CHARDATA_LENGTH])
|
||||
{
|
||||
int idx;
|
||||
|
||||
memset(data, 0, TAI_CHARDATA_LENGTH);
|
||||
|
||||
for (idx = 0; idx < TAI_CHARDATA_LENGTH; ++idx)
|
||||
{
|
||||
char c = buffer[idx];
|
||||
|
||||
if (isprint(c) && c != '\\' && c != '"')
|
||||
{
|
||||
data[idx] = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
/*
|
||||
* We allow quote as last char since chardata will be serialized in
|
||||
* quotes.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("invalid character 0x%x in chardata", c);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
if (tai_serialize_is_char_allowed(buffer[idx]))
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("invalid character 0x%x in chardata", buffer[idx]);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_uint8(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint8_t u8)
|
||||
{
|
||||
return sprintf(buffer, "%u", u8);
|
||||
}
|
||||
|
||||
int tai_deserialize_uint8(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint8_t *u8)
|
||||
{
|
||||
uint64_t u64;
|
||||
|
||||
int res = tai_deserialize_uint64(buffer, &u64);
|
||||
|
||||
if (res > 0 && u64 <= UCHAR_MAX)
|
||||
{
|
||||
*u8 = (uint8_t)u64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as uint8", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_int8(
|
||||
_Out_ char *buffer,
|
||||
_In_ int8_t u8)
|
||||
{
|
||||
return sprintf(buffer, "%d", u8);
|
||||
}
|
||||
|
||||
int tai_deserialize_int8(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int8_t *s8)
|
||||
{
|
||||
int64_t s64;
|
||||
|
||||
int res = tai_deserialize_int64(buffer, &s64);
|
||||
|
||||
if (res > 0 && s64 >= CHAR_MIN && s64 <= CHAR_MAX)
|
||||
{
|
||||
*s8 = (int8_t)s64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as int8", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_uint16(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint16_t u16)
|
||||
{
|
||||
return sprintf(buffer, "%u", u16);
|
||||
}
|
||||
|
||||
int tai_deserialize_uint16(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint16_t *u16)
|
||||
{
|
||||
uint64_t u64;
|
||||
|
||||
int res = tai_deserialize_uint64(buffer, &u64);
|
||||
|
||||
if (res > 0 && u64 <= USHRT_MAX)
|
||||
{
|
||||
*u16 = (uint16_t)u64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as uint16", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_int16(
|
||||
_Out_ char *buffer,
|
||||
_In_ int16_t s16)
|
||||
{
|
||||
return sprintf(buffer, "%d", s16);
|
||||
}
|
||||
|
||||
int tai_deserialize_int16(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int16_t *s16)
|
||||
{
|
||||
int64_t s64;
|
||||
|
||||
int res = tai_deserialize_int64(buffer, &s64);
|
||||
|
||||
if (res > 0 && s64 >= SHRT_MIN && s64 <= SHRT_MAX)
|
||||
{
|
||||
*s16 = (int16_t)s64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as int16", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_uint32(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint32_t u32)
|
||||
{
|
||||
return sprintf(buffer, "%u", u32);
|
||||
}
|
||||
|
||||
int tai_deserialize_uint32(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint32_t *u32)
|
||||
{
|
||||
uint64_t u64;
|
||||
|
||||
int res = tai_deserialize_uint64(buffer, &u64);
|
||||
|
||||
if (res > 0 && u64 <= UINT_MAX)
|
||||
{
|
||||
*u32 = (uint32_t)u64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as uint32", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_int32(
|
||||
_Out_ char *buffer,
|
||||
_In_ int32_t s32)
|
||||
{
|
||||
return sprintf(buffer, "%d", s32);
|
||||
}
|
||||
|
||||
int tai_deserialize_int32(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int32_t *s32)
|
||||
{
|
||||
int64_t s64;
|
||||
|
||||
int res = tai_deserialize_int64(buffer, &s64);
|
||||
|
||||
if (res > 0 && s64 >= INT_MIN && s64 <= INT_MAX)
|
||||
{
|
||||
*s32 = (int32_t)s64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as int32", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_uint64(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint64_t u64)
|
||||
{
|
||||
return sprintf(buffer, "%lu", u64);
|
||||
}
|
||||
|
||||
#define TAI_BASE_10 10
|
||||
|
||||
int tai_deserialize_uint64(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint64_t *u64)
|
||||
{
|
||||
int idx = 0;
|
||||
uint64_t result = 0;
|
||||
|
||||
while (isdigit(buffer[idx]))
|
||||
{
|
||||
char c = (char)(buffer[idx] - '0');
|
||||
|
||||
/*
|
||||
* Base is 10 we can check, that if result is greater than (2^64-1)/10)
|
||||
* then next multiplication with 10 will cause overflow.
|
||||
*/
|
||||
|
||||
if (result > (ULONG_MAX/TAI_BASE_10) ||
|
||||
((result == ULONG_MAX/TAI_BASE_10) && (c > (char)(ULONG_MAX % TAI_BASE_10))))
|
||||
{
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
result = result * 10 + (uint64_t)(c);
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx > 0 && tai_serialize_is_char_allowed(buffer[idx]))
|
||||
{
|
||||
*u64 = result;
|
||||
return idx;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s...' as uint64", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_int64(
|
||||
_Out_ char *buffer,
|
||||
_In_ int64_t s64)
|
||||
{
|
||||
return sprintf(buffer, "%ld", s64);
|
||||
}
|
||||
|
||||
int tai_deserialize_int64(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int64_t *s64)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
bool negative = 0;
|
||||
|
||||
if (*buffer == '-')
|
||||
{
|
||||
buffer++;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
int res = tai_deserialize_uint64(buffer, &result);
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
if (negative)
|
||||
{
|
||||
if (result <= (uint64_t)(LONG_MIN))
|
||||
{
|
||||
*s64 = -(int64_t)result;
|
||||
return res + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result <= LONG_MAX)
|
||||
{
|
||||
*s64 = (int64_t)result;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as int64", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_float(
|
||||
_Out_ char *buffer,
|
||||
_In_ float flt)
|
||||
{
|
||||
return sprintf(buffer, "%f", flt);
|
||||
}
|
||||
|
||||
int tai_deserialize_float(
|
||||
_In_ const char *buffer,
|
||||
_In_ float *flt)
|
||||
{
|
||||
double v = atof(buffer);
|
||||
*flt = (float)v;
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
int tai_serialize_size(
|
||||
_Out_ char *buffer,
|
||||
_In_ tai_size_t size)
|
||||
{
|
||||
return sprintf(buffer, "%zu", size);
|
||||
}
|
||||
|
||||
int tai_deserialize_size(
|
||||
_In_ const char *buffer,
|
||||
_Out_ tai_size_t *size)
|
||||
{
|
||||
uint64_t u64;
|
||||
|
||||
int res = tai_deserialize_uint64(buffer, &u64);
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
*size = (tai_size_t)u64;
|
||||
return res;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s...' as tai_size_t", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_object_id(
|
||||
_Out_ char *buffer,
|
||||
_In_ tai_object_id_t oid)
|
||||
{
|
||||
return sprintf(buffer, "oid:0x%lx", oid);
|
||||
}
|
||||
|
||||
int tai_deserialize_object_id(
|
||||
_In_ const char *buffer,
|
||||
_Out_ tai_object_id_t *oid)
|
||||
{
|
||||
int read;
|
||||
|
||||
int n = sscanf(buffer, "oid:0x%16lx%n", oid, &read);
|
||||
|
||||
if (n == 1 && tai_serialize_is_char_allowed(buffer[read]))
|
||||
{
|
||||
return read;
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("failed to deserialize '%.*s' as oid", MAX_CHARS_PRINT, buffer);
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_serialize_enum(
|
||||
_Out_ char *buffer,
|
||||
_In_ const tai_enum_metadata_t* meta,
|
||||
_In_ int32_t value,
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
if (meta == NULL)
|
||||
{
|
||||
return tai_serialize_int32(buffer, value);
|
||||
}
|
||||
bool short_ = false;
|
||||
if ( option != NULL && option->human ) {
|
||||
short_ = true;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < meta->valuescount; ++i)
|
||||
{
|
||||
if (meta->values[i] == value)
|
||||
{
|
||||
if ( short_ ) {
|
||||
return sprintf(buffer, "%s", meta->valuesshortnames[i]);
|
||||
} else {
|
||||
return sprintf(buffer, "%s", meta->valuesnames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("enum value %d not found in enum %s", value, meta->name);
|
||||
|
||||
return tai_serialize_int32(buffer, value);
|
||||
}
|
||||
|
||||
int tai_deserialize_enum(
|
||||
_In_ const char *buffer,
|
||||
_In_ const tai_enum_metadata_t* meta,
|
||||
_Out_ int32_t *value,
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
if (meta == NULL)
|
||||
{
|
||||
return tai_deserialize_int32(buffer, value);
|
||||
}
|
||||
|
||||
const char* const* names = meta->valuesnames;
|
||||
if ( option != NULL && option->human ) {
|
||||
names = meta->valuesshortnames;
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
|
||||
for (; idx < meta->valuescount; ++idx)
|
||||
{
|
||||
size_t len = strlen(names[idx]);
|
||||
|
||||
if (strncmp(names[idx], buffer, len) == 0 &&
|
||||
tai_serialize_is_char_allowed(buffer[len]))
|
||||
{
|
||||
*value = meta->values[idx];
|
||||
return (int)len;
|
||||
}
|
||||
}
|
||||
|
||||
TAI_META_LOG_WARN("enum value '%.*s' not found in enum %s", MAX_CHARS_PRINT, buffer, meta->name);
|
||||
|
||||
return tai_deserialize_int32(buffer, value);
|
||||
}
|
||||
|
||||
int tai_serialize_attribute(
|
||||
_Out_ char *buffer,
|
||||
_In_ const tai_attr_metadata_t *meta,
|
||||
_In_ const tai_attribute_t *attr,
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
int i;
|
||||
char *ptr = buffer;
|
||||
if ( option == NULL || !option->valueonly ) {
|
||||
if ( option != NULL && option->human ) {
|
||||
ptr += sprintf(ptr, "%s | ", meta->attridshortname);
|
||||
} else {
|
||||
ptr += sprintf(ptr, "%s | ", meta->attridname);
|
||||
}
|
||||
}
|
||||
switch ( meta->attrvaluetype ) {
|
||||
case TAI_ATTR_VALUE_TYPE_BOOLDATA:
|
||||
return tai_serialize_bool(ptr, attr->value.booldata);
|
||||
case TAI_ATTR_VALUE_TYPE_CHARDATA:
|
||||
return tai_serialize_chardata(ptr, attr->value.chardata);
|
||||
case TAI_ATTR_VALUE_TYPE_U8:
|
||||
return tai_serialize_uint8(ptr, attr->value.u8);
|
||||
case TAI_ATTR_VALUE_TYPE_S8:
|
||||
return tai_serialize_int8(ptr, attr->value.s8);
|
||||
case TAI_ATTR_VALUE_TYPE_U16:
|
||||
return tai_serialize_uint16(ptr, attr->value.u16);
|
||||
case TAI_ATTR_VALUE_TYPE_S16:
|
||||
return tai_serialize_int16(ptr, attr->value.s16);
|
||||
case TAI_ATTR_VALUE_TYPE_U32:
|
||||
return tai_serialize_uint32(ptr, attr->value.u32);
|
||||
case TAI_ATTR_VALUE_TYPE_S32:
|
||||
if ( meta->isenum ) {
|
||||
return tai_serialize_enum(ptr, meta->enummetadata, attr->value.s32, option);
|
||||
}
|
||||
return tai_serialize_int32(ptr, attr->value.s32);
|
||||
case TAI_ATTR_VALUE_TYPE_U64:
|
||||
return tai_serialize_uint64(ptr, attr->value.u64);
|
||||
case TAI_ATTR_VALUE_TYPE_S64:
|
||||
return tai_serialize_int64(ptr, attr->value.s64);
|
||||
case TAI_ATTR_VALUE_TYPE_FLT:
|
||||
return tai_serialize_float(ptr, attr->value.flt);
|
||||
case TAI_ATTR_VALUE_TYPE_PTR:
|
||||
TAI_META_LOG_WARN("pointer serialization is not implemented");
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
case TAI_ATTR_VALUE_TYPE_OID:
|
||||
return tai_serialize_object_id(ptr, attr->value.oid);
|
||||
case TAI_ATTR_VALUE_TYPE_OBJLIST:
|
||||
for ( i = 0; i < attr->value.objlist.count; i++ ) {
|
||||
ptr += tai_serialize_object_id(ptr, attr->value.objlist.list[i]);
|
||||
if ( i + 1 < attr->value.objlist.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_CHARLIST:
|
||||
memcpy(ptr, attr->value.charlist.list, attr->value.charlist.count);
|
||||
return ptr - buffer + attr->value.charlist.count;
|
||||
case TAI_ATTR_VALUE_TYPE_U8LIST:
|
||||
for ( i = 0; i < attr->value.u8list.count; i++ ) {
|
||||
ptr += tai_serialize_uint8(ptr, attr->value.u8list.list[i]);
|
||||
if ( i + 1 < attr->value.u8list.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_S8LIST:
|
||||
for ( i = 0; i < attr->value.s8list.count; i++ ) {
|
||||
ptr += tai_serialize_int8(ptr, attr->value.s8list.list[i]);
|
||||
if ( i + 1 < attr->value.s8list.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_U16LIST:
|
||||
for ( i = 0; i < attr->value.u16list.count; i++ ) {
|
||||
ptr += tai_serialize_uint16(ptr, attr->value.u16list.list[i]);
|
||||
if ( i + 1 < attr->value.u16list.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_S16LIST:
|
||||
for ( i = 0; i < attr->value.s16list.count; i++ ) {
|
||||
ptr += tai_serialize_int16(ptr, attr->value.s16list.list[i]);
|
||||
if ( i + 1 < attr->value.s16list.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_U32LIST:
|
||||
for ( i = 0; i < attr->value.u32list.count; i++ ) {
|
||||
ptr += tai_serialize_uint32(ptr, attr->value.u32list.list[i]);
|
||||
if ( i + 1 < attr->value.u32list.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_S32LIST:
|
||||
if ( meta->isenum ) {
|
||||
for ( i = 0; i < attr->value.s32list.count; i++ ) {
|
||||
ptr += tai_serialize_enum(ptr, meta->enummetadata, attr->value.s32list.list[i], option);
|
||||
if ( i + 1 < attr->value.s32list.count ) {
|
||||
ptr += sprintf(ptr, "|");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
}
|
||||
for ( i = 0; i < attr->value.s32list.count; i++ ) {
|
||||
ptr += tai_serialize_int32(ptr, attr->value.s32list.list[i]);
|
||||
if ( i + 1 < attr->value.s32list.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_FLOATLIST:
|
||||
for ( i = 0; i < attr->value.floatlist.count; i++ ) {
|
||||
ptr += tai_serialize_float(ptr, attr->value.floatlist.list[i]);
|
||||
if ( i + 1 < attr->value.floatlist.count ) {
|
||||
ptr += sprintf(ptr, ",");
|
||||
}
|
||||
}
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_U32RANGE:
|
||||
ptr += sprintf(ptr, "%u..%u", attr->value.u32range.min, attr->value.u32range.max);
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_S32RANGE:
|
||||
ptr += sprintf(ptr, "%d..%d", attr->value.s32range.min, attr->value.s32range.max);
|
||||
return ptr - buffer;
|
||||
case TAI_ATTR_VALUE_TYPE_OBJMAPLIST:
|
||||
TAI_META_LOG_WARN("objmaplist serialization is not implemented");
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
default:
|
||||
TAI_META_LOG_WARN("unknown attr value type");
|
||||
}
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_deserialize_attribute(
|
||||
_In_ const char *buffer,
|
||||
_In_ const tai_attr_metadata_t *meta,
|
||||
_Out_ tai_attribute_t *attribute,
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
TAI_META_LOG_WARN("not implemented");
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
|
||||
int tai_deserialize_attribute_value(
|
||||
_In_ const char *buffer,
|
||||
_In_ const tai_attr_metadata_t *meta,
|
||||
_Out_ tai_attribute_value_t *value,
|
||||
_In_ const tai_serialize_option_t *option)
|
||||
{
|
||||
switch ( meta->attrvaluetype ) {
|
||||
case TAI_ATTR_VALUE_TYPE_BOOLDATA:
|
||||
return tai_deserialize_bool(buffer, &value->booldata);
|
||||
case TAI_ATTR_VALUE_TYPE_CHARDATA:
|
||||
return tai_deserialize_chardata(buffer, value->chardata);
|
||||
case TAI_ATTR_VALUE_TYPE_U8:
|
||||
return tai_deserialize_uint8(buffer, &value->u8);
|
||||
case TAI_ATTR_VALUE_TYPE_S8:
|
||||
return tai_deserialize_int8(buffer, &value->s8);
|
||||
case TAI_ATTR_VALUE_TYPE_U16:
|
||||
return tai_deserialize_uint16(buffer, &value->u16);
|
||||
case TAI_ATTR_VALUE_TYPE_S16:
|
||||
return tai_deserialize_int16(buffer, &value->s16);
|
||||
case TAI_ATTR_VALUE_TYPE_U32:
|
||||
return tai_deserialize_uint32(buffer, &value->u32);
|
||||
case TAI_ATTR_VALUE_TYPE_S32:
|
||||
if ( meta->isenum ) {
|
||||
return tai_deserialize_enum(buffer, meta->enummetadata, &value->s32, option);
|
||||
}
|
||||
return tai_deserialize_int32(buffer, &value->s32);
|
||||
case TAI_ATTR_VALUE_TYPE_U64:
|
||||
return tai_deserialize_uint64(buffer, &value->u64);
|
||||
case TAI_ATTR_VALUE_TYPE_S64:
|
||||
return tai_deserialize_int64(buffer, &value->s64);
|
||||
case TAI_ATTR_VALUE_TYPE_FLT:
|
||||
return tai_deserialize_float(buffer, &value->flt);
|
||||
case TAI_ATTR_VALUE_TYPE_PTR:
|
||||
TAI_META_LOG_WARN("pointer serialization is not implemented");
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
return TAI_SERIALIZE_ERROR;
|
||||
}
|
||||
525
meta/taiserialize.h
Normal file
525
meta/taiserialize.h
Normal file
@@ -0,0 +1,525 @@
|
||||
/**
|
||||
* @file taiserialize.h
|
||||
*
|
||||
* @brief This module defines TAI Serialize methods
|
||||
*
|
||||
* @copyright Copyright (c) 2014 Microsoft Open Technologies, Inc.
|
||||
* @copyright Copyright (c) 2018 Nippon Telegraph and Telephone Corporation
|
||||
*
|
||||
* @remark Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||
* may not use this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* @remark THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
|
||||
* LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
*
|
||||
* @remark See the Apache Version 2.0 License for specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* @remark Microsoft would like to thank the following companies for their
|
||||
* review and assistance with these files: Intel Corporation, Mellanox
|
||||
* Technologies Ltd, Dell Products, L.P., Facebook, Inc., Marvell
|
||||
* International Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __TAISERIALIZE_H_
|
||||
#define __TAISERIALIZE_H_
|
||||
|
||||
/**
|
||||
* @defgroup TAISERIALIZE TAI - Serialize Definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def TAI_SERIALIZE_ERROR
|
||||
*
|
||||
* Returned from serialize/deserialize methods on any error.
|
||||
* Meta log functions are used to produce specific error message.
|
||||
*/
|
||||
#define TAI_SERIALIZE_ERROR (-1)
|
||||
|
||||
/**
|
||||
* @def TAI_CHARDATA_LENGTH
|
||||
*
|
||||
* Defines size of char data inside tai_attribute_value_t union.
|
||||
*/
|
||||
#define TAI_CHARDATA_LENGTH 32
|
||||
|
||||
/**
|
||||
* @brief Is char allowed.
|
||||
*
|
||||
* Function checks if given char is one of the following:
|
||||
* - '\0', '"', ',', ']', '}'
|
||||
*
|
||||
* Since serialization is done to json format, after each value
|
||||
* there may be some characters specific to json format, like:
|
||||
*
|
||||
* * quote, if value was in quotes (string)
|
||||
* * comma, if value was without quotes but an item in array (number, bool)
|
||||
* * square bracket, if item was last item in array (number, bool)
|
||||
* * curly bracket, if item was last item in object (number, bool)
|
||||
*
|
||||
* This means that deserialize is "relaxed", so each item don't need to end
|
||||
* as zero '\0' but it can end on any of those characters. This allows us to
|
||||
* deserialize json string reading it directly without creating json object
|
||||
* tree and without any extra string copy. For example if we have item:
|
||||
* {"foo":true}, we can just read value "true}" and ignore last character and
|
||||
* still value will be deserialized correctly.
|
||||
*
|
||||
* This is not ideal solution, but in this case it will work just fine.
|
||||
*
|
||||
* NOTE: All auto generated methods will enforce to check extra characters at
|
||||
* the end of each value.
|
||||
*/
|
||||
bool tai_serialize_is_char_allowed(
|
||||
_In_ char c);
|
||||
|
||||
/**
|
||||
* @brief Serialize bool value.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] flag Bool flag to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_bool(
|
||||
_Out_ char *buffer,
|
||||
_In_ bool flag);
|
||||
|
||||
/**
|
||||
* @brief Deserialize bool value.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] flag Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_bool(
|
||||
_In_ const char *buffer,
|
||||
_Out_ bool *flag);
|
||||
|
||||
/**
|
||||
* @brief Serialize char data value.
|
||||
*
|
||||
* All printable characters (isprint) are allowed except '\' and '"'.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] data Data to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_chardata(
|
||||
_Out_ char *buffer,
|
||||
_In_ const char data[TAI_CHARDATA_LENGTH]);
|
||||
|
||||
/**
|
||||
* @brief Deserialize char data value.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] data Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_chardata(
|
||||
_In_ const char *buffer,
|
||||
_Out_ char data[TAI_CHARDATA_LENGTH]);
|
||||
|
||||
/**
|
||||
* @brief Serialize 8 bit unsigned integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] u8 Deserialized value.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_uint8(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint8_t u8);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 8 bit unsigned integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] u8 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_uint8(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint8_t *u8);
|
||||
|
||||
/**
|
||||
* @brief Serialize 8 bit signed integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] u8 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_int8(
|
||||
_Out_ char *buffer,
|
||||
_In_ int8_t u8);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 8 bit signed integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] s8 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_int8(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int8_t *s8);
|
||||
|
||||
/**
|
||||
* @brief Serialize 16 bit unsigned integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] u16 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_uint16(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint16_t u16);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 16 bit unsigned integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] u16 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_uint16(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint16_t *u16);
|
||||
|
||||
/**
|
||||
* @brief Serialize 16 bit signed integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] s16 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_int16(
|
||||
_Out_ char *buffer,
|
||||
_In_ int16_t s16);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 16 bit signed integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] s16 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_int16(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int16_t *s16);
|
||||
|
||||
/**
|
||||
* @brief Serialize 32 bit unsigned integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] u32 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_uint32(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint32_t u32);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 32 bit unsigned integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] u32 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_uint32(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint32_t *u32);
|
||||
|
||||
/**
|
||||
* @brief Serialize 32 bit signed integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] s32 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_int32(
|
||||
_Out_ char *buffer,
|
||||
_In_ int32_t s32);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 32 bit signed integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] s32 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_int32(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int32_t *s32);
|
||||
|
||||
/**
|
||||
* @brief Serialize 64 bit unsigned integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] u64 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_uint64(
|
||||
_Out_ char *buffer,
|
||||
_In_ uint64_t u64);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 64 bit unsigned integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] u64 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_uint64(
|
||||
_In_ const char *buffer,
|
||||
_Out_ uint64_t *u64);
|
||||
|
||||
/**
|
||||
* @brief Serialize 64 bit signed integer.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] s64 Integer to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_int64(
|
||||
_Out_ char *buffer,
|
||||
_In_ int64_t s64);
|
||||
|
||||
/**
|
||||
* @brief Deserialize 64 bit signed integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] s64 Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_int64(
|
||||
_In_ const char *buffer,
|
||||
_Out_ int64_t *s64);
|
||||
|
||||
/**
|
||||
* @brief Serialize float.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] Float to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_float(
|
||||
_Out_ char *buffer,
|
||||
_In_ float flt);
|
||||
|
||||
/**
|
||||
* @brief Deserialize float.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] Float Deserialized value.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_float(
|
||||
_In_ const char *buffer,
|
||||
_Out_ float *flt);
|
||||
|
||||
/**
|
||||
* @brief Serialize tai_size_t.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] size Size to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_size(
|
||||
_Out_ char *buffer,
|
||||
_In_ tai_size_t size);
|
||||
|
||||
/**
|
||||
* @brief Deserialize tai_size_t.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] size Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_size(
|
||||
_In_ const char *buffer,
|
||||
_Out_ tai_size_t *size);
|
||||
|
||||
/**
|
||||
* @brief Serialize object ID.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] object_id Object ID to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_object_id(
|
||||
_Out_ char *buffer,
|
||||
_In_ tai_object_id_t object_id);
|
||||
|
||||
/**
|
||||
* @brief Deserialize object Id.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] object_id Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_object_id(
|
||||
_In_ const char *buffer,
|
||||
_Out_ tai_object_id_t *object_id);
|
||||
|
||||
/**
|
||||
* @brief Attribute serialize/deserialize option.
|
||||
*/
|
||||
typedef struct _tai_serialize_option_t
|
||||
{
|
||||
/**
|
||||
* @brief use human friendly names
|
||||
*/
|
||||
bool human;
|
||||
|
||||
/**
|
||||
* @brief value only
|
||||
*/
|
||||
bool valueonly;
|
||||
} tai_serialize_option_t;
|
||||
|
||||
/**
|
||||
* @brief Serialize enum value.
|
||||
*
|
||||
* Buffer will contain actual enum name of number if enum
|
||||
* value was not found in specified enum metadata.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] meta Enum metadata for serialization info.
|
||||
* @param[in] value Enum value to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_enum(
|
||||
_Out_ char *buffer,
|
||||
_In_ const tai_enum_metadata_t *meta,
|
||||
_In_ int32_t value,
|
||||
_In_ const tai_serialize_option_t *option);
|
||||
|
||||
/**
|
||||
* @brief Deserialize enum value.
|
||||
*
|
||||
* If buffer will not contain valid enum name, function will attempt to
|
||||
* deserialize value as signed 32 bit integer.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[in] meta Enum metadata.
|
||||
* @param[out] value Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_enum(
|
||||
_In_ const char *buffer,
|
||||
_In_ const tai_enum_metadata_t *meta,
|
||||
_Out_ int32_t *value,
|
||||
_In_ const tai_serialize_option_t *option);
|
||||
|
||||
/**
|
||||
* @brief Serialize TAI attribute.
|
||||
*
|
||||
* @param[out] buffer Output buffer for serialized value.
|
||||
* @param[in] meta Attribute metadata.
|
||||
* @param[in] attribute Attribute to be serialized.
|
||||
*
|
||||
* @return Number of characters written to buffer excluding '\0',
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_serialize_attribute(
|
||||
_Out_ char *buffer,
|
||||
_In_ const tai_attr_metadata_t *meta,
|
||||
_In_ const tai_attribute_t *attribute,
|
||||
_In_ const tai_serialize_option_t *option);
|
||||
|
||||
/**
|
||||
* @brief Deserialize TAI attribute.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] attribute Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_attribute(
|
||||
_In_ const char *buffer,
|
||||
_In_ const tai_attr_metadata_t *meta,
|
||||
_Out_ tai_attribute_t *attribute,
|
||||
_In_ const tai_serialize_option_t *option);
|
||||
|
||||
/**
|
||||
* @brief Deserialize TAI attribute value.
|
||||
*
|
||||
* @param[in] buffer Input buffer to be examined.
|
||||
* @param[out] attribute Deserialized value.
|
||||
*
|
||||
* @return Number of characters consumed from the buffer,
|
||||
* or #TAI_SERIALIZE_ERROR on error.
|
||||
*/
|
||||
int tai_deserialize_attribute_value(
|
||||
_In_ const char *buffer,
|
||||
_In_ const tai_attr_metadata_t *meta,
|
||||
_Out_ tai_attribute_value_t *value,
|
||||
_In_ const tai_serialize_option_t *option);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /** __TAISERIALIZE_H_ */
|
||||
1
meta/test/.gitignore
vendored
Normal file
1
meta/test/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test
|
||||
2
meta/test/Makefile
Normal file
2
meta/test/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
gcc -I ../../inc -I ../ -L .. -o test test.c -lmetatai
|
||||
85
meta/test/test.c
Normal file
85
meta/test/test.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "tai.h"
|
||||
#include "taimetadata.h"
|
||||
#include "stdio.h"
|
||||
|
||||
int test(char *buffer) {
|
||||
tai_attribute_t attr = {0};
|
||||
tai_serialize_option_t option = {
|
||||
.valueonly = true,
|
||||
};
|
||||
const tai_attr_metadata_t* meta = tai_metadata_get_attr_metadata(TAI_OBJECT_TYPE_MODULE, TAI_MODULE_ATTR_OPER_STATUS);
|
||||
attr.id = TAI_MODULE_ATTR_OPER_STATUS;
|
||||
attr.value.s32 = TAI_MODULE_OPER_STATUS_READY;
|
||||
return tai_serialize_attribute(buffer, meta, &attr, &option);
|
||||
}
|
||||
|
||||
int test2(char *buffer) {
|
||||
tai_attribute_t attr = {0};
|
||||
tai_serialize_option_t option = {
|
||||
.valueonly = true,
|
||||
};
|
||||
const tai_attr_metadata_t* meta = tai_metadata_get_attr_metadata(TAI_OBJECT_TYPE_MODULE, TAI_MODULE_ATTR_TEMP);
|
||||
attr.id = TAI_MODULE_ATTR_TEMP;
|
||||
attr.value.flt = 1.10;
|
||||
return tai_serialize_attribute(buffer, meta, &attr, &option);
|
||||
}
|
||||
|
||||
int test3(char *buffer) {
|
||||
tai_attribute_t attr = {0};
|
||||
tai_serialize_option_t option = {
|
||||
.valueonly = false,
|
||||
.human = true,
|
||||
};
|
||||
const tai_attr_metadata_t* meta = tai_metadata_get_attr_metadata(TAI_OBJECT_TYPE_NETWORKIF, TAI_NETWORK_INTERFACE_ATTR_TX_ALIGN_STATUS);
|
||||
int32_t list[] = {
|
||||
TAI_NETWORK_INTERFACE_TX_ALIGN_STATUS_LOSS,
|
||||
TAI_NETWORK_INTERFACE_TX_ALIGN_STATUS_OUT
|
||||
};
|
||||
attr.id = TAI_NETWORK_INTERFACE_ATTR_TX_ALIGN_STATUS;
|
||||
attr.value.s32list.count = 2;
|
||||
attr.value.s32list.list = (int32_t*)&list;
|
||||
|
||||
return tai_serialize_attribute(buffer, meta, &attr, &option);
|
||||
}
|
||||
|
||||
int test4() {
|
||||
const tai_attr_metadata_t* meta;
|
||||
meta = tai_metadata_get_attr_metadata_by_attr_id_name("TAI_NETWORK_INTERFACE_ATTR_TX_LASER_FREQ");
|
||||
printf("%p\n", meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test5() {
|
||||
int32_t value;
|
||||
int ret;
|
||||
tai_serialize_option_t option = {
|
||||
.human = true,
|
||||
};
|
||||
ret = tai_deserialize_network_interface_attr("tx-channel", &value, &option);
|
||||
printf("%d, %d\n", value, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int ret, value;
|
||||
char buf[128] = {0};
|
||||
|
||||
ret = tai_serialize_module_oper_status(buf, TAI_MODULE_OPER_STATUS_READY, NULL);
|
||||
|
||||
printf("%s, %d\n", buf, ret);
|
||||
ret = tai_deserialize_module_oper_status("TAI_MODULE_OPER_STATUS_INITIALIZE", &value, NULL);
|
||||
printf("%d, %d\n", value, ret);
|
||||
|
||||
ret = test(buf);
|
||||
printf("%s, %d\n", buf, ret);
|
||||
|
||||
ret = test2(buf);
|
||||
printf("%s, %d\n", buf, ret);
|
||||
|
||||
ret = test3(buf);
|
||||
printf("%s, %d\n", buf, ret);
|
||||
|
||||
test4();
|
||||
|
||||
test5();
|
||||
}
|
||||
Reference in New Issue
Block a user