amath/src/clib/amathc.3

513 lines
12 KiB
Groff

.TH "amath/amathc.h" 3 "Wed Mar 1 2017" "Version 1.7.1" "amath" \" -*- nroff -*-
.ad l
.nh
.SH NAME
amathc.h \- C functions for manipulating strings and memory
.SH SYNOPSIS
.br
.PP
\fC#include <stddef\&.h>\fP
.br
\fC#include 'amath\&.h'\fP
.br
.SS "Classes"
.in +1c
.ti -1c
.RI "struct \fBtexttag\fP"
.br
.in -1c
.SS "Functions"
.in +1c
.ti -1c
.RI "void * \fBAllocMemSafe\fP (size_t)"
.br
.RI "\fIAllocate memory and add it to the global memory list\&. \fP"
.ti -1c
.RI "void \fBFreeMemSafe\fP (void *)"
.br
.RI "\fIDeallocate memory from the global memory list\&. \fP"
.ti -1c
.RI "void \fBFreeAllSafe\fP ()"
.br
.RI "\fIDeallocate all memory in the global memory list\&. \fP"
.ti -1c
.RI "void \fBMemUsage\fP (long *, long *, long *)"
.br
.RI "\fIGet memory usage in the global memory list\&. \fP"
.ti -1c
.RI "int \fBStrLen\fP (const char *string)"
.br
.RI "\fIGet the length of a null terminated string\&. \fP"
.ti -1c
.RI "\fBbool\fP \fBStrIsEqual\fP (const char *s1, const char *s2)"
.br
.RI "\fICompare two null terminated strings to each other\&. \fP"
.ti -1c
.RI "void \fBMemSet\fP (void *destination, int c0, unsigned int length)"
.br
.RI "\fIFill block of memory with a constant value\&. \fP"
.ti -1c
.RI "void \fBMemCopy\fP (void *destination, const void *source, unsigned int length)"
.br
.RI "\fICopy a block of memory, handling overlap\&. \fP"
.ti -1c
.RI "unsigned int \fBAllocAndCopy\fP (char **destination, const char *source)"
.br
.RI "\fIAllocate memory and copy a string into the array\&. \fP"
.ti -1c
.RI "void \fBUntag\fP (char *destination, const char *source, \fBtexttag\fP tags[], unsigned int tagcount)"
.br
.in -1c
.SH "Detailed Description"
.PP
C functions for manipulating strings and memory\&.
.PP
Definition in file \fBamathc\&.h\fP\&.
.SH "Function Documentation"
.br
.PP
.SS "unsigned int AllocAndCopy (char ** destination, const char * source)"
.br
.PP
Allocate memory and copy a string into the array\&.
.PP
Definition at line 40 of file alloccpy\&.c\&.
.PP
.nf
41 {
42 char *i, *s, *d;
43 unsigned int n, size;
44
45 if (source == nullptr)
46 {
47 *destination = nullptr;
48 return 0;
49 }
50
51 i = (char*)source;
52 s = (char*)source;
53 while (*i)
54 i++;
55
56 n = (unsigned int)(i - s + 1);
57 size = n;
58 *destination = AllocMemSafe(size);
59 d = *destination;
60
64 while (n--)
65 *d++ = *s++;
67
68 return size;
69 }
.fi
.SS "void* AllocMemSafe (size_t)"
.PP
Allocate memory and add it to the global memory list\&.
.PP
Definition at line 86 of file mem\&.c\&.
.PP
.nf
87 {
88 struct MemoryBlock* newblock;
89 size_t allocsize;
90
91 if (list == nullptr)
92 {
93 list = (struct MemoryList*)ALLOC_MEM(sizeof(struct MemoryList));
94 if (!list)
95 {
96 alloc_error("list", sizeof(struct MemoryList));
97 return 0;
98 }
99
100 list->first = nullptr;
101 list->peak = 0;
102 list->size = 0;
103 list->count = 0;
104 }
105
106 #ifdef P64BIT
107 // Align to bytes of 8
108 allocsize = (size + 7) & ~0x07;
109 #else
110 // Align to bytes of 4
111 allocsize = (size + 3) & ~0x03;
112 #endif
113
114 newblock = (struct MemoryBlock*)ALLOC_MEM(sizeof(struct MemoryBlock));
115 if (!newblock)
116 {
117 alloc_error("block", sizeof(struct MemoryBlock));
118 return 0;
119 }
120
121 newblock->address = (struct MemoryBlock*)ALLOC_MEM(allocsize);
122 if (!newblock->address)
123 {
124 FREE_MEM(newblock);
125 alloc_error("memory", allocsize);
126 return 0;
127 }
128
129 newblock->size = allocsize;
130 newblock->next = list->first;
131 list->first = newblock;
132 list->size += allocsize;
133 list->count++;
134
135 if (list->size > list->peak)
136 {
137 list->peak = list->size;
138 }
139
140 // Memory allocated
141 return newblock->address;
142 }
.fi
.SS "void FreeAllSafe ()"
.PP
Deallocate all memory in the global memory list\&.
.PP
Definition at line 199 of file mem\&.c\&.
.PP
.nf
200 {
201 struct MemoryBlock *current, *next;
202
203 if (list == nullptr)
204 {
205 return;
206 }
207
208 current = list->first;
209 while (current != nullptr)
210 {
211 next = current->next;
212 FREE_MEM(current->address);
213 FREE_MEM(current);
214 current = next;
215 }
216
217 FREE_MEM(list);
218 list = nullptr;
219 }
.fi
.SS "void FreeMemSafe (void *)"
.PP
Deallocate memory from the global memory list\&.
.PP
Definition at line 147 of file mem\&.c\&.
.PP
.nf
148 {
149 struct MemoryBlock *current, *previous;
150
151 if (list == nullptr || block == nullptr)
152 {
153 dealloc_error("list", 0);
154 return;
155 }
156
157 if (block == nullptr)
158 {
159 dealloc_error("memory", 0);
160 return;
161 }
162
163 previous = nullptr;
164 current = list->first;
165 while (current != nullptr && current->address != block)
166 {
167 previous = current;
168 current = current->next;
169 }
170
171 if (current == nullptr)
172 {
173 dealloc_error("address not found", block);
174 return;
175 }
176
177 if (previous == nullptr)
178 {
179 list->first = current->next;
180 }
181 else
182 {
183 previous->next = current->next;
184 }
185
186 list->size -= current->size;
187 list->count--;
188
189 FREE_MEM(current->address);
190 current->address = nullptr;
191 current->next = nullptr;
192 current->size = 0;
193 FREE_MEM(current);
194 }
.fi
.SS "void MemCopy (void * destination, const void * source, unsigned int length)"
.PP
Copy a block of memory, handling overlap\&.
.PP
Definition at line 77 of file memcpy\&.c\&.
.PP
.nf
78 {
79 char* dst = (char*) destination;
80 const char* src = (const char*) source;
81 unsigned int t;
82
83 if (length == 0 || dst == src) // nothing to do
84 return;
85
86 if ((mem_ptr)dst < (mem_ptr)src)
87 {
88 // Copy forward
92 t = (mem_ptr)src; // only need low bits
93 if ((t | (mem_ptr)dst) & wmask)
94 {
95 // Try to align operands\&. This cannot be done unless the low bits match\&.
96 if ((t ^ (mem_ptr)dst) & wmask || length < wsize)
97 t = length;
98 else
99 t = wsize - (t & wmask);
100 length -= t;
101
102 TLOOP1(*dst++ = *src++);
103 }
104
105 // Copy whole words, then mop up any trailing bytes\&.
106 t = length / wsize;
107 TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
108
109 t = length & wmask;
110 TLOOP(*dst++ = *src++);
111 #endif
112 }
113 else
114 {
115 // Copy backwards\&. Otherwise essentially the same\&.
116 // Alignment works as before, except that it takes
117 // (t&wmask) bytes to align, not wsize-(t&wmask)\&.
118 src += length;
119 dst += length;
120 t = (mem_ptr)src;
121 if ((t | (mem_ptr)dst) & wmask)
122 {
123 if ((t ^ (mem_ptr)dst) & wmask || length <= wsize)
124 t = length;
125 else
126 t &= wmask;
127 length -= t;
128
129 TLOOP1(*--dst = *--src);
130 }
131
132 t = length / wsize;
133 TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
134
135 t = length & wmask;
136 TLOOP(*--dst = *--src);
137 }
138 }
.fi
.SS "void MemSet (void * destination, int c0, unsigned int length)"
.PP
Fill block of memory with a constant value\&.
.PP
Definition at line 60 of file memset\&.c\&.
.PP
.nf
61 {
62 unsigned char* dst = (unsigned char*) dst0;
63 unsigned int t;
64 unsigned int c;
65
66 /*
67 * If not enough words, just fill bytes\&. A length >= 2 words
68 * guarantees that at least one of them is `complete' after
69 * any necessary alignment\&. For instance:
70 *
71 * |-----------|-----------|-----------|
72 * |00|01|02|03|04|05|06|07|08|09|0A|00|
73 * ^---------------------^
74 * dst dst+length-1
75 *
76 * but we use a minimum of 3 here since the overhead of the code
77 * to do word writes is substantial\&.
78 */
79 if (length < 3 * wsize)
80 {
81 while (length != 0)
82 {
83 *dst++ = c0;
84 --length;
85 }
86 }
87
88 if ((c = (unsigned char)c0) != 0)
89 { /* Fill the word\&. */
90 c = (c << 8) | c; /* u_int is 16 bits\&. */
91 #if UINT_MAX > 0xffff
92 c = (c << 16) | c; /* u_int is 32 bits\&. */
93 #endif
94 #if UINT_MAX > 0xffffffff
95 c = (c << 32) | c; /* u_int is 64 bits\&. */
96 #endif
97 }
98
99 /* Align destination by filling in bytes\&. */
100 if ((t = (mem_ptr)dst & wmask) != 0)
101 {
102 t = wsize - t;
103 length -= t;
104 do
105 {
106 *dst++ = c0;
107 }
108 while (--t != 0);
109 }
110
111 /* Fill words\&. Length was >= 2*words so we know t >= 1 here\&. */
112 t = length / wsize;
113 do
114 {
115 *(unsigned int*)dst = c;
116 dst += wsize;
117 }
118 while (--t != 0);
119
120 /* Mop up trailing bytes, if any\&. */
121 t = length & wmask;
122 if (t != 0)
123 do
124 {
125 *dst++ = c0;
126 }
127 while (--t != 0);
128 }
.fi
.SS "void MemUsage (long *, long *, long *)"
.PP
Get memory usage in the global memory list\&.
.PP
Definition at line 224 of file mem\&.c\&.
.PP
.nf
225 {
226 *blocks = list->count;
227 *size = (long)list->size;
228 *peak = (long)list->peak;;
229 }
.fi
.SS "\fBbool\fP StrIsEqual (const char * s1, const char * s2)"
.PP
Compare two null terminated strings to each other\&.
.PP
Definition at line 50 of file strcmp\&.c\&.
.PP
.nf
51 {
52 int r;
53
54 while (*s1 == *s2++)
55 if (*s1++ == '\0')
56 return true;
57
58 r = (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
59
60 return r == 0;
61 }
.fi
.SS "int StrLen (const char * string)"
.PP
Get the length of a null terminated string\&.
.PP
Definition at line 34 of file strlen\&.c\&.
.PP
.nf
35 {
36 char* i = (char*)string;
37 char* s = i;
38 while (*i)
39 i++;
40 return (int)(i - s);
41 }
.fi
.SS "void Untag (char * destination, const char * source, \fBtexttag\fP tags[], unsigned int tagcount)"
.PP
Definition at line 32 of file untag\&.c\&.
.PP
.nf
33 {
34 const char *pos, *tmp, *tag;
35 char* dest;
36 int unsigned i, j, found;
37
38 pos = source;
39 dest = destination;
40
41 while (*pos != '\0')
42 {
43 if (*pos != '#')
44 {
45 (*dest++ = *pos++);
46 }
47 else
48 {
49 // Try to replace tag
50 found = 0;
51 for (i = 0; i < tagcount; i++)
52 {
53 tag = tags[i]\&.tag;
54 tmp = pos;
55 j = 0;
56 while (*tmp != '\0' && *tag != '\0' && *tmp == *tag)
57 {
58 tmp++;
59 tag++;
60 j++;
61 }
62
63 if (j > 1 && *(--tag) == '#')
64 {
65 // Tag found\&. Now replace\&.
66 tag = tags[i]\&.text;
67 while ((*dest++ = *tag++));
68 dest--;
69 pos = tmp;
70 found = 1;
71 break;
72 }
73 }
74
75 if (!found)
76 {
77 (*dest++ = *pos++);
78 }
79 }
80 }
81 *dest = '\0';
82 }
.fi
.SH "See also"
.PP
amath(1), amathr(3), amathi(3)