2017-03-24 19:09:05 +00:00
|
|
|
.TH "amath/amathc.h" 3 "Wed Mar 1 2017" "Version 1.7.1" "amath" \" -*- nroff -*-
|
2017-03-11 22:37:45 +00:00
|
|
|
.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
|
2017-03-24 19:09:05 +00:00
|
|
|
91 if (list == nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
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
|
2017-03-24 19:09:05 +00:00
|
|
|
100 list->first = nullptr;
|
2017-03-11 22:37:45 +00:00
|
|
|
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
|
2017-03-24 19:09:05 +00:00
|
|
|
203 if (list == nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
204 {
|
|
|
|
205 return;
|
|
|
|
206 }
|
|
|
|
207
|
|
|
|
208 current = list->first;
|
2017-03-24 19:09:05 +00:00
|
|
|
209 while (current != nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
210 {
|
|
|
|
211 next = current->next;
|
|
|
|
212 FREE_MEM(current->address);
|
|
|
|
213 FREE_MEM(current);
|
|
|
|
214 current = next;
|
|
|
|
215 }
|
|
|
|
216
|
|
|
|
217 FREE_MEM(list);
|
2017-03-24 19:09:05 +00:00
|
|
|
218 list = nullptr;
|
2017-03-11 22:37:45 +00:00
|
|
|
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
|
2017-03-24 19:09:05 +00:00
|
|
|
151 if (list == nullptr || block == nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
152 {
|
|
|
|
153 dealloc_error("list", 0);
|
|
|
|
154 return;
|
|
|
|
155 }
|
|
|
|
156
|
2017-03-24 19:09:05 +00:00
|
|
|
157 if (block == nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
158 {
|
|
|
|
159 dealloc_error("memory", 0);
|
|
|
|
160 return;
|
|
|
|
161 }
|
|
|
|
162
|
2017-03-24 19:09:05 +00:00
|
|
|
163 previous = nullptr;
|
2017-03-11 22:37:45 +00:00
|
|
|
164 current = list->first;
|
2017-03-24 19:09:05 +00:00
|
|
|
165 while (current != nullptr && current->address != block)
|
2017-03-11 22:37:45 +00:00
|
|
|
166 {
|
|
|
|
167 previous = current;
|
|
|
|
168 current = current->next;
|
|
|
|
169 }
|
|
|
|
170
|
2017-03-24 19:09:05 +00:00
|
|
|
171 if (current == nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
172 {
|
|
|
|
173 dealloc_error("address not found", block);
|
|
|
|
174 return;
|
|
|
|
175 }
|
|
|
|
176
|
2017-03-24 19:09:05 +00:00
|
|
|
177 if (previous == nullptr)
|
2017-03-11 22:37:45 +00:00
|
|
|
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);
|
2017-03-24 19:09:05 +00:00
|
|
|
190 current->address = nullptr;
|
|
|
|
191 current->next = nullptr;
|
2017-03-11 22:37:45 +00:00
|
|
|
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)
|