Skip to content

Commit f421142

Browse files
committed
Implement map that is MISRA compliant
- MISRA compliant map
1 parent 67a5ed9 commit f421142

File tree

5 files changed

+289
-0
lines changed

5 files changed

+289
-0
lines changed

Inc/map.h

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2023 IMProject Development Team. All rights reserved.
4+
* Authors: Juraj Ciberlin <[email protected]>
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions
8+
* are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in
14+
* the documentation and/or other materials provided with the
15+
* distribution.
16+
* 3. Neither the name IMProject nor the names of its contributors may be
17+
* used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+
* POSSIBILITY OF SUCH DAMAGE.
32+
*
33+
****************************************************************************/
34+
35+
#ifndef UTILITY_MAP_H_
36+
#define UTILITY_MAP_H_
37+
38+
#include "typedefs.h"
39+
40+
typedef struct {
41+
byte_t* keys;
42+
byte_t* values;
43+
int32_t key_size;
44+
int32_t value_size;
45+
int32_t max_map_size;
46+
int32_t current_size;
47+
bool initialized;
48+
} Map_t;
49+
50+
/**
51+
* @brief Initialize map.
52+
*
53+
* @param[out] *map Pointer to the map (type Map_t).
54+
* @param[in] *keys Pointer to keys in the map.
55+
* @param[in] *values Pointer to values in the map.
56+
* @param[in] key_size Size of the key in the map.
57+
* @param[in] value_size Size of the value in the map.
58+
* @param[in] max_map_size Max size of the map.
59+
*
60+
* @return True if map is successfully initialized, otherwise false.
61+
*/
62+
bool Map_initMap(Map_t* map, byte_t* keys, byte_t* values, int32_t key_size, int32_t value_size,
63+
int32_t max_map_size);
64+
65+
/**
66+
* @brief Insert new element in the map.
67+
*
68+
* @param[in/out] *map Pointer to the map (type Map_t).
69+
* @param[in] *key Pointer to the key that will be inserted in the map.
70+
* @param[in] *value Pointer to the value that will be inserted in the map.
71+
*
72+
* @return True if new element is successfully inserted in the map, otherwise false.
73+
*/
74+
bool Map_insert(Map_t* map, const byte_t* key, const byte_t* value);
75+
76+
/**
77+
* @brief Get a value from the map using the key.
78+
*
79+
* @param[in] *map Pointer to the map (type Map_t).
80+
* @param[in] *key Pointer to the key.
81+
* @param[out] *value Pointer to the value that is mapped with the particular key.
82+
*
83+
* @return True if the value is successfully gotten using the key, otherwise false.
84+
*/
85+
bool Map_getValue(const Map_t* map, const byte_t* key, byte_t* value);
86+
87+
#endif /* UTILITY_MAP_H_ */

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ IMUTILITY_FILES=\
107107
Src/crc/crc32_variants/crc32_xfer.c \
108108
Src/heap_sort.c \
109109
Src/json.c \
110+
Src/map.c \
110111
Src/priority_queue.c \
111112
Src/queue.c \
112113
Src/scheduler.c \
@@ -124,6 +125,7 @@ SRC_FILES+=$(IMUTILITY_FILES) \
124125
Tests/test_crc32.c \
125126
Tests/test_heap_sort.c \
126127
Tests/test_json.c \
128+
Tests/test_map.c \
127129
Tests/test_priority_queue.c \
128130
Tests/test_queue.c \
129131
Tests/test_scheduler.c \

