.\" Copyright (c) 2014-2021 Carsten Sonne Larsen .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .TH "amathc.h" 3 "Version 1.9.0" "January 11 2021" .SH NAME amathc.h \- C functions for manipulating strings and memory .SH SYNOPSIS .br .PP \fC#include \fB"amathc\&.h"\fP .SS "Data Structures" .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 \fBDetachMemSafe\fP (void *)" .br .RI "\fIDetach an allocated 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 "bool \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 .SH DESCRIPTION .PP .SS "unsigned int AllocAndCopy (char ** destination, const char * source)" .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 DetachMemSafe (void * block)" .PP Detach an allocated memory from the global memory list\&. The memory block is only detached, not deallocated\&. .PP Definition at line 209 of file mem\&.c\&. .PP .nf 210 { 211 RemoveMemSafe(block, false); 212 } .fi .SS "void FreeAllSafe ()" .PP Deallocate all memory in the global memory list\&. .PP Definition at line 217 of file mem\&.c\&. .PP .nf 218 { 219 struct MemoryBlock *current, *next; 220 221 if (list == nullptr) 222 { 223 return; 224 } 225 226 current = list->first; 227 while (current != nullptr) 228 { 229 next = current->next; 230 FREE_MEM(current->address); 231 FREE_MEM(current); 232 current = next; 233 } 234 235 FREE_MEM(list); 236 list = nullptr; 237 } .fi .SS "void FreeMemSafe (void *)" .PP Deallocate memory from the global memory list\&. .PP Definition at line 200 of file mem\&.c\&. .PP .nf 201 { 202 RemoveMemSafe(block, true); 203 } .fi .SS "void MemCopy (void * destination, const void * source, unsigned int length)" .PP Copy a block of memory, handling overlap\&. .PP Definition at line 75 of file memcpy\&.c\&. .PP .nf 76 { 77 char* dst = (char*) destination; 78 const char* src = (const char*) source; 79 unsigned int t; 80 81 if (length == 0 || dst == src) // nothing to do 82 return; 83 84 if ((mem_ptr)dst < (mem_ptr)src) 85 { 86 // Copy forward 90 t = (mem_ptr)src; // only need low bits 91 if ((t | (mem_ptr)dst) & wmask) 92 { 93 // Try to align operands\&. This cannot be done unless the low bits match\&. 94 if ((t ^ (mem_ptr)dst) & wmask || length < wsize) 95 t = length; 96 else 97 t = wsize - (t & wmask); 98 length -= t; 99 100 TLOOP1(*dst++ = *src++); 101 } 102 103 // Copy whole words, then mop up any trailing bytes\&. 104 t = length / wsize; 105 TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); 106 107 t = length & wmask; 108 TLOOP(*dst++ = *src++); 110 } 111 else 112 { 113 // Copy backwards\&. Otherwise essentially the same\&. 114 // Alignment works as before, except that it takes 115 // (t&wmask) bytes to align, not wsize-(t&wmask)\&. 116 src += length; 117 dst += length; 118 t = (mem_ptr)src; 119 if ((t | (mem_ptr)dst) & wmask) 120 { 121 if ((t ^ (mem_ptr)dst) & wmask || length <= wsize) 122 t = length; 123 else 124 t &= wmask; 125 length -= t; 126 127 TLOOP1(*--dst = *--src); 128 } 129 130 t = length / wsize; 131 TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); 132 133 t = length & wmask; 134 TLOOP(*--dst = *--src); 135 } 136 } .fi .SS "void MemSet (void * destination, int c0, unsigned int length)" .PP Fill block of memory with a constant value\&. .PP Definition at line 56 of file memset\&.c\&. .PP .nf 57 { 58 unsigned char* dst = (unsigned char*) dst0; 59 unsigned int t; 60 unsigned int c; 61 62 /* 63 * If not enough words, just fill bytes\&. A length >= 2 words 64 * guarantees that at least one of them is `complete' after 65 * any necessary alignment\&. For instance: 66 * 67 * |-----------|-----------|-----------| 68 * |00|01|02|03|04|05|06|07|08|09|0A|00| 69 * ^---------------------^ 70 * dst dst+length-1 71 * 72 * but we use a minimum of 3 here since the overhead of the code 73 * to do word writes is substantial\&. 74 */ 75 if (length < 3 * wsize) 76 { 77 while (length != 0) 78 { 79 *dst++ = c0; 80 --length; 81 } 82 } 83 84 if ((c = (unsigned char)c0) != 0) 85 { /* Fill the word\&. */ 86 c = (c << 8) | c; /* u_int is 16 bits\&. */ 87 #if UINT_MAX > 0xffff 88 c = (c << 16) | c; /* u_int is 32 bits\&. */ 89 #endif 90 #if UINT_MAX > 0xffffffff 91 c = (c << 32) | c; /* u_int is 64 bits\&. */ 92 #endif 93 } 94 95 /* Align destination by filling in bytes\&. */ 96 if ((t = (mem_ptr)dst & wmask) != 0) 97 { 98 t = wsize - t; 99 length -= t; 100 do 101 { 102 *dst++ = c0; 103 } 104 while (--t != 0); 105 } 106 107 /* Fill words\&. Length was >= 2*words so we know t >= 1 here\&. */ 108 t = length / wsize; 109 do 110 { 111 *(unsigned int*)dst = c; 112 dst += wsize; 113 } 114 while (--t != 0); 115 116 /* Mop up trailing bytes, if any\&. */ 117 t = length & wmask; 118 if (t != 0) 119 do 120 { 121 *dst++ = c0; 122 } 123 while (--t != 0); 124 } .fi .SS "void MemUsage (long *, long *, long *)" .PP Get memory usage in the global memory list\&. .PP Definition at line 242 of file mem\&.c\&. .PP .nf 243 { 244 *blocks = list->count; 245 *size = (long)list->size; 246 *peak = (long)list->peak;; 247 } .fi .SS "bool 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 HOMEPAGE https://amath.innolan.net/ .SH AUTHORS .PP Written by Carsten Sonne Larsen . The code in MemSet and MemCopy is derived from software contributed to Berkeley by Mike Hibler and Chris Torek. .SH COPYRIGHT Copyright (c) 2014-2021 Carsten Sonne Larsen .br Copyright (c) 2007 The NetBSD Foundation, Inc. .br Copyright (c) 1990, 1993 The Regents of the University of California .SH SEE ALSO amath(1), amathr(3), amathi(3)