Skip to content

Commit a1e9a25

Browse files
committed
CM: String & memory set functions added
Also includes: * Associated unittests.
1 parent 1e76469 commit a1e9a25

File tree

5 files changed

+209
-0
lines changed

5 files changed

+209
-0
lines changed

include/cm/cm.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,11 @@ static inline void* cm_process_get_datamem_start()
6363
typedef void (*cm_event_handler)(OSIF_ProcessEvent const * const);
6464
bool cm_process_register_event_handler(OSIF_ProcessEvents event, cm_event_handler h);
6565
bool cm_process_handle_events();
66+
67+
/***************************************************************************************************
68+
* String and memory functions
69+
***************************************************************************************************/
70+
void* cm_memcpy (void* dest, const void* src, size_t n);
71+
UINT cm_strlen (const char* s);
72+
char* cm_strncpy (char* d, const char* s, SIZE n);
73+
void* cm_memset (void* const s, U8 c, size_t n);

src/cm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ set(APPLIB_SOURCES
2626
${CMAKE_CURRENT_SOURCE_DIR}/printf.c
2727
${CMAKE_CURRENT_SOURCE_DIR}/debug.c
2828
${CMAKE_CURRENT_SOURCE_DIR}/cm.c
29+
${CMAKE_CURRENT_SOURCE_DIR}/string.c
2930
)
3031

3132
if (MOS_GRAPHICS_ENABLED)

src/cm/string.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* -------------------------------------------------------------------------------------------------
3+
* Megha Operating System V2 - App Library - String/Memory functions
4+
* -------------------------------------------------------------------------------------------------
5+
*/
6+
7+
#include <cm/types.h>
8+
9+
/***************************************************************************************************
10+
* Copies n bytes from src to dest. Can handle overlaps.
11+
*
12+
* @Input dest Pointer to the destination. Should not be NULL.
13+
* @Input src Pointer to the source. Should not be NULL.
14+
* @Input n Number of bytes to copy.
15+
* @return Pointer to the start of the destination.
16+
***************************************************************************************************/
17+
void* cm_memcpy (void* dest, const void* src, size_t n)
18+
{
19+
U8* cdest = (U8*)dest;
20+
U8* csrc = (U8*)src;
21+
22+
// This handles the scenario where destination overlaps the source.
23+
cdest += n - 1;
24+
csrc += n - 1;
25+
26+
while (n--)
27+
*cdest-- = *csrc--;
28+
29+
return (CHAR*)dest;
30+
}
31+
32+
/***************************************************************************************************
33+
* Gets lenght of a NULL terminated string.
34+
*
35+
* @Input s Pointer to NULL terminated string
36+
* @return Length of the string not including the NULL character.
37+
* TODO: Make the implementation mode efficient
38+
***************************************************************************************************/
39+
UINT cm_strlen (const char* s)
40+
{
41+
UINT len = 0;
42+
for (; *s != '\0'; len++, s++)
43+
;
44+
45+
return len;
46+
}
47+
48+
/***************************************************************************************************
49+
* Copies at most 'n' characters from one string to another.
50+
*
51+
* @Input d Destination
52+
* @Input s Source
53+
* @Input n Number of characters (bytes) to copy from destination to source.
54+
* @return Pointer to destination
55+
***************************************************************************************************/
56+
char* cm_strncpy (char* d, const char* s, SIZE n)
57+
{
58+
char* dh = d;
59+
for (; n > 0 && (*d = *s) != '\0'; s++, d++, n--)
60+
;
61+
62+
return dh;
63+
}
64+
65+
/***************************************************************************************************
66+
* Fills memory with constant byte
67+
*
68+
* @Input s Pointer to the destination. Should not be NULL.
69+
* @Input c Byte to fill the destination with.
70+
* @Input n Number of bytes to fill.
71+
* @return Pointer to the start of the destination.
72+
***************************************************************************************************/
73+
void* cm_memset (void* const s, U8 c, size_t n)
74+
{
75+
return __builtin_memset (s, c, n);
76+
}

src/unittests/cm/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,12 @@ test(
88
${PROJECT_SOURCE_DIR}/src/unittests/unittest.c
99
${CMAKE_CURRENT_SOURCE_DIR}/printf_test.c
1010
)
11+
12+
test(
13+
NAME cm_string_test
14+
DEPENDENT_FOR build-all
15+
SOURCES
16+
${PROJECT_SOURCE_DIR}/src/cm/string.c
17+
${PROJECT_SOURCE_DIR}/src/unittests/unittest.c
18+
${CMAKE_CURRENT_SOURCE_DIR}/string_test.c
19+
)