Src/map.c

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2023 IMProject Development Team. All rights reserved.
4+
* Authors: Juraj Ciberlin <[email protected]>
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions
8+
* are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in
14+
* the documentation and/or other materials provided with the
15+
* distribution.
16+
* 3. Neither the name IMProject nor the names of its contributors may be
17+
* used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+
* POSSIBILITY OF SUCH DAMAGE.
32+
*
33+
****************************************************************************/
34+
35+
#include "map.h"
36+
37+
#include <string.h>
38+
39+
#define INDEX_NOT_FOUND (-1)
40+
41+
static int32_t
42+
Map_findIndex(const Map_t* map, const byte_t* key, int32_t size) {
43+
int32_t index = INDEX_NOT_FOUND;
44+
for (int32_t i = 0; i < size; ++i) {
45+
if (memcmp(&map->keys[i * map->key_size], key, (size_t)map->key_size) == 0) {
46+
index = i;
47+
break;
48+
}
49+
}
50+
return index;
51+
}
52+
53+
bool
54+
Map_initMap(Map_t* map, byte_t* keys, byte_t* values, int32_t key_size, int32_t value_size,
55+
int32_t max_map_size) {
56+
bool status = false;
57+
if ((key_size != 0) && (value_size != 0) && (max_map_size != 0) && (keys != NULL_PTR) && (values != NULL_PTR)) {
58+
map->keys = keys;
59+
map->values = values;
60+
map->key_size = key_size;
61+
map->value_size = value_size;
62+
map->max_map_size = max_map_size;
63+
map->current_size = 0;
64+
map->initialized = true;
65+
status = true;
66+
}
67+
return status;
68+
}
69+
70+
bool
71+
Map_insert(Map_t* map, const byte_t* key, const byte_t* value) {
72+
bool status = false;
73+
if ((map != NULL_PTR) && (map->initialized)) {
74+
int32_t index = Map_findIndex(map, key, map->current_size);
75+
if (index == INDEX_NOT_FOUND) {
76+
if (map->current_size != map->max_map_size) {
77+
// cppcheck-suppress misra-c2012-17.7; return value is not needed in this case
78+
memcpy(&map->keys[map->current_size * map->key_size], key, (size_t)map->key_size);
79+
// cppcheck-suppress misra-c2012-17.7; return value is not needed in this case
80+
memcpy(&map->values[map->current_size * map->value_size], value, (size_t)map->value_size);
81+
++map->current_size;
82+
status = true;
83+
}
84+
} else {
85+
// cppcheck-suppress misra-c2012-17.7; return value is not needed in this case
86+
memcpy(&map->values[index * map->value_size], value, (size_t)map->value_size);
87+
status = true;
88+
}
89+
}
90+
return status;
91+
}
92+
93+
bool
94+
Map_getValue(const Map_t* map, const byte_t* key, byte_t* value) {
95+
bool status = false;
96+
if ((map != NULL_PTR) && (map->initialized)) {
97+
int32_t index = Map_findIndex(map, key, map->current_size);
98+
if (index != INDEX_NOT_FOUND) {
99+
// cppcheck-suppress misra-c2012-17.7; return value is not needed in this case
100+
memcpy(value, &map->values[index * map->value_size], (size_t)map->value_size);
101+
status = true;
102+
}
103+
}
104+
return status;
105+
}

