fix memory leaks
[scilab.git] / scilab / modules / mpi / src / c / serialization.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011-2011 - DIGITEO - Antoine ELIAS
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12 #include <string.h>
13 #include <stdio.h>
14 #include "api_scilab.h"
15 #include "BOOL.h"
16 #include "MALLOC.h"
17 #include "serialization.h"
18
19 static int serialize_double(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
20 {
21     SciErr sciErr;
22     int iRows = 0;
23     int iCols = 0;
24     int iOne = 1;
25     int iSize = 0;
26     double *pdblR = NULL;
27     double *pdblI = NULL;
28
29     int *piOut = NULL;
30     int iOutLen = 0;
31
32     if (isVarComplex(_pvCtx, _piAddr))
33     {
34         double *p = NULL;
35
36         sciErr = getComplexMatrixOfDouble(_pvCtx, _piAddr, &iRows, &iCols, &pdblR, &pdblI);
37         if (sciErr.iErr)
38         {
39             printError(&sciErr, 0);
40             return 1;
41         }
42
43         iOutLen = 4 + (2 * iRows * iCols * sizeof(double) / sizeof(int));
44         piOut = (int *)MALLOC(iOutLen * sizeof(int));
45         if (piOut == NULL)
46         {
47             return 1;
48         }
49
50         piOut[0] = sci_matrix;
51         piOut[1] = iRows;
52         piOut[2] = iCols;
53         piOut[3] = 1;           //complex
54
55         //move 'p' to first real value
56         p = (double *)(piOut + 4);
57         iSize = iRows * iCols;
58         C2F(dcopy) (&iSize, pdblR, &iOne, p, &iOne);
59         //move 'p' to first complex value
60         p = p + iRows * iCols;
61         C2F(dcopy) (&iSize, pdblI, &iOne, p, &iOne);
62     }
63     else
64     {
65         double *p = NULL;
66
67         sciErr = getMatrixOfDouble(_pvCtx, _piAddr, &iRows, &iCols, &pdblR);
68         if (sciErr.iErr)
69         {
70             printError(&sciErr, 0);
71             return 1;
72         }
73
74         iOutLen = 4 + (iRows * iCols * sizeof(double) / sizeof(int));
75         piOut = (int *)MALLOC(iOutLen * sizeof(int));
76         if (piOut == NULL)
77         {
78             return 1;
79         }
80
81         piOut[0] = sci_matrix;
82         piOut[1] = iRows;
83         piOut[2] = iCols;
84         piOut[3] = 0;           //not complex
85
86         //move 'p' to first value
87         p = (double *)(piOut + 4);
88         iSize = iRows * iCols;
89         C2F(dcopy) (&iSize, pdblR, &iOne, p, &iOne);
90     }
91
92     *_piBuffer = piOut;
93     *_piBufferSize = iOutLen;
94     return 0;
95 }
96
97 static int serialize_string(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
98 {
99     int iErr = 0;
100     int i = 0;
101     int iRows = 0;
102     int iCols = 0;
103     char **pstData = NULL;
104     char *p = NULL;
105
106     int *piOut = NULL;
107     int *piOutLen = NULL;
108     int iOutLen = 0;
109
110     iErr = getAllocatedMatrixOfString(_pvCtx, _piAddr, &iRows, &iCols, &pstData);
111     if (iErr)
112     {
113         return 1;
114     }
115
116     for (i = 0; i < iRows * iCols; i++)
117     {
118         iOutLen += (int)strlen(pstData[i]);
119     }
120
121     if (iOutLen % 4)
122     {
123         iOutLen = iOutLen / (sizeof(int) / sizeof(char)) + 1;
124     }
125     else
126     {
127         iOutLen = iOutLen / (sizeof(int) / sizeof(char));
128     }
129
130     //4 for header and size of each string
131     iOutLen += 4 + iRows * iCols;
132
133     piOut = (int *)MALLOC(iOutLen * sizeof(int));
134     if (piOut == NULL)
135     {
136         return 1;
137     }
138
139     piOut[0] = sci_strings;
140     piOut[1] = iRows;
141     piOut[2] = iCols;
142     piOut[3] = 0;               //not complex
143
144     piOutLen = piOut + 4;
145
146     for (i = 0; i < iRows * iCols; i++)
147     {
148         piOutLen[i] = (int)strlen(pstData[i]);
149     }
150
151     p = (char *)(piOut + 4 + iRows * iCols);
152     for (i = 0; i < iRows * iCols; i++)
153     {
154         memcpy(p, pstData[i], piOutLen[i]);
155         p += piOutLen[i];
156     }
157
158     *_piBuffer = piOut;
159     *_piBufferSize = iOutLen;
160
161     freeAllocatedMatrixOfString(iRows, iCols, pstData);
162     return 0;
163 }
164
165 static int serialize_boolean(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
166 {
167     SciErr sciErr;
168     int iRows = 0;
169     int iCols = 0;
170     int *piBool = NULL;
171     int *p = NULL;
172
173     int *piOut = NULL;
174     int iOutLen = 0;
175
176     sciErr = getMatrixOfBoolean(_pvCtx, _piAddr, &iRows, &iCols, &piBool);
177     if (sciErr.iErr)
178     {
179         printError(&sciErr, 0);
180         return 1;
181     }
182
183     //4 for header and 1 for each boolean
184     iOutLen = 4 + iRows * iCols;
185
186     piOut = (int *)MALLOC(iOutLen * sizeof(int *));
187     if (piOut == NULL)
188     {
189         return 1;
190     }
191
192     piOut[0] = sci_boolean;
193     piOut[1] = iRows;
194     piOut[2] = iCols;
195     piOut[3] = 0;               //not complex
196
197     p = (int *)(piOut + 4);
198     memcpy(p, piBool, iRows * iCols * sizeof(int));
199
200     *_piBuffer = piOut;
201     *_piBufferSize = iOutLen;
202     return 0;
203 }
204
205 static int serialize_int(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
206 {
207     SciErr sciErr;
208     int iPrecision = 0;
209     int iRows = 0;
210     int iCols = 0;
211     int iItemSize = 0;
212     void *p = NULL;
213     void *pvData = NULL;
214
215     int *piOut = NULL;
216     int iOutLen = 0;
217
218     sciErr = getVarDimension(_pvCtx, _piAddr, &iRows, &iCols);
219     if (sciErr.iErr)
220     {
221         printError(&sciErr, 0);
222         return 1;
223     }
224
225     sciErr = getMatrixOfIntegerPrecision(_pvCtx, _piAddr, &iPrecision);
226     if (sciErr.iErr)
227     {
228         printError(&sciErr, 0);
229         return 1;
230     }
231
232     if (iPrecision == SCI_INT8 || iPrecision == SCI_UINT8)
233     {
234         iItemSize = sizeof(char);
235     }
236     else if (iPrecision == SCI_INT16 || iPrecision == SCI_UINT16)
237     {
238         iItemSize = sizeof(short);
239     }
240     else if (iPrecision == SCI_INT32 || iPrecision == SCI_UINT32)
241     {
242         iItemSize = sizeof(int);
243     }
244     /*
245         else if(iPrecision == SCI_INT64 || iPrecision == SCI_UINT64)
246         {
247             iItemSize = sizeof(long long);
248         }
249     */
250     //check and adjust alignement on integer
251     iOutLen = iRows * iCols;
252     if ((iOutLen * iItemSize) % sizeof(int))
253     {
254         iOutLen = (iOutLen * iItemSize) / sizeof(int) + 1;
255     }
256     else
257     {
258         iOutLen = (iOutLen * iItemSize) / (sizeof(int));
259     }
260
261     iOutLen += 4;
262     piOut = (int *)MALLOC(iOutLen * sizeof(int *));
263     if (piOut == NULL)
264     {
265         return 1;
266     }
267
268     piOut[0] = sci_ints;
269     piOut[1] = iRows;
270     piOut[2] = iCols;
271     piOut[3] = iPrecision;      //precision
272
273     switch (iPrecision)
274     {
275         case SCI_INT8:
276         {
277             sciErr = getMatrixOfInteger8(_pvCtx, _piAddr, &iRows, &iCols, (char **)&pvData);
278             break;
279         }
280         case SCI_UINT8:
281         {
282             sciErr = getMatrixOfUnsignedInteger8(_pvCtx, _piAddr, &iRows, &iCols, (unsigned char **)&pvData);
283             break;
284         }
285         case SCI_INT16:
286         {
287             sciErr = getMatrixOfInteger16(_pvCtx, _piAddr, &iRows, &iCols, (short **)&pvData);
288             break;
289         }
290         case SCI_UINT16:
291         {
292             sciErr = getMatrixOfUnsignedInteger16(_pvCtx, _piAddr, &iRows, &iCols, (unsigned short **)&pvData);
293             break;
294         }
295         case SCI_INT32:
296         {
297             sciErr = getMatrixOfInteger32(_pvCtx, _piAddr, &iRows, &iCols, (int **)&pvData);
298             break;
299         }
300         case SCI_UINT32:
301         {
302             sciErr = getMatrixOfUnsignedInteger32(_pvCtx, _piAddr, &iRows, &iCols, (unsigned int **)&pvData);
303             break;
304         }
305         /*
306             case SCI_INT64 :
307             {
308                 sciErr = getMatrixOfInteger64(_pvCtx, _piAddr, &iRows, &iCols, (long long**)&pvData);
309                 break;
310             }
311             case SCI_UINT64 :
312             {
313                 sciErr = getMatrixOfUnsignedInteger64(_pvCtx, _piAddr, &iRows, &iCols, (unsigned long long**)&pvData);
314                 break;
315                 }
316         */ default:
317             FREE(piOut);
318             return 1;
319     }
320
321     if (sciErr.iErr)
322     {
323         FREE(piOut);
324         printError(&sciErr, 0);
325         return 1;
326     }
327
328     p = piOut + 4;
329     memcpy(p, pvData, iRows * iCols * iItemSize);
330     *_piBuffer = piOut;
331     *_piBufferSize = iOutLen;
332     return 0;
333 }
334
335 static int serialize_sparse(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize, BOOL _bData)
336 {
337     int iRet = 0;
338     int iRows = 0;
339     int iCols = 0;
340     int iItemCount = 0;
341     int *piRowCount = 0;
342     int *piColPos = 0;
343     int iComplex = 0;
344
345     double *pdblR = NULL;
346     double *pdblI = NULL;
347
348     int *piOut = NULL;
349     int iOutLen = 0;
350
351     if (_bData)
352     {
353         //sparse
354
355         iComplex = isVarComplex(_pvCtx, _piAddr);
356         if (iComplex)
357         {
358             iRet = getAllocatedComplexSparseMatrix(_pvCtx, _piAddr, &iRows, &iCols, &iItemCount, &piRowCount, &piColPos, &pdblR, &pdblI);
359         }
360         else
361         {
362             iRet = getAllocatedSparseMatrix(_pvCtx, _piAddr, &iRows, &iCols, &iItemCount, &piRowCount, &piColPos, &pdblR);
363         }
364     }
365     else
366     {
367         //boolean sparse
368         iRet = getAllocatedBooleanSparseMatrix(_pvCtx, _piAddr, &iRows, &iCols, &iItemCount, &piRowCount, &piColPos);
369     }
370
371     if (iRet)
372     {
373         return 1;
374     }
375
376     //5 -> 4 for header + 1 for item count
377     iOutLen = 5 + iRows + iItemCount;
378
379     if (_bData)
380     {
381         iOutLen += iItemCount * (iComplex + 1) * sizeof(double) / sizeof(int);
382     }
383
384     piOut = (int *)MALLOC(iOutLen * sizeof(int));
385
386     piOut[0] = _bData ? sci_sparse : sci_boolean_sparse;
387     piOut[1] = iRows;
388     piOut[2] = iCols;
389     piOut[3] = iComplex;
390     piOut[4] = iItemCount;
391
392     memcpy(piOut + 5, piRowCount, iRows * sizeof(int));
393     memcpy(piOut + 5 + iRows, piColPos, iItemCount * sizeof(int));
394
395     if (_bData)
396     {
397         int iOne = 1;
398         double *pRealData = (double *)(piOut + 5 + iRows + iItemCount);
399
400         C2F(dcopy) (&iItemCount, pdblR, &iOne, pRealData, &iOne);
401         if (iComplex)
402         {
403             double *pImgData = pRealData + iItemCount;
404
405             C2F(dcopy) (&iItemCount, pdblI, &iOne, pImgData, &iOne);
406         }
407     }
408
409     *_piBuffer = piOut;
410     *_piBufferSize = iOutLen;
411
412     if (_bData)
413     {
414         if (iComplex)
415         {
416             freeAllocatedSparseMatrix(piRowCount, piColPos, pdblR);
417         }
418         else
419         {
420             freeAllocatedComplexSparseMatrix(piRowCount, piColPos, pdblR, pdblI);
421         }
422     }
423     else
424     {
425         freeAllocatedBooleanSparse(piRowCount, piColPos);
426     }
427
428     return 0;
429 }
430
431 int serialize_to_mpi(void *_pvCtx, int *_piAddr, int **_piBuffer, int *_piBufferSize)
432 {
433     switch (*_piAddr)
434     {
435         case sci_matrix:
436             return serialize_double(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
437             break;
438         case sci_strings:
439             return serialize_string(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
440             break;
441         case sci_boolean:
442             return serialize_boolean(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
443             break;
444         case sci_sparse:
445             return serialize_sparse(pvApiCtx, _piAddr, _piBuffer, _piBufferSize, TRUE);
446             break;
447         case sci_boolean_sparse:
448             return serialize_sparse(pvApiCtx, _piAddr, _piBuffer, _piBufferSize, FALSE);
449             break;
450         case sci_ints:
451             return serialize_int(pvApiCtx, _piAddr, _piBuffer, _piBufferSize);
452             break;
453         default:
454             return -1;
455             break;
456     }
457 }