xref: /onnv-gate/usr/src/lib/libtecla/common/strngmem.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd.
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * All rights reserved.
5*0Sstevel@tonic-gate  *
6*0Sstevel@tonic-gate  * Permission is hereby granted, free of charge, to any person obtaining a
7*0Sstevel@tonic-gate  * copy of this software and associated documentation files (the
8*0Sstevel@tonic-gate  * "Software"), to deal in the Software without restriction, including
9*0Sstevel@tonic-gate  * without limitation the rights to use, copy, modify, merge, publish,
10*0Sstevel@tonic-gate  * distribute, and/or sell copies of the Software, and to permit persons
11*0Sstevel@tonic-gate  * to whom the Software is furnished to do so, provided that the above
12*0Sstevel@tonic-gate  * copyright notice(s) and this permission notice appear in all copies of
13*0Sstevel@tonic-gate  * the Software and that both the above copyright notice(s) and this
14*0Sstevel@tonic-gate  * permission notice appear in supporting documentation.
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*0Sstevel@tonic-gate  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*0Sstevel@tonic-gate  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
19*0Sstevel@tonic-gate  * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20*0Sstevel@tonic-gate  * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
21*0Sstevel@tonic-gate  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
22*0Sstevel@tonic-gate  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
23*0Sstevel@tonic-gate  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24*0Sstevel@tonic-gate  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25*0Sstevel@tonic-gate  *
26*0Sstevel@tonic-gate  * Except as contained in this notice, the name of a copyright holder
27*0Sstevel@tonic-gate  * shall not be used in advertising or otherwise to promote the sale, use
28*0Sstevel@tonic-gate  * or other dealings in this Software without prior written authorization
29*0Sstevel@tonic-gate  * of the copyright holder.
30*0Sstevel@tonic-gate  */
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <stdlib.h>
35*0Sstevel@tonic-gate #include <stdio.h>
36*0Sstevel@tonic-gate #include <errno.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate #include "strngmem.h"
39*0Sstevel@tonic-gate #include "freelist.h"
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate struct StringMem {
42*0Sstevel@tonic-gate   unsigned long nmalloc;  /* The number of strings allocated with malloc */
43*0Sstevel@tonic-gate   FreeList *fl;           /* The free-list */
44*0Sstevel@tonic-gate };
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*.......................................................................
47*0Sstevel@tonic-gate  * Create a string free-list container and the first block of its free-list.
48*0Sstevel@tonic-gate  *
49*0Sstevel@tonic-gate  * Input:
50*0Sstevel@tonic-gate  *  blocking_factor   int    The blocking_factor argument specifies how
51*0Sstevel@tonic-gate  *                           many strings of length SM_STRLEN
52*0Sstevel@tonic-gate  *                           bytes (see stringmem.h) are allocated in each
53*0Sstevel@tonic-gate  *                           free-list block.
54*0Sstevel@tonic-gate  *                           For example if blocking_factor=64 and
55*0Sstevel@tonic-gate  *                           SM_STRLEN=16, then each new
56*0Sstevel@tonic-gate  *                           free-list block will take 1K of memory.
57*0Sstevel@tonic-gate  * Output:
58*0Sstevel@tonic-gate  *  return      StringMem *  The new free-list container, or NULL on
59*0Sstevel@tonic-gate  *                           error.
60*0Sstevel@tonic-gate  */
_new_StringMem(unsigned blocking_factor)61*0Sstevel@tonic-gate StringMem *_new_StringMem(unsigned blocking_factor)
62*0Sstevel@tonic-gate {
63*0Sstevel@tonic-gate   StringMem *sm;    /* The container to be returned. */
64*0Sstevel@tonic-gate /*
65*0Sstevel@tonic-gate  * Check arguments.
66*0Sstevel@tonic-gate  */
67*0Sstevel@tonic-gate   if(blocking_factor < 1) {
68*0Sstevel@tonic-gate     errno = EINVAL;
69*0Sstevel@tonic-gate     return NULL;
70*0Sstevel@tonic-gate   };
71*0Sstevel@tonic-gate /*
72*0Sstevel@tonic-gate  * Allocate the container.
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate   sm = (StringMem *) malloc(sizeof(StringMem));
75*0Sstevel@tonic-gate   if(!sm) {
76*0Sstevel@tonic-gate     errno = ENOMEM;
77*0Sstevel@tonic-gate     return NULL;
78*0Sstevel@tonic-gate   };
79*0Sstevel@tonic-gate /*
80*0Sstevel@tonic-gate  * Before attempting any operation that might fail, initialize
81*0Sstevel@tonic-gate  * the container at least up to the point at which it can safely
82*0Sstevel@tonic-gate  * be passed to _del_StringMem().
83*0Sstevel@tonic-gate  */
84*0Sstevel@tonic-gate   sm->nmalloc = 0;
85*0Sstevel@tonic-gate   sm->fl = NULL;
86*0Sstevel@tonic-gate /*
87*0Sstevel@tonic-gate  * Allocate the free-list.
88*0Sstevel@tonic-gate  */
89*0Sstevel@tonic-gate   sm->fl = _new_FreeList(SM_STRLEN, blocking_factor);
90*0Sstevel@tonic-gate   if(!sm->fl)
91*0Sstevel@tonic-gate     return _del_StringMem(sm, 1);
92*0Sstevel@tonic-gate /*
93*0Sstevel@tonic-gate  * Return the free-list container.
94*0Sstevel@tonic-gate  */
95*0Sstevel@tonic-gate   return sm;
96*0Sstevel@tonic-gate }
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate /*.......................................................................
99*0Sstevel@tonic-gate  * Delete a string free-list.
100*0Sstevel@tonic-gate  *
101*0Sstevel@tonic-gate  * Input:
102*0Sstevel@tonic-gate  *  sm       StringMem *  The string free-list to be deleted, or NULL.
103*0Sstevel@tonic-gate  *  force          int    If force==0 then _del_StringMem() will complain
104*0Sstevel@tonic-gate  *                         and refuse to delete the free-list if any
105*0Sstevel@tonic-gate  *                         of nodes have not been returned to the free-list.
106*0Sstevel@tonic-gate  *                        If force!=0 then _del_StringMem() will not check
107*0Sstevel@tonic-gate  *                         whether any nodes are still in use and will
108*0Sstevel@tonic-gate  *                         always delete the list.
109*0Sstevel@tonic-gate  * Output:
110*0Sstevel@tonic-gate  *  return   StringMem *  Always NULL (even if the list couldn't be
111*0Sstevel@tonic-gate  *                        deleted).
112*0Sstevel@tonic-gate  */
_del_StringMem(StringMem * sm,int force)113*0Sstevel@tonic-gate StringMem *_del_StringMem(StringMem *sm, int force)
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate   if(sm) {
116*0Sstevel@tonic-gate /*
117*0Sstevel@tonic-gate  * Check whether any strings have not been returned to the free-list.
118*0Sstevel@tonic-gate  */
119*0Sstevel@tonic-gate     if(!force && (sm->nmalloc > 0 || _busy_FreeListNodes(sm->fl) > 0)) {
120*0Sstevel@tonic-gate       errno = EBUSY;
121*0Sstevel@tonic-gate       return NULL;
122*0Sstevel@tonic-gate     };
123*0Sstevel@tonic-gate /*
124*0Sstevel@tonic-gate  * Delete the free-list.
125*0Sstevel@tonic-gate  */
126*0Sstevel@tonic-gate     sm->fl = _del_FreeList(sm->fl, force);
127*0Sstevel@tonic-gate /*
128*0Sstevel@tonic-gate  * Delete the container.
129*0Sstevel@tonic-gate  */
130*0Sstevel@tonic-gate     free(sm);
131*0Sstevel@tonic-gate   };
132*0Sstevel@tonic-gate   return NULL;
133*0Sstevel@tonic-gate }
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate /*.......................................................................
136*0Sstevel@tonic-gate  * Allocate an array of 'length' chars.
137*0Sstevel@tonic-gate  *
138*0Sstevel@tonic-gate  * Input:
139*0Sstevel@tonic-gate  *  sm      StringMem *  The string free-list to allocate from.
140*0Sstevel@tonic-gate  *  length     size_t    The length of the new string (including '\0').
141*0Sstevel@tonic-gate  * Output:
142*0Sstevel@tonic-gate  *  return       char *  The new string or NULL on error.
143*0Sstevel@tonic-gate  */
_new_StringMemString(StringMem * sm,size_t length)144*0Sstevel@tonic-gate char *_new_StringMemString(StringMem *sm, size_t length)
145*0Sstevel@tonic-gate {
146*0Sstevel@tonic-gate   char *string;   /* The string to be returned */
147*0Sstevel@tonic-gate   int was_malloc; /* True if malloc was used to allocate the string */
148*0Sstevel@tonic-gate /*
149*0Sstevel@tonic-gate  * Check arguments.
150*0Sstevel@tonic-gate  */
151*0Sstevel@tonic-gate   if(!sm)
152*0Sstevel@tonic-gate     return NULL;
153*0Sstevel@tonic-gate   if(length < 1)
154*0Sstevel@tonic-gate     length = 1;
155*0Sstevel@tonic-gate /*
156*0Sstevel@tonic-gate  * Allocate the new node from the free list if possible.
157*0Sstevel@tonic-gate  */
158*0Sstevel@tonic-gate   if(length < SM_STRLEN) {
159*0Sstevel@tonic-gate     string = (char *)_new_FreeListNode(sm->fl);
160*0Sstevel@tonic-gate     if(!string)
161*0Sstevel@tonic-gate       return NULL;
162*0Sstevel@tonic-gate     was_malloc = 0;
163*0Sstevel@tonic-gate   } else {
164*0Sstevel@tonic-gate     string = (char *) malloc(length+1); /* Leave room for the flag byte */
165*0Sstevel@tonic-gate     if(!string)
166*0Sstevel@tonic-gate       return NULL;
167*0Sstevel@tonic-gate /*
168*0Sstevel@tonic-gate  * Count malloc allocations.
169*0Sstevel@tonic-gate  */
170*0Sstevel@tonic-gate     was_malloc = 1;
171*0Sstevel@tonic-gate     sm->nmalloc++;
172*0Sstevel@tonic-gate   };
173*0Sstevel@tonic-gate /*
174*0Sstevel@tonic-gate  * Use the first byte of the string to record whether the string was
175*0Sstevel@tonic-gate  * allocated with malloc or from the free-list. Then return the rest
176*0Sstevel@tonic-gate  * of the string for use by the user.
177*0Sstevel@tonic-gate  */
178*0Sstevel@tonic-gate   string[0] = (char) was_malloc;
179*0Sstevel@tonic-gate   return string + 1;
180*0Sstevel@tonic-gate }
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate /*.......................................................................
183*0Sstevel@tonic-gate  * Free a string that was previously returned by _new_StringMemString().
184*0Sstevel@tonic-gate  *
185*0Sstevel@tonic-gate  * Input:
186*0Sstevel@tonic-gate  *  sm      StringMem *  The free-list from which the string was originally
187*0Sstevel@tonic-gate  *                       allocated.
188*0Sstevel@tonic-gate  *  s            char *  The string to be returned to the free-list, or NULL.
189*0Sstevel@tonic-gate  * Output:
190*0Sstevel@tonic-gate  *  return       char *  Always NULL.
191*0Sstevel@tonic-gate  */
_del_StringMemString(StringMem * sm,char * s)192*0Sstevel@tonic-gate char *_del_StringMemString(StringMem *sm, char *s)
193*0Sstevel@tonic-gate {
194*0Sstevel@tonic-gate   int was_malloc;  /* True if the string originally came from malloc() */
195*0Sstevel@tonic-gate /*
196*0Sstevel@tonic-gate  * Is there anything to be deleted?
197*0Sstevel@tonic-gate  */
198*0Sstevel@tonic-gate   if(s && sm) {
199*0Sstevel@tonic-gate /*
200*0Sstevel@tonic-gate  * Retrieve the true string pointer. This is one less than the one
201*0Sstevel@tonic-gate  * returned by _new_StringMemString() because the first byte of the
202*0Sstevel@tonic-gate  * allocated memory is reserved by _new_StringMemString as a flag byte
203*0Sstevel@tonic-gate  * to say whether the memory was allocated from the free-list or directly
204*0Sstevel@tonic-gate  * from malloc().
205*0Sstevel@tonic-gate  */
206*0Sstevel@tonic-gate     s--;
207*0Sstevel@tonic-gate /*
208*0Sstevel@tonic-gate  * Get the origination flag.
209*0Sstevel@tonic-gate  */
210*0Sstevel@tonic-gate     was_malloc = s[0];
211*0Sstevel@tonic-gate     if(was_malloc) {
212*0Sstevel@tonic-gate       free(s);
213*0Sstevel@tonic-gate       s = NULL;
214*0Sstevel@tonic-gate       sm->nmalloc--;
215*0Sstevel@tonic-gate     } else {
216*0Sstevel@tonic-gate       s = (char *) _del_FreeListNode(sm->fl, s);
217*0Sstevel@tonic-gate     };
218*0Sstevel@tonic-gate   };
219*0Sstevel@tonic-gate   return NULL;
220*0Sstevel@tonic-gate }
221