Tests/test_main.c

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ RunAllTests(void) {
1010
RUN_TEST_GROUP(Crc32);
1111
RUN_TEST_GROUP(HeapSort);
1212
RUN_TEST_GROUP(Json);
13+
RUN_TEST_GROUP(Map);
1314
RUN_TEST_GROUP(PriorityQueue);
1415
RUN_TEST_GROUP(Queue);
1516
RUN_TEST_GROUP(Scheduler);

Tests/test_map.c

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#include "map.h"
2+
3+
#include <string.h>
4+
5+
#include "unity.h"
6+
#include "unity_fixture.h"
7+
8+
TEST_GROUP(Map);
9+
10+
TEST_SETUP(Map) {
11+
}
12+
13+
TEST_TEAR_DOWN(Map) {
14+
}
15+
16+
TEST_GROUP_RUNNER(Map) {
17+
RUN_TEST_CASE(Map, Map_uint32_key_char_value);
18+
RUN_TEST_CASE(Map, Map_int32_key_fp32_value);
19+
RUN_TEST_CASE(Map, Map_negative_cases);
20+
}
21+
22+
TEST(Map, Map_uint32_key_char_value) {
23+
uint32_t keys[100];
24+
char values[100][50];
25+
Map_t map;
26+
TEST_ASSERT_TRUE(Map_initMap(&map, (byte_t*)keys, (byte_t*)values, sizeof(keys[0]), sizeof(values[0]),
27+
sizeof(keys) / sizeof(keys[0])));
28+
29+
uint32_t key = 2U;
30+
char value1[] = "Value1";
31+
TEST_ASSERT_TRUE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value1));
32+
key = 3U;
33+
char value2[] = "Value2";
34+
TEST_ASSERT_TRUE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value2));
35+
36+
char foundValue[50];
37+
key = 2U;
38+
TEST_ASSERT_TRUE(Map_getValue(&map, (byte_t*)&key, (byte_t*)&foundValue));
39+
TEST_ASSERT_TRUE(0 == strcmp(&foundValue[0], "Value1"));
40+
}
41+
42+
TEST(Map, Map_int32_key_fp32_value) {
43+
int32_t keys[2];
44+
float32_t values[2];
45+
Map_t map;
46+
TEST_ASSERT_TRUE(Map_initMap(&map, (byte_t*)keys, (byte_t*)values, sizeof(keys[0]), sizeof(values[0]),
47+
sizeof(keys) / sizeof(keys[0])));
48+
49+
int32_t key = 1;
50+
float32_t value = 10.5F;
51+
TEST_ASSERT_TRUE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value));
52+
key = 2;
53+
value = 15.4F;
54+
TEST_ASSERT_TRUE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value));
55+
56+
float32_t foundValue;
57+
TEST_ASSERT_TRUE(Map_getValue(&map, (byte_t*)&key, (byte_t*)&foundValue));
58+
TEST_ASSERT_EQUAL_FLOAT(foundValue, 15.4F);
59+
60+
value = 300.1F;
61+
TEST_ASSERT_TRUE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value));
62+
TEST_ASSERT_TRUE(Map_getValue(&map, (byte_t*)&key, (byte_t*)&foundValue));
63+
TEST_ASSERT_EQUAL_FLOAT(foundValue, 300.1F);
64+
65+
key = 10;
66+
TEST_ASSERT_FALSE(Map_getValue(&map, (byte_t*)&key, (byte_t*)&foundValue));
67+
68+
TEST_ASSERT_FALSE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value));
69+
}
70+
71+
TEST(Map, Map_negative_cases) {
72+
int32_t keys[5];
73+
float32_t values[5];
74+
Map_t map;
75+
76+
TEST_ASSERT_FALSE(Map_initMap(&map, (byte_t*)keys, (byte_t*)values, 0, sizeof(values[0]),
77+
sizeof(keys) / sizeof(keys[0])));
78+
TEST_ASSERT_FALSE(Map_initMap(&map, (byte_t*)keys, (byte_t*)values, sizeof(keys[0]), 0,
79+
sizeof(keys) / sizeof(keys[0])));
80+
TEST_ASSERT_FALSE(Map_initMap(&map, (byte_t*)keys, (byte_t*)values, sizeof(keys[0]), sizeof(values[0]),
81+
0));
82+
TEST_ASSERT_FALSE(Map_initMap(&map, NULL_PTR, (byte_t*)values, sizeof(keys[0]), sizeof(values[0]),
83+
sizeof(keys) / sizeof(keys[0])));
84+
TEST_ASSERT_FALSE(Map_initMap(&map, (byte_t*)keys, NULL_PTR, sizeof(keys[0]), sizeof(values[0]),
85+
sizeof(keys) / sizeof(keys[0])));
86+
87+
int32_t key = 1;
88+
float32_t value = 10.5F;
89+
TEST_ASSERT_FALSE(Map_insert(&map, (byte_t*)&key, (byte_t*)&value));
90+
TEST_ASSERT_FALSE(Map_insert(NULL_PTR, (byte_t*)&key, (byte_t*)&value));
91+
92+
TEST_ASSERT_FALSE(Map_getValue(&map, (byte_t*)&key, (byte_t*)&value));
93+
TEST_ASSERT_FALSE(Map_getValue(NULL_PTR, (byte_t*)&key, (byte_t*)&value));
94+
}

0 commit comments

Comments
 (0)