Refine ov_partial_shape for OV API 2.0 C interface (#11891)

* Refine ov_partial_shape for OV 2.0 C interface

To avoid potential string security problem, remove string pointer from ov_partial_shape structure.

* Remove redundant code

* fix typo issue

* fix shape test issue

* fix some minor issues

* Address reviewing comments

Use Dimension to represent rank of parital shape.

* Appy safer method to parse partialShape string

1. adopt ov::Dimension::value_type to construct ov::Dimension
2. safter method to convert string to dimension value
3. apply std::vector<std::string> to replace std::vector<char *> during pasrsing partialShape string

Change-Id: I0e0b70a915fc5c5fefad51de51f167798854f55e
This commit is contained in:
River Li
2022-06-20 08:22:39 +08:00
committed by GitHub
parent 870f84f19b
commit ce5b2c6a45
4 changed files with 259 additions and 152 deletions

View File

@@ -133,8 +133,8 @@ int main(int argc, char** argv) {
ov_version_t version;
CHECK_STATUS(ov_get_version(&version));
printf("---- OpenVINO INFO----\n");
printf("description : %s \n", version.description);
printf("build number: %s \n", version.buildNumber);
printf("Description : %s \n", version.description);
printf("Build number: %s \n", version.buildNumber);
ov_version_free(&version);
// -------- Parsing and validation of input arguments --------
@@ -167,7 +167,7 @@ int main(int argc, char** argv) {
c_mat_t img;
image_read(input_image_path, &img);
ov_element_type_e input_type = U8;
ov_shape_t input_shape = {1, (size_t)img.mat_height, (size_t)img.mat_width, 3};
ov_shape_t input_shape = {4, {1, (size_t)img.mat_height, (size_t)img.mat_width, 3}};
CHECK_STATUS(ov_tensor_create_from_host_ptr(input_type, input_shape, img.mat_data, &tensor));
// -------- Step 4. Configure preprocessing --------

View File

@@ -278,25 +278,42 @@ typedef char ov_layout_t[MAX_DIMENSION];
* @struct ov_shape_t
*/
typedef struct {
int ranks;
size_t rank;
size_t dims[MAX_DIMENSION];
} ov_shape_t;
/**
* @struct ov_PartialShape_t
* @struct ov_partial_shape_t
* brief Class representing a shape that may be partially or totally dynamic.
*
* A PartialShape may have:
* Dynamic rank. (Informal notation: `?`)
* Static rank, but dynamic dimensions on some or all axes.
* (Informal notation examples: `{1,2,?,4}`, `{?,?,?}`)
* Static rank, and static dimensions on all axes.
* (Informal notation examples: `{1,2,3,4}`, `{6}`, `{}`)
*
* An interface to make user can initialize ov_partial_shape_t
*/
typedef struct {
int ranks;
const char *dims[MAX_DIMENSION];
} ov_partial_shape_t;
typedef struct ov_partial_shape ov_partial_shape_t;
/**
* @enum ov_performance_mode_e
* @brief Enum to define possible performance mode hints
* @brief This represents OpenVINO 2.0 ov::hint::PerformanceMode entity.
* It is same with enum class ov::hint::PerformanceMode as below:
*
* enum class PerformanceMode {
* UNDEFINED = -1, //!< Undefined value, performance setting may vary from device to device
* LATENCY = 1, //!< Optimize for latency
* THROUGHPUT = 2, //!< Optimize for throughput
* CUMULATIVE_THROUGHPUT = 3, //!< Optimize for cumulative throughput
* };
*
* There also is a map in C implement to keep it aligned with C++ definition.
*/
typedef enum {
UNDEFINED_MODE = -1, //!< Undefined value, performance setting may vary from device to device
UNDEFINED_MODE = -1, //!< Undefined value, performance setting may vary from device to device
LATENCY = 1, //!< Optimize for latency
THROUGHPUT = 2, //!< Optimize for throughput
CUMULATIVE_THROUGHPUT = 3, //!< Optimize for cumulative throughput
@@ -349,9 +366,17 @@ typedef struct ov_property{
/**
* @brief Initialize a partial shape.
* @param str is the input partial info string
* Dynamic rank:
* Example: "?"
* Static rank, but dynamic dimensions on some or all axes.
* Examples: "{1,2,?,4}" or "{?,?,?}" or "{1,2,-1,4}""
* Static rank, and static dimensions on all axes.
* Examples: "{1,2,3,4}" or "{6}" or "{}""
*
* @param ov_status_e a status code.
*/
OPENVINO_C_API(ov_status_e) ov_partial_shape_init(ov_partial_shape_t* partial_shape, const char* str);
OPENVINO_C_API(ov_status_e) ov_partial_shape_init(ov_partial_shape_t** partial_shape, const char* str);
/**
* @brief Parse the partial shape to readable string.
@@ -509,14 +534,6 @@ OPENVINO_C_API(ov_status_e) ov_core_get_property(const ov_core_t* core, const ch
const ov_property_key_e property_name,
ov_property_value* property_value);
/**
* @brief Registers an extension to a Core object.
* @param core A pointer to the ie_core_t instance.
* @param library_path Path to the library with ov::Extension.
* @return Status code of the operation: OK(0) for success.
*/
OPENVINO_C_API(ov_status_e) ov_core_add_extension(const ov_core_t* core, const char* library_path);
/**
* @brief Returns devices available for inference.
* @param core A pointer to the ie_core_t instance.
@@ -646,9 +663,8 @@ OPENVINO_C_API(bool) ov_model_is_dynamic(const ov_model_t* model);
* @param tensor_name input tensor name (char *).
* @param partialShape A PartialShape.
*/
OPENVINO_C_API(ov_status_e) ov_model_reshape(const ov_model_t* model,
const char* tensor_name,
const ov_partial_shape_t partial_shape);
OPENVINO_C_API(ov_status_e)
ov_model_reshape(const ov_model_t* model, const char* tensor_name, const ov_partial_shape_t* partial_shape);
/**
* @brief Gets the friendly name for a model.
@@ -673,7 +689,7 @@ OPENVINO_C_API(void) ov_output_node_free(ov_output_node_t *output_node);
* @brief free char
* @param content The pointer to the char to free.
*/
OPENVINO_C_API(void) ov_free(char *content);
OPENVINO_C_API(void) ov_free(const char *content);
/**
* @brief Create a ov_preprocess_t instance.

View File

@@ -76,6 +76,11 @@ struct ov_tensor {
std::shared_ptr<ov::Tensor> object;
};
struct ov_partial_shape {
ov::Dimension rank; // Support static rank and dynamic rank
std::vector<ov::Dimension> dims; // Dimemsion vector
};
/**
* @variable global value for error info
*/
@@ -554,7 +559,7 @@ ov_status_e ov_node_get_tensor_shape(ov_output_node_list_t* nodes, size_t idx,
if (shape.size() > MAX_DIMENSION) {
return ov_status_e::GENERAL_ERROR;
}
tensor_shape->ranks = shape.size();
tensor_shape->rank = shape.size();
std::copy_n(shape.begin(), shape.size(), tensor_shape->dims);
} CATCH_OV_EXCEPTIONS
@@ -592,7 +597,7 @@ ov_status_e ov_model_get_input_by_name(const ov_model_t* model,
ov_status_e ov_model_get_input_by_id(const ov_model_t* model,
const size_t index,
ov_output_node_t **input_node) {
if (!model || index < 0 || !input_node) {
if (!model || !input_node) {
return ov_status_e::GENERAL_ERROR;
}
try {
@@ -611,35 +616,75 @@ bool ov_model_is_dynamic(const ov_model_t* model) {
return model->object->is_dynamic();
}
std::vector<char*> split(std::string s) {
std::vector<char*> result;
std::regex delimiter("[,]");
std::sregex_token_iterator tokens(s.cbegin(), s.cend(), delimiter, -1);
std::sregex_token_iterator end;
for (; tokens != end; ++tokens) {
result.push_back(str_to_char_array(*tokens));
std::vector<std::string> split_to_dims(const std::string& partial_shape_str) {
std::vector<std::string> result;
std::regex delimiter("[^{},]+");
auto words_begin = std::sregex_iterator(partial_shape_str.begin(), partial_shape_str.end(), delimiter);
auto words_end = std::sregex_iterator();
for (auto iter = words_begin; iter != words_end; ++iter) {
result.push_back(iter->str());
}
return result;
}
ov_status_e ov_partial_shape_init(ov_partial_shape_t* partial_shape, const char* str) {
if (!partial_shape || !str) {
template <class T>
T str_to_value(const std::string& str) {
T ret{0};
std::istringstream ss(str);
if (!ss.eof()) {
ss >> ret;
}
return ret;
}
ov_status_e ov_partial_shape_init(ov_partial_shape_t** partial_shape_obj, const char* str) {
*partial_shape_obj = nullptr;
if (!str) {
return ov_status_e::GENERAL_ERROR;
}
ov_partial_shape_t* partial_shape = nullptr;
try {
std::string s = str;
std::regex reg("[^,0-9.?][^\\-1]");
std::regex reg("[^,0-9.?}{}][^\\-1]");
bool res = std::regex_search(s, reg);
if (res) {
return ov_status_e::PARAMETER_MISMATCH;
}
std::vector<char*> result = split(s);
partial_shape->ranks = result.size();
if (partial_shape->ranks > MAX_DIMENSION) {
return ov_status_e::GENERAL_ERROR;
partial_shape = new ov_partial_shape_t;
if (s == "?") { // dynamic rank
partial_shape->rank = ov::Dimension::dynamic();
} else { // static rank
std::vector<std::string> result = split_to_dims(s);
using value_type = ov::Dimension::value_type;
size_t cnt = result.size();
if (cnt > MAX_DIMENSION) {
delete partial_shape;
return ov_status_e::GENERAL_ERROR;
}
partial_shape->rank = ov::Dimension(cnt);
for (auto& dim : result) {
if (dim == "?" || dim == "-1") {
partial_shape->dims.emplace_back(ov::Dimension::dynamic());
} else {
const std::string range_divider = "..";
size_t range_index = dim.find(range_divider);
if (range_index != std::string::npos) {
std::string min_str = dim.substr(0, range_index);
std::string max_str = dim.substr(range_index + range_divider.length());
value_type min = min_str.empty() ? 0 : str_to_value<value_type>(min_str);
value_type max = max_str.empty() ? -1 : str_to_value<value_type>(max_str);
partial_shape->dims.emplace_back(min, max);
} else {
partial_shape->dims.emplace_back(str_to_value<value_type>(dim));
}
}
}
}
std::copy_n(result.begin(), result.size(), partial_shape->dims);
} CATCH_OV_EXCEPTIONS
}
CATCH_OV_EXCEPTIONS
*partial_shape_obj = partial_shape;
return ov_status_e::OK;
}
@@ -647,13 +692,28 @@ const char* ov_partial_shape_parse(ov_partial_shape_t* partial_shape) {
if (!partial_shape) {
return str_to_char_array("error");
}
std::string str;
for (int i = 0; i < partial_shape->ranks; ++i) {
std::string tmp = partial_shape->dims[i];
str += tmp;
if (i != partial_shape->ranks - 1)
// dynamic rank
if (partial_shape->rank.is_dynamic()) {
return str_to_char_array("?");
}
// static rank
auto rank = partial_shape->rank.get_length();
if (rank != partial_shape->dims.size()) {
return str_to_char_array("rank error");
}
std::string str = std::string("{");
int i = 0;
for (auto& item : partial_shape->dims) {
std::ostringstream out;
out.str("");
out << item;
str += out.str();
if (i++ < rank - 1)
str += ",";
}
str += std::string("}");
const char* res = str_to_char_array(str);
return res;
}
@@ -662,57 +722,44 @@ ov_status_e ov_partial_shape_to_shape(ov_partial_shape_t* partial_shape, ov_shap
if (!partial_shape || !shape) {
return ov_status_e::GENERAL_ERROR;
}
try {
std::vector<size_t> tmp_shape;
std::regex reg("[^0-9,]");
auto tmp = ov_partial_shape_parse(partial_shape);
std::string dim(tmp);
bool res = std::regex_search(dim, reg);
if (res) {
if (partial_shape->rank.is_dynamic()) {
return ov_status_e::PARAMETER_MISMATCH;
}
for (int i = 0; i < partial_shape->ranks; ++i) {
shape->dims[i] = std::stoi(partial_shape->dims[i]);
auto rank = partial_shape->rank.get_length();
if (rank > MAX_DIMENSION) {
return ov_status_e::PARAMETER_MISMATCH;
}
shape->ranks = partial_shape->ranks;
delete tmp;
} CATCH_OV_EXCEPTIONS
for (auto i = 0; i < rank; ++i) {
auto& ov_dim = partial_shape->dims[i];
if (ov_dim.is_static())
shape->dims[i] = ov_dim.get_length();
else
return ov_status_e::PARAMETER_MISMATCH;
}
shape->rank = rank;
}
CATCH_OV_EXCEPTIONS
return ov_status_e::OK;
}
ov_status_e ov_model_reshape(const ov_model_t* model,
const char* tensor_name,
const ov_partial_shape_t partial_shape) {
if (!model || !tensor_name) {
const char* tensor_name,
const ov_partial_shape_t* partial_shape) {
if (!model || !tensor_name || !partial_shape) {
return ov_status_e::GENERAL_ERROR;
}
try {
std::vector<ngraph::Dimension> shape;
for (int i = 0; i < partial_shape.ranks; i++) {
if (!partial_shape.dims[i])
return ov_status_e::GENERAL_ERROR;
std::string dim = partial_shape.dims[i];
if (dim == "?" || dim == "-1") {
shape.push_back(ov::Dimension::dynamic());
} else {
const std::string range_divider = "..";
size_t range_index = dim.find(range_divider);
if (range_index != std::string::npos) {
std::string min = dim.substr(0, range_index);
std::string max = dim.substr(range_index + range_divider.length());
shape.emplace_back(min.empty() ? 0 : std::stoi(min),
max.empty() ? ngraph::Interval::s_max : std::stoi(max));
} else {
shape.emplace_back(std::stoi(dim));
}
}
std::map<std::string, ov::PartialShape> in_shape;
if (partial_shape->rank.is_static() && (partial_shape->rank.get_length() == partial_shape->dims.size())) {
in_shape[tensor_name] = partial_shape->dims;
} else {
return ov_status_e::PARAMETER_MISMATCH;
}
std::map<std::string, ov::PartialShape> const_pshape;
const_pshape[tensor_name] = shape;
model->object->reshape(const_pshape);
} CATCH_OV_EXCEPTIONS
model->object->reshape(in_shape);
}
CATCH_OV_EXCEPTIONS
return ov_status_e::OK;
}
@@ -738,17 +785,14 @@ void ov_output_node_free(ov_output_node_t *output_node) {
delete output_node;
}
void ov_free(char *content) {
delete content;
void ov_free(const char *content) {
if (content)
delete content;
}
void ov_partial_shape_free(ov_partial_shape_t* partial_shape) {
if (partial_shape) {
std::for_each(&partial_shape->dims[0],
&partial_shape->dims[partial_shape->ranks],
[](const char* n){ delete [] n; });
partial_shape->ranks = 0;
}
if (partial_shape)
delete partial_shape;
}
ov_status_e ov_preprocess_create(const ov_model_t* model,
@@ -1334,7 +1378,7 @@ ov_status_e ov_tensor_create(const ov_element_type_e type, const ov_shape_t shap
*tensor = new ov_tensor_t;
auto tmp_type = GET_OV_ELEMENT_TYPE(type);
ov::Shape tmp_shape;
std::copy_n(shape.dims, shape.ranks, std::back_inserter(tmp_shape));
std::copy_n(shape.dims, shape.rank, std::back_inserter(tmp_shape));
(*tensor)->object = std::make_shared<ov::Tensor>(tmp_type, tmp_shape);
} CATCH_OV_EXCEPTIONS
return ov_status_e::OK;
@@ -1349,7 +1393,7 @@ ov_status_e ov_tensor_create_from_host_ptr(const ov_element_type_e type, const o
*tensor = new ov_tensor_t;
auto tmp_type = GET_OV_ELEMENT_TYPE(type);
ov::Shape tmp_shape;
std::copy_n(shape.dims, shape.ranks, std::back_inserter(tmp_shape));
std::copy_n(shape.dims, shape.rank, std::back_inserter(tmp_shape));
(*tensor)->object = std::make_shared<ov::Tensor>(tmp_type, tmp_shape, host_ptr);
} CATCH_OV_EXCEPTIONS
return ov_status_e::OK;
@@ -1361,7 +1405,7 @@ ov_status_e ov_tensor_set_shape(ov_tensor_t* tensor, const ov_shape_t shape) {
}
try {
ov::Shape tmp_shape;
std::copy_n(shape.dims, shape.ranks, std::back_inserter(tmp_shape));
std::copy_n(shape.dims, shape.rank, std::back_inserter(tmp_shape));
tensor->object->set_shape(tmp_shape);
} CATCH_OV_EXCEPTIONS
return ov_status_e::OK;
@@ -1376,7 +1420,7 @@ ov_status_e ov_tensor_get_shape(const ov_tensor_t* tensor, ov_shape_t* shape) {
if (tmp_shape.size() > MAX_DIMENSION) {
return ov_status_e::GENERAL_ERROR;
}
shape->ranks = tmp_shape.size();
shape->rank = tmp_shape.size();
std::copy_n(tmp_shape.begin(), tmp_shape.size(), shape->dims);
} CATCH_OV_EXCEPTIONS
return ov_status_e::OK;

View File

@@ -190,7 +190,7 @@ TEST(ov_core, ov_core_read_model_from_memory) {
std::vector<uint8_t> weights_content(content_from_file(bin, true));
ov_tensor_t* tensor = nullptr;
ov_shape_t shape = {1, weights_content.size()};
ov_shape_t shape = {2, {1, weights_content.size()}};
OV_ASSERT_OK(ov_tensor_create_from_host_ptr(ov_element_type_e::U8, shape, weights_content.data(), &tensor));
ASSERT_NE(nullptr, tensor);
@@ -553,7 +553,7 @@ TEST(ov_preprocess, ov_preprocess_input_tensor_info_set_tensor) {
ASSERT_NE(nullptr, input_tensor_info);
ov_tensor_t* tensor = nullptr;
ov_shape_t shape = {1, 416, 416, 3};
ov_shape_t shape = {4, {1, 416, 416, 3}};
OV_ASSERT_OK(ov_tensor_create(ov_element_type_e::F32, shape, &tensor));
OV_ASSERT_OK(ov_preprocess_input_tensor_info_set_tensor(input_tensor_info, tensor));
@@ -1330,7 +1330,6 @@ void infer_request_callback(void *args) {
ov_infer_request_t *infer_request = (ov_infer_request_t *)args;
ov_tensor_t *out_tensor = nullptr;
printf("async infer callback...\n");
OV_EXPECT_OK(ov_infer_request_get_out_tensor(infer_request, 0, &out_tensor));
EXPECT_NE(nullptr, out_tensor);
@@ -1378,7 +1377,7 @@ TEST_P(ov_infer_request, get_profiling_info) {
TEST(ov_tensor, ov_tensor_create) {
ov_element_type_e type = ov_element_type_e::U8;
ov_shape_t shape = {10, 20, 30, 40};
ov_shape_t shape = {4, {10, 20, 30, 40}};
ov_tensor_t* tensor = nullptr;
OV_EXPECT_OK(ov_tensor_create(type, shape, &tensor));
EXPECT_NE(nullptr, tensor);
@@ -1387,7 +1386,7 @@ TEST(ov_tensor, ov_tensor_create) {
TEST(ov_tensor, ov_tensor_create_from_host_ptr) {
ov_element_type_e type = ov_element_type_e::U8;
ov_shape_t shape = {1, 3, 4, 4};
ov_shape_t shape = {4, {1, 3, 4, 4}};
uint8_t host_ptr[1][3][4][4]= {0};
ov_tensor_t* tensor = nullptr;
OV_EXPECT_OK(ov_tensor_create_from_host_ptr(type, shape, &host_ptr,&tensor));
@@ -1404,7 +1403,7 @@ TEST(ov_tensor, ov_tensor_get_shape) {
ov_shape_t shape_res = {0,{0}};
OV_EXPECT_OK(ov_tensor_get_shape(tensor, &shape_res));
EXPECT_EQ(shape.ranks, shape_res.ranks);
EXPECT_EQ(shape.rank, shape_res.rank);
OV_EXPECT_ARREQ(shape.dims, shape_res.dims);
ov_tensor_free(tensor);
@@ -1421,7 +1420,7 @@ TEST(ov_tensor, ov_tensor_set_shape) {
OV_EXPECT_OK(ov_tensor_set_shape(tensor, shape_update));
ov_shape_t shape_res = {0,{0}};
OV_EXPECT_OK(ov_tensor_get_shape(tensor, &shape_res));
EXPECT_EQ(shape_update.ranks, shape_res.ranks);
EXPECT_EQ(shape_update.rank, shape_res.rank);
OV_EXPECT_ARREQ(shape_update.dims, shape_res.dims);
ov_tensor_free(tensor);
@@ -1429,7 +1428,7 @@ TEST(ov_tensor, ov_tensor_set_shape) {
TEST(ov_tensor, ov_tensor_get_element_type) {
ov_element_type_e type = ov_element_type_e::U8;
ov_shape_t shape = {10, 20, 30, 40};
ov_shape_t shape = {4, {10, 20, 30, 40}};
ov_tensor_t* tensor = nullptr;
OV_EXPECT_OK(ov_tensor_create(type, shape, &tensor));
EXPECT_NE(nullptr, tensor);
@@ -1449,7 +1448,7 @@ static size_t product(const std::vector<size_t>& dims) {
size_t calculate_size(ov_shape_t shape) {
std::vector<size_t> tmp_shape;
std::copy_n(shape.dims, shape.ranks, std::back_inserter(tmp_shape));
std::copy_n(shape.dims, shape.rank, std::back_inserter(tmp_shape));
return product(tmp_shape);
}
@@ -1459,7 +1458,7 @@ size_t calculate_byteSize(ov_shape_t shape, ov_element_type_e type) {
TEST(ov_tensor, ov_tensor_get_size) {
ov_element_type_e type = ov_element_type_e::I16;
ov_shape_t shape = {1, 3, 4, 4};
ov_shape_t shape = {4, {1, 3, 4, 4}};
ov_tensor_t* tensor = nullptr;
OV_EXPECT_OK(ov_tensor_create(type, shape, &tensor));
EXPECT_NE(nullptr, tensor);
@@ -1474,7 +1473,7 @@ TEST(ov_tensor, ov_tensor_get_size) {
TEST(ov_tensor, ov_tensor_get_byte_size) {
ov_element_type_e type = ov_element_type_e::I16;
ov_shape_t shape = {1, 3, 4, 4};
ov_shape_t shape = {4, {1, 3, 4, 4}};
ov_tensor_t* tensor = nullptr;
OV_EXPECT_OK(ov_tensor_create(type, shape, &tensor));
EXPECT_NE(nullptr, tensor);
@@ -1489,7 +1488,7 @@ TEST(ov_tensor, ov_tensor_get_byte_size) {
TEST(ov_tensor, ov_tensor_get_data) {
ov_element_type_e type = ov_element_type_e::U8;
ov_shape_t shape = {10, 20, 30, 40};
ov_shape_t shape = {4, {10, 20, 30, 40}};
ov_tensor_t *tensor = nullptr;
OV_EXPECT_OK(ov_tensor_create(type, shape, &tensor));
EXPECT_NE(nullptr, tensor);
@@ -1607,13 +1606,11 @@ TEST(ov_model, ov_model_reshape) {
char* tensor_name = nullptr;
OV_ASSERT_OK(ov_node_get_tensor_name(&input_node_list1, 0, &tensor_name));
const char* str = "1,3,896,896";
const char* str = "{1,3,896,896}";
ov_partial_shape_t* partial_shape;
partial_shape = new ov_partial_shape_t;
partial_shape->ranks = 0;
OV_ASSERT_OK(ov_partial_shape_init(partial_shape,str));
OV_ASSERT_OK(ov_model_reshape(model, tensor_name, *partial_shape));
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
OV_ASSERT_OK(ov_model_reshape(model, tensor_name, partial_shape));
ov_output_node_list_t input_node_list2;
input_node_list2.output_nodes = nullptr;
@@ -1622,6 +1619,7 @@ TEST(ov_model, ov_model_reshape) {
EXPECT_NE(input_node_list1.output_nodes, input_node_list2.output_nodes);
ov_partial_shape_free(partial_shape);
ov_free(tensor_name);
ov_output_node_list_free(&input_node_list1);
ov_output_node_list_free(&input_node_list2);
@@ -1648,71 +1646,120 @@ TEST(ov_model, ov_model_get_friendly_name) {
}
TEST(ov_partial_shape, ov_partial_shape_init_and_parse) {
const char* str = "1,2,3,4..5";
const char* str = "{1,20,300,40..100}";
ov_partial_shape_t* partial_shape = nullptr;
ov_partial_shape_t partial_shape;
partial_shape.ranks = 0;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape,str));
auto tmp = ov_partial_shape_parse(&partial_shape);
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
auto tmp = ov_partial_shape_parse(partial_shape);
EXPECT_STREQ(tmp, str);
delete tmp;
ov_partial_shape_free(&partial_shape);
ov_free(tmp);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_init_and_parse_dynamic) {
const char* str = "{1,?,300,40..100}";
ov_partial_shape_t* partial_shape = nullptr;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
auto tmp = ov_partial_shape_parse(partial_shape);
EXPECT_STREQ(tmp, str);
ov_free(tmp);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_init_and_parse_dynamic_mix) {
const char* str = "{1,?,?,40..100}";
ov_partial_shape_t* partial_shape = nullptr;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
auto tmp = ov_partial_shape_parse(partial_shape);
EXPECT_STREQ(tmp, str);
ov_free(tmp);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_init_and_parse_dynamic_mix_2) {
const char* str = "{1,?,-1,40..100}";
ov_partial_shape_t* partial_shape = nullptr;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
auto tmp = ov_partial_shape_parse(partial_shape);
ov_partial_shape_t* partial_shape2 = nullptr;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape2, tmp));
auto tmp2 = ov_partial_shape_parse(partial_shape);
EXPECT_STREQ(tmp, tmp2);
ov_free(tmp);
ov_free(tmp2);
ov_partial_shape_free(partial_shape);
ov_partial_shape_free(partial_shape2);
}
TEST(ov_partial_shape, ov_partial_shape_init_and_parse_dynamic_rank) {
const char* str = "?";
ov_partial_shape_t* partial_shape = nullptr;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
auto tmp = ov_partial_shape_parse(partial_shape);
EXPECT_STREQ(tmp, str);
ov_free(tmp);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_init_and_parse_invalid) {
const char* str = "1,2+3;4..5";
const char* str = "{1,2+3;4..5}";
ov_partial_shape_t* partial_shape = nullptr;
ov_partial_shape_t partial_shape;
partial_shape.ranks = 0;
OV_EXPECT_NOT_OK(ov_partial_shape_init(&partial_shape, str));
OV_EXPECT_NOT_OK(ov_partial_shape_init(&partial_shape,str));
ov_partial_shape_free(&partial_shape);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_to_shape) {
const char* str = "1,2,3,4,5";
const char* str = "{10,20,30,40,50}";
ov_partial_shape_t* partial_shape = nullptr;
ov_partial_shape_t partial_shape;
partial_shape.ranks = 0;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape,str));
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
ov_shape_t shape;
shape.ranks = 0;
OV_ASSERT_OK(ov_partial_shape_to_shape(&partial_shape, &shape));
shape.rank = 0;
OV_ASSERT_OK(ov_partial_shape_to_shape(partial_shape, &shape));
EXPECT_EQ(shape.rank, 5);
EXPECT_EQ(shape.dims[0], 10);
EXPECT_EQ(shape.dims[1], 20);
EXPECT_EQ(shape.dims[2], 30);
EXPECT_EQ(shape.dims[3], 40);
EXPECT_EQ(shape.dims[4], 50);
ov_partial_shape_free(&partial_shape);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_to_shape_invalid_num) {
const char* str = "-1,2,3,4,5";
const char* str = "{-1,2,3,4,5}";
ov_partial_shape_t* partial_shape = nullptr;
ov_partial_shape_t partial_shape;
partial_shape.ranks = 0;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape,str));
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
ov_shape_t shape;
shape.ranks = 0;
OV_EXPECT_NOT_OK(ov_partial_shape_to_shape(&partial_shape, &shape));
shape.rank = 0;
OV_EXPECT_NOT_OK(ov_partial_shape_to_shape(partial_shape, &shape));
ov_partial_shape_free(&partial_shape);
ov_partial_shape_free(partial_shape);
}
TEST(ov_partial_shape, ov_partial_shape_to_shape_invalid_sign) {
const char* str = "1,2,3,4..5";
const char* str = "{1,2,3,4..5}";
ov_partial_shape_t* partial_shape = nullptr;
ov_partial_shape_t partial_shape;
partial_shape.ranks = 0;
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape,str));
OV_ASSERT_OK(ov_partial_shape_init(&partial_shape, str));
ov_shape_t shape;
shape.ranks = 0;
OV_EXPECT_NOT_OK(ov_partial_shape_to_shape(&partial_shape, &shape));
shape.rank = 0;
OV_EXPECT_NOT_OK(ov_partial_shape_to_shape(partial_shape, &shape));
ov_partial_shape_free(&partial_shape);
ov_partial_shape_free(partial_shape);
}