1 /*
2  * PROPRIETARY INFORMATION.  This software is proprietary to POWDER
3  * Development, and is not to be reproduced, transmitted, or disclosed
4  * in any way without written permission.
5  *
6  * Produced by:	Jeff Lait
7  *
8  *      	POWDER Development
9  *
10  * NAME:        name.cpp ( POWDER Library, C++ )
11  *
12  * COMMENTS:
13  *	This handles tracking the name library.
14  */
15 
16 #include "mygba.h"
17 #include <stdio.h>
18 #include "sramstream.h"
19 #include "assert.h"
20 #include "name.h"
21 #include "msg.h"
22 
23 #define INVALID_NAME 65535
24 
25 int    glb_numnames = 0;
26 char **glb_names = 0;
27 u8    *glb_namerefs = 0;
28 
29 void
name_init(int numnames)30 name_init(int numnames)
31 {
32     int			i;
33 
34     for (i = 0; i < glb_numnames; i++)
35     {
36 	if (glb_names[i])
37 	    free(glb_names[i]);
38     }
39     delete [] glb_names;
40     delete [] glb_namerefs;
41 
42     if (numnames < 64)
43 	numnames = 64;
44     glb_numnames = numnames;
45     glb_names = new char *[glb_numnames];
46     glb_namerefs = new u8[glb_numnames];
47     memset(glb_names, 0, sizeof(char *) * glb_numnames);
48     memset(glb_namerefs, 0, sizeof(u8) * glb_numnames);
49 }
50 
51 int
name_alloc(const char * name)52 name_alloc(const char *name)
53 {
54     int		i;
55 
56     for (i = 0; i < glb_numnames; i++)
57     {
58 	if (!glb_namerefs[i])
59 	{
60 	    // Found a free name!
61 	    break;
62 	}
63     }
64     if (i == glb_numnames)
65     {
66 	// Need to realloc.
67 	int		  newsize;
68 	char		**newnames;
69 	u8		 *newref;
70 
71 	newsize = glb_numnames * 2;
72 	newnames = new char *[newsize];
73 	newref = new u8[newsize];
74 	memset(newnames, 0, sizeof(char *) * newsize);
75 	memset(newref, 0, sizeof(u8) * newsize);
76 
77 	// Copy old ones.
78 	memcpy(newnames, glb_names, sizeof(char *) * glb_numnames);
79 	memcpy(newref, glb_namerefs, sizeof(u8) * glb_numnames);
80 
81 	// Delete & change over.
82 	// Note that i is now a valid index.
83 	glb_numnames = newsize;
84 	delete [] glb_names;
85 	glb_names = newnames;
86 	delete [] glb_namerefs;
87 	glb_namerefs = newref;
88     }
89 
90     UT_ASSERT(glb_namerefs[i] == 0);
91 
92     glb_namerefs[i] = 1;
93     glb_names[i] = strdup(name);
94     return i;
95 }
96 
97 void
name_addref(int idx)98 name_addref(int idx)
99 {
100     if (idx < 0)
101 	return;
102     if (idx == INVALID_NAME)
103 	return;
104 
105     if (idx >= glb_numnames)
106     {
107 	UT_ASSERT(0);
108 	return;
109     }
110     glb_namerefs[idx]++;
111 }
112 
113 void
name_decref(int idx)114 name_decref(int idx)
115 {
116     if (idx < 0)
117 	return;
118     if (idx == INVALID_NAME)
119 	return;
120 
121     if (idx >= glb_numnames)
122     {
123 	UT_ASSERT(0);
124 	return;
125     }
126     if (glb_namerefs[idx] == 0)
127     {
128 	UT_ASSERT(0);
129 	return;
130     }
131     glb_namerefs[idx]--;
132     if (!glb_namerefs[idx])
133     {
134 	free(glb_names[idx]);
135 	glb_names[idx] = 0;
136     }
137 }
138 
139 void
name_load(SRAMSTREAM & is)140 name_load(SRAMSTREAM &is)
141 {
142     int		i;
143     int		numnames;
144     char	buf[40];
145 
146     is.uread(numnames, 16);
147 
148     name_init(numnames);
149 
150     for (i = 0; i < numnames; i++)
151     {
152 	is.readString(buf, 30);
153 	if (buf[0])
154 	{
155 	    // This is a real string...
156 	    glb_names[i] = strdup(buf);
157 	}
158     }
159 }
160 
161 void
name_save(SRAMSTREAM & os)162 name_save(SRAMSTREAM &os)
163 {
164     int		numnames, i;
165 
166     // Count backward to find number of real names.
167     for (numnames = glb_numnames-1; numnames >= 0 && !glb_names[numnames];
168 	    numnames--);
169 
170     // Include the last guy found.
171     numnames++;
172 
173     os.write(numnames, 16);
174 
175     for (i = 0; i < numnames; i++)
176     {
177 	os.writeString(glb_names[i], 30);
178     }
179 }
180 
181 //
182 // Now for the actual NAME definitions
183 //
184 
NAME()185 NAME::NAME()
186 {
187     myIdx = INVALID_NAME;
188 }
189 
~NAME()190 NAME::~NAME()
191 {
192     name_decref(myIdx);
193 }
194 
NAME(const NAME & name)195 NAME::NAME(const NAME &name)
196 {
197     myIdx = name.myIdx;
198     name_addref(myIdx);
199 }
200 
201 NAME &
operator =(const NAME & name)202 NAME::operator=(const NAME &name)
203 {
204     name_addref(name.myIdx);
205     name_decref(myIdx);
206     myIdx = name.myIdx;
207 
208     return *this;
209 }
210 
211 const char *
getName() const212 NAME::getName() const
213 {
214     if (myIdx == INVALID_NAME)
215 	return 0;
216 
217     if (myIdx >= glb_numnames)
218     {
219 	UT_ASSERT(0);
220 	return 0;
221     }
222 
223     return glb_names[myIdx];
224 }
225 
226 void
setName(const char * name)227 NAME::setName(const char *name)
228 {
229     name_decref(myIdx);
230     if (name && *name)
231 	myIdx = name_alloc(name);
232     else
233 	myIdx = INVALID_NAME;
234 }
235 
236 void
save(SRAMSTREAM & os) const237 NAME::save(SRAMSTREAM &os) const
238 {
239     os.write(myIdx, 16);
240 }
241 
242 void
load(SRAMSTREAM & is)243 NAME::load(SRAMSTREAM &is)
244 {
245     int		val;
246 
247     name_decref(myIdx);
248 
249     is.uread(val, 16);
250 
251     myIdx = val;
252     name_addref(myIdx);
253 }
254