.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 \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)