amath/src/clib/amathc.3

488 lines
13 KiB
Groff

.\" Copyright (c) 2014-2017 Carsten Sonne Larsen <cs@innolan.net>
.\" 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.8.1" "April 22 2017"
.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
http://amath.innolan.net/
.SH AUTHORS
.PP
Written by Carsten Sonne Larsen <cs@innolan.net>. The code in MemSet and
MemCopy is derived from software contributed to Berkeley by Mike Hibler and
Chris Torek.
.SH COPYRIGHT
Copyright (c) 2014-2017 Carsten Sonne Larsen <cs@innolan.net>
.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)