1 /*
2  csound_type_system.c:
3 
4  Copyright (C) 2012,2013 Steven Yi
5 
6  This file is part of Csound.
7 
8  The Csound Library is free software; you can redistribute it
9  and/or modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  Csound is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with Csound; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  02110-1301 USA
22  */
23 
24 #include "csound_type_system.h"
25 #include <string.h>
26 #include <stdio.h>
27 #include "csoundCore.h"
28 
csTypeExistsWithSameName(TYPE_POOL * pool,CS_TYPE * typeInstance)29 int csTypeExistsWithSameName(TYPE_POOL* pool, CS_TYPE* typeInstance) {
30     CS_TYPE_ITEM* current = pool->head;
31     while (current != NULL) {
32 
33       /* printf("Search if type [%s] == [%s]",
34          current->varTypeName, typeInstance->varTypeName); */
35 
36       if (strcmp(current->cstype->varTypeName,
37                  typeInstance->varTypeName) == 0) {
38         return 1;
39       }
40       current = current->next;
41     }
42 
43     return 0;
44 }
45 
csoundGetTypeWithVarTypeName(TYPE_POOL * pool,char * typeName)46 CS_TYPE* csoundGetTypeWithVarTypeName(TYPE_POOL* pool, char* typeName) {
47     CS_TYPE_ITEM* current = pool->head;
48     while (current != NULL) {
49       if (strcmp(typeName, current->cstype->varTypeName) == 0) {
50         return current->cstype;
51       }
52       current = current->next;
53     }
54     return NULL;
55 }
56 
csoundGetTypeForVarName(TYPE_POOL * pool,char * varName)57 CS_TYPE* csoundGetTypeForVarName(TYPE_POOL* pool, char* varName) {
58     CS_TYPE_ITEM* current = pool->head;
59     char temp[2];
60     temp[0] = varName[0];
61     temp[1] = 0;
62     while (current != NULL) {
63       if (strcmp(temp, current->cstype->varTypeName) == 0) {
64         return current->cstype;
65       }
66       current = current->next;
67     }
68     return NULL;
69 }
70 
csoundAddVariableType(CSOUND * csound,TYPE_POOL * pool,CS_TYPE * typeInstance)71 int csoundAddVariableType(CSOUND* csound, TYPE_POOL* pool, CS_TYPE* typeInstance)
72 {
73     CS_TYPE_ITEM* item;
74     if (csTypeExistsWithSameName(pool, typeInstance)) {
75       return 0;
76     }
77 
78     item = (CS_TYPE_ITEM*)csound->Calloc(csound, sizeof(CS_TYPE_ITEM));
79     item->cstype = typeInstance;
80 
81     if (pool->head == NULL) {
82       pool->head = item;
83     } else {
84       CS_TYPE_ITEM* current = pool->head;
85       while (current->next) {
86         current = current->next;
87       }
88       current->next = item;
89       item->next = NULL;
90     }
91 
92     /* printf("Adding type with type name: %s\n", typeInstance->varTypeName); */
93 
94     return 1;
95 }
96 
97 /* VAR POOL FUNCTIONS */
98 
99 
csoundCreateVarPool(CSOUND * csound)100 CS_VAR_POOL* csoundCreateVarPool(CSOUND* csound) {
101     CS_VAR_POOL* varPool = csound->Calloc(csound, sizeof(CS_VAR_POOL));
102     varPool->table = cs_hash_table_create(csound);
103     return varPool;
104 }
105 
csoundFreeVarPool(CSOUND * csound,CS_VAR_POOL * pool)106 void csoundFreeVarPool(CSOUND* csound, CS_VAR_POOL* pool) {
107     if(pool->table) cs_hash_table_mfree_complete(csound, pool->table);
108     csound->Free(csound, pool);
109 }
110 
getVarSimpleName(CSOUND * csound,const char * varName)111 char* getVarSimpleName(CSOUND* csound, const char* varName) {
112     char* retVal;
113 
114     if (varName[0] != '[') {
115       retVal = (char*)csound->Calloc(csound, sizeof(char) * (strlen(varName) + 1));
116       strcpy(retVal, varName);
117     } else {
118       int start = 0;
119       int typeEnd = 0;
120       int len = strlen(varName);
121       int newFirstLen, newSecondLen, newTotalLen;
122       char* t = (char*) varName;
123       char* t2;
124 
125       while(*t == '[') {
126         t++;
127         start++;
128       }
129       typeEnd = start;
130       t2 = t;
131       while(*t2 != ']' && *t2 != (char)0) {
132         t2++;
133         typeEnd++;
134       }
135       t2++;
136       typeEnd++;
137 
138       newFirstLen = (typeEnd - start - 1);
139       newSecondLen = (len - typeEnd);
140       newTotalLen = newFirstLen + newSecondLen;
141 
142       retVal = (char*)csound->Calloc(csound, sizeof(char) * (newTotalLen + 1));
143       strncpy(retVal, t, newFirstLen);
144       strncpy(retVal + newFirstLen, t2, newSecondLen);
145     }
146 
147     return retVal;
148 }
149 
csoundCreateVariable(void * csound,TYPE_POOL * pool,CS_TYPE * type,char * name,void * typeArg)150 CS_VARIABLE* csoundCreateVariable(void* csound, TYPE_POOL* pool,
151                                   CS_TYPE* type, char* name, void* typeArg)
152 {
153     CS_TYPE_ITEM* current = pool->head;
154     if (LIKELY(type != NULL))
155       while (current != NULL) {
156         if (strcmp(type->varTypeName, current->cstype->varTypeName) == 0) {
157           CS_VARIABLE* var = current->cstype->createVariable(csound, typeArg);
158           var->varType = type;
159           var->varName = cs_strdup(csound, name);
160           return var;
161         }
162         current = current->next;
163       }
164     else ((CSOUND *)csound)->ErrorMsg(csound,
165                                       Str("cannot create variable %s: NULL type"),
166                                       name);
167     return NULL;
168 }
169 
csoundFindVariableWithName(CSOUND * csound,CS_VAR_POOL * pool,const char * name)170 CS_VARIABLE* csoundFindVariableWithName(CSOUND* csound, CS_VAR_POOL* pool,
171                                         const char* name)
172 {
173 
174     CS_VARIABLE* returnValue = cs_hash_table_get(csound, pool->table, (char*)name);
175 
176     if (returnValue == NULL && pool->parent != NULL) {
177       returnValue = csoundFindVariableWithName(csound, pool->parent, name);
178     }
179 
180     return returnValue;
181 }
182 
csoundGetVariable(CS_VAR_POOL * pool,int index)183 CS_VARIABLE* csoundGetVariable(CS_VAR_POOL* pool, int index) {
184 
185     CS_VARIABLE* current = pool->head;
186     int i;
187 
188     for(i = 0; i < index || current != NULL; i++) {
189       /* THIS WAS WRONG!! && or || meant foR , ?? */
190       current = current->next;
191     }
192 
193     return current;
194 }
195 
196 //int csoundGetVariableIndex(CS_VAR_POOL* pool, CS_VARIABLE* var) {
197 //    CS_VARIABLE* current = pool->head;
198 //    int index = 0;
199 //
200 //    if (current == NULL) {
201 //        return -1;
202 //    }
203 //
204 //    for (index = 0; current != NULL; index++) {
205 //        if (current == var) {
206 //            return index;
207 //        }
208 //    }
209 //    return -1;
210 //}
211 
csoundAddVariable(CSOUND * csound,CS_VAR_POOL * pool,CS_VARIABLE * var)212 int csoundAddVariable(CSOUND* csound, CS_VAR_POOL* pool, CS_VARIABLE* var) {
213   if(var != NULL) {
214     if(pool->head == NULL) {
215       pool->head = var;
216       pool->tail = var;
217     } else {
218       pool->tail->next = var;
219       pool->tail = var;
220     }
221     cs_hash_table_put(csound, pool->table, var->varName, var);
222     // may need to revise this; var pools are accessed as MYFLT*,
223     // so need to ensure all memory is aligned to sizeof(MYFLT)
224     var->memBlockIndex = (pool->poolSize / sizeof(MYFLT)) +
225       ((pool->varCount + 1) * (CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET) / sizeof(MYFLT)));
226     pool->poolSize += var->memBlockSize;
227     pool->varCount += 1;
228     return 0;
229   } else return -1;
230 }
231 
recalculateVarPoolMemory(void * csound,CS_VAR_POOL * pool)232 void recalculateVarPoolMemory(void* csound, CS_VAR_POOL* pool)
233 {
234     CS_VARIABLE* current = pool->head;
235     int varCount = 1;
236     pool->poolSize = 0;
237 
238     while (current != NULL) {
239       /* VL 26-12-12: had to revert these lines to avoid memory crashes
240          with higher ksmps */
241       if(current->updateMemBlockSize != NULL) {
242         current->updateMemBlockSize(csound, current);
243       }
244 
245       current->memBlockIndex = (pool->poolSize / sizeof(MYFLT)) +
246         (varCount * CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET) / sizeof(MYFLT));
247       pool->poolSize += current->memBlockSize;
248 
249       current = current->next;
250       varCount++;
251     }
252 }
253 
reallocateVarPoolMemory(void * csound,CS_VAR_POOL * pool)254 void reallocateVarPoolMemory(void* csound, CS_VAR_POOL* pool) {
255     CS_VARIABLE* current = pool->head;
256     CS_VAR_MEM* varMem = NULL;
257     size_t memSize;
258     pool->poolSize = 0;
259 
260     while (current != NULL) {
261       varMem = current->memBlock;
262       memSize = current->memBlockSize;
263 
264       if(current->updateMemBlockSize != NULL) {
265         current->updateMemBlockSize(csound, current);
266       }
267       // VL 14-3-2015 only realloc if we need to
268       if(memSize < (size_t)current->memBlockSize) {
269           memSize = CS_VAR_TYPE_OFFSET + current->memBlockSize;
270           varMem =
271                (CS_VAR_MEM *)((CSOUND *)csound)->ReAlloc(csound,varMem,
272                                              memSize);
273           current->memBlock = varMem;
274        }
275        pool->poolSize += current->memBlockSize;
276        current = current->next;
277     }
278 }
279 
deleteVarPoolMemory(void * csnd,CS_VAR_POOL * pool)280 void deleteVarPoolMemory(void* csnd, CS_VAR_POOL* pool) {
281     CS_VARIABLE* current = pool->head, *tmp;
282     CSOUND *csound = (CSOUND *)csnd;
283     CS_TYPE* type;
284     while (current != NULL) {
285       tmp = current;
286       type = current->subType;
287       if (type->freeVariableMemory != NULL) {
288         type->freeVariableMemory(csound, current->memBlock);
289       }
290       csound->Free(csound, current->memBlock);
291       current = current->next;
292       csound->Free(csound, tmp);
293     }
294 }
295 
296 
297 
initializeVarPool(void * csound,MYFLT * memBlock,CS_VAR_POOL * pool)298 void initializeVarPool(void *csound, MYFLT* memBlock, CS_VAR_POOL* pool) {
299     CS_VARIABLE* current = pool->head;
300     int varNum = 1;
301 
302     while (current != NULL) {
303       if (current->initializeVariableMemory != NULL) {
304         current->initializeVariableMemory(csound, current,
305                                           memBlock + current->memBlockIndex);
306       }
307       varNum++;
308       current = current->next;
309     }
310 }
311 
debug_print_varpool(CSOUND * csound,CS_VAR_POOL * pool)312 void debug_print_varpool(CSOUND* csound, CS_VAR_POOL* pool) {
313     CS_VARIABLE* gVar = pool->head;
314     int count = 0;
315     while(gVar != NULL) {
316       csound->Message(csound, "  %d) %s:%s\n", count++,
317                       gVar->varName, gVar->varType->varTypeName);
318       gVar = gVar->next;
319     }
320 }
321