src/unittests/cm/string_test.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#include <cm/types.h>
2+
#include <cm/cm.h>
3+
#include <unittest/unittest.h>
4+
#include <mock/kernel/paging.h>
5+
6+
extern bool panic_invoked;
7+
8+
TEST (MEM, memset_one_byte)
9+
{
10+
U8 dest;
11+
EQ_SCALAR ((PTR)cm_memset (&dest, 0x1A, 1), (PTR)&dest);
12+
EQ_SCALAR (dest, 0x1A);
13+
END();
14+
}
15+
16+
TEST (STRING, string_length)
17+
{
18+
EQ_SCALAR (cm_strlen (""), 0);
19+
EQ_SCALAR (cm_strlen ("ABCD"), 4);
20+
EQ_SCALAR (cm_strlen ("A\n\tB"), 4);
21+
END();
22+
}
23+
24+
TEST (STRING, string_copy)
25+
{
26+
char destination[10];
27+
char* source = NULL;
28+
29+
// Copy empty string
30+
source = "";
31+
EQ_SCALAR ((PTR)cm_strncpy (destination, source, ARRAY_LENGTH (destination)), (PTR)destination);
32+
EQ_STRING (source, destination);
33+
34+
// Copy < size of destination
35+
source = "ABC";
36+
EQ_SCALAR ((PTR)cm_strncpy (destination, source, ARRAY_LENGTH (destination)), (PTR)destination);
37+
EQ_STRING (source, destination);
38+
39+
//// Copy = size of destination
40+
source = "123456789";
41+
EQ_SCALAR ((PTR)cm_strncpy (destination, source, ARRAY_LENGTH (destination)), (PTR)destination);
42+
EQ_STRING (source, destination);
43+
44+
//// Copy > size of destination
45+
// source = "123456789ABCD";
46+
EQ_SCALAR ((PTR)cm_strncpy (destination, source, ARRAY_LENGTH (destination)), (PTR)destination);
47+
EQ_STRING ("123456789", destination); // Not more than size of destination is copied.
48+
END();
49+
}
50+
51+
TEST (MEM, memcpy_overlap)
52+
{
53+
// Here is the memory layout for this test;
54+
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 < byte indices]
55+
// |-----------------| <src]
56+
// 1 2 3 4 5 6 7 8 9 10 <src contents before copy]
57+
// |----------------------| <dest]
58+
// 1 2 3 4 5 6 7 8 9 10 <dest contents after copy]
59+
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 < byte indices]
60+
61+
U8 memory[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
62+
CHAR* src = &memory[0];
63+
CHAR* dest = &memory[5];
64+
65+
EQ_SCALAR ((PTR)cm_memcpy (dest, src, 10), (PTR)dest);
66+
67+
for (int i = 0; i < 10; i++)
68+
EQ_SCALAR (dest[i], i + 1); // Dest[0 to 9] has 1 to 10
69+
70+
for (int i = 0; i < 5; i++) {
71+
EQ_SCALAR (src[i], i + 1); // Src[0 to 4] has 1 to 5
72+
EQ_SCALAR (src[i + 5], i + 1); // Src[5 to 9] has 1 to 5
73+
}
74+
75+
END();
76+
}
77+
78+
TEST (MEM, memcpy_normal)
79+
{
80+
CHAR* src = "123456789ABCDEF0";
81+
CHAR dest[10];
82+
83+
EQ_SCALAR ((PTR)cm_memcpy (dest, src, ARRAY_LENGTH (dest)), (PTR)&dest);
84+
85+
for (int i = 0; i < ARRAY_LENGTH (dest); i++)
86+
EQ_SCALAR (dest[i], src[i]);
87+
88+
END();
89+
}
90+
91+
TEST (MEM, memset_normal)
92+
{
93+
U8 dest[10];
94+
95+
EQ_SCALAR ((PTR)cm_memset (dest, 0x1A, ARRAY_LENGTH (dest)), (PTR)&dest);
96+
97+
for (int i = 0; i < ARRAY_LENGTH (dest); i++)
98+
EQ_SCALAR (dest[i], 0x1A);
99+
100+
END();
101+
}
102+
103+
void reset()
104+
{
105+
}
106+
107+
int main()
108+
{
109+
memset_one_byte();
110+
memset_normal();
111+
memcpy_normal();
112+
memcpy_overlap();
113+
string_length();
114+
string_copy();
115+
}

0 commit comments

Comments
 (0)