Adding callback for C++ (still has bug for return values); adding struct as method...
[iot2.git] / iotjava / iotrmi / C++ / IoTRMIUtil.hpp
1 /** Class IoTRMIUtil provides methods that the upper
2  *  layers can use to transport and invoke methods
3  *  when using IoTSocket, IoTSocketClient and IoTSocketServer.
4  *
5  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
6  * @version     1.0
7  * @since       2016-10-18
8  */
9 #ifndef _IOTRMIUTIL_HPP__
10 #define _IOTRMIUTIL_HPP__
11
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <endian.h>
15 #include <cxxabi.h>
16 #include <cstdlib>
17 #include <memory>
18 #include <typeinfo>
19
20 #include <iostream>
21 #include <string>
22 #include <vector>
23 #include <string.h>
24
25 #include "IoTRMITypes.hpp"
26
27 using namespace std;
28
29 class IoTRMIUtil {
30
31         public:
32                 IoTRMIUtil();
33                 //~IoTRMIUtil();
34                 
35                 // Helper functions
36                 static void             printBytes(char* bytes, const int len, const bool hex);
37                 static int              hashCode(string str);
38                 static char*    getHashCodeBytes(string methodSign, char* bytes);
39                 int                     getTypeSize(string type);
40                 int                             getVarTypeSize(string type, void* paramObj);
41                 static int              getArrStringLength(vector<string> arrString);
42                 static int              getByteStringLength(vector<string> arrString);
43                 
44                 // Primitives to byte array
45                 static char*    shortToByteArray(short i, char* bytes);
46                 static char*    intToByteArray(int i, char* bytes);
47                 static char*    longToByteArray(int64_t i, char* bytes);
48                 static char*    floatToByteArray(float f, char* bytes);
49                 static char*    doubleToByteArray(double d, char* bytes);
50                 static char*    charToByteArray(char c, char* bytes);
51                 static char*    booleanToByteArray(bool c, char* bytes);
52                 static char*    stringToByteArray(string c, char* bytes);
53
54                 // Byte array to primitives
55                 static short*   byteArrayToShort(short* result, char* bytes);
56                 static int*     byteArrayToInt(int* result, char* bytes);
57                 static int64_t* byteArrayToLong(int64_t* result, char* bytes);
58                 static float*   byteArrayToFloat(float* result, char* bytes);
59                 static double*  byteArrayToDouble(double* result, char* bytes);
60                 static char*    byteArrayToChar(char* result, char* bytes);
61                 static bool*    byteArrayToBoolean(bool* result, char* bytes);
62                 static string*  byteArrayToString(string* result, char* bytes);
63                 static string*  byteArrayToString(string* result, char* bytes, int len);
64
65                 // Get parameter object from byte array
66                 static void*    getParamObject(void* retObj, const char* type, char* paramBytes, int len);
67                 static char*    getObjectBytes(char* retObjBytes, void* obj, const char* type);
68
69                 // Arrays to bytes
70                 static char*    arrShortToByteArray(vector<short> arrShort, char* bytes);
71                 static char*    arrIntToByteArray(vector<int> arrInt, char* bytes);
72                 static char*    arrLongToByteArray(vector<int64_t> arrInt, char* bytes);
73                 static char*    arrFloatToByteArray(vector<float> arrFloat, char* bytes);
74                 static char*    arrDoubleToByteArray(vector<double> arrDouble, char* bytes);
75                 static char*    arrCharToByteArray(vector<char> arrChar, char* bytes);
76                 static char*    arrBooleanToByteArray(vector<bool> arrBoolean, char* bytes);
77                 static char*    arrStringToByteArray(vector<string> arrString, char* bytes);
78
79                 // Bytes to array
80                 static vector<short>*   byteArrayToShortArray(vector<short>* result, char* bytes, int len);
81                 static vector<int>*     byteArrayToIntArray(vector<int>* result, char* bytes, int len);
82                 static vector<int64_t>* byteArrayToLongArray(vector<int64_t>* result, char* bytes, int len);
83                 static vector<float>*   byteArrayToFloatArray(vector<float>* result, char* bytes, int len);
84                 static vector<double>*  byteArrayToDoubleArray(vector<double>* result, char* bytes, int len);
85                 static vector<char>*    byteArrayToCharArray(vector<char>* result, char* bytes, int len);
86                 static vector<bool>*    byteArrayToBooleanArray(vector<bool>* result, char* bytes, int len);
87                 static vector<string>*  byteArrayToStringArray(vector<string>* result, char* bytes, int len);
88
89                 // Aggregator functions
90                 static char*    getArrayObjectBytes(char* retObjBytes, void* obj, const char* type);
91                 static void*    getArrayParamObject(void* retObj, const char* type, char* paramBytes, int len);
92
93                 // Constants
94                 const static int        OBJECT_ID_LEN = 4;      // 4 bytes = 32 bits
95                 const static int        METHOD_ID_LEN = 4;      // 4 bytes = 32 bits
96                 const static int        PARAM_LEN = 4;          // 4 bytes = 32 bits (4-byte field that stores the length of the param)
97                 const static int        CHAR_LEN = 2;           // 2 bytes (we follow Java convention)
98                 const static int        BOOL_LEN = 1;           // 1 byte
99                 
100         private:
101                 map<string,string>      mapPrimitives;
102                 map<string,int>         mapPrimitiveSizes;
103                 map<string,string>      mapNonPrimitives;
104 };
105
106
107 // Constructor
108 IoTRMIUtil::IoTRMIUtil() {
109
110         // Prepare vectors for inputs
111         std::vector<string> primJava (IoTRMITypes::primitivesJava, 
112                 IoTRMITypes::primitivesJava + sizeof(IoTRMITypes::primitivesJava)/sizeof(string));
113         std::vector<string> primCplus (IoTRMITypes::primitivesCplus, 
114                 IoTRMITypes::primitivesCplus + sizeof(IoTRMITypes::primitivesCplus)/sizeof(string));
115         std::vector<int> primSizes (IoTRMITypes::primitivesSizes, 
116                 IoTRMITypes::primitivesSizes + sizeof(IoTRMITypes::primitivesSizes)/sizeof(int));
117         std::vector<string> nonPrimJava (IoTRMITypes::nonPrimitivesJava, 
118                 IoTRMITypes::nonPrimitivesJava + sizeof(IoTRMITypes::nonPrimitivesJava)/sizeof(string));
119         std::vector<string> nonPrimCplus (IoTRMITypes::nonPrimitivesCplus, 
120                 IoTRMITypes::nonPrimitivesCplus + sizeof(IoTRMITypes::nonPrimitivesCplus)/sizeof(string));
121
122
123         // Write into maps
124         IoTRMITypes::arraysToMap(mapPrimitives, primJava, primCplus);
125         IoTRMITypes::arraysToMap(mapPrimitiveSizes, primJava, primSizes); 
126         IoTRMITypes::arraysToMap(mapNonPrimitives, nonPrimJava, nonPrimCplus);
127 }
128
129 // *************
130 //    Helpers
131 // *************
132 void IoTRMIUtil::printBytes(char* bytes, const int len, const bool hex) {
133
134         printf("[ ");
135         for (int i = 0; i < len; i++) {
136                 if (hex)        // print in hexadecimal
137                         printf("%x", bytes[i]);
138                 else
139                         printf("%d", bytes[i]);
140                 if (i < len - 1)
141                         printf(", ");
142         }
143         printf(" ]\n");
144 }
145
146
147 // Return hashCode value 
148 // This mimics the method Object.hashCode() in Java
149 int IoTRMIUtil::hashCode(string str)  
150 {
151         int hash = 0;
152         int len = str.length();
153         char c;
154         if (len == 0) 
155                 return hash;
156         
157         for (int i = 0; i < len; i++) {
158                 c = str.at(i);
159                 hash = (31*hash) + (int) c;
160         }
161
162         return hash;
163 }
164
165
166 char* IoTRMIUtil::getHashCodeBytes(string methodSign, char* bytes) {
167
168         int hash = hashCode(methodSign);
169         return intToByteArray(hash, bytes);
170 }
171
172
173 int IoTRMIUtil::getTypeSize(string type) {
174
175         // Handle the types and find the sizes
176         if (mapPrimitiveSizes.find(type) != mapPrimitiveSizes.end())
177                 return mapPrimitiveSizes.find(type)->second;
178         else
179                 return -1; // Size is unknown
180 }
181
182
183 // Get variable type size, e.g. strings, arrays, etc.
184 int IoTRMIUtil::getVarTypeSize(string type, void* paramObj) {
185
186         int paramLen = 0;
187         if (type.compare("string") == 0) {
188                 // Get the length of the string through void* casting to string*
189                 paramLen = (*(string*)paramObj).length();
190         } else if (type.compare("string[]") == 0) {
191                 paramLen = IoTRMIUtil::getByteStringLength(*(vector<string>*) paramObj);
192         } else if (type.compare("byte[]") == 0) {
193                 int dataSize = getTypeSize("byte");
194                 paramLen = (*(vector<char>*) paramObj).size() * dataSize;
195         } else if (type.compare("short[]") == 0) {
196                 int dataSize = getTypeSize("short");
197                 paramLen = (*(vector<short>*) paramObj).size() * dataSize;
198         } else if (type.compare("int[]") == 0) {
199                 int dataSize = getTypeSize("int");
200                 paramLen = (*(vector<int>*) paramObj).size() * dataSize;
201         } else if (type.compare("long[]") == 0) {
202                 int dataSize = getTypeSize("long");
203                 paramLen = (*(vector<int64_t>*) paramObj).size() * dataSize;
204         } else if (type.compare("float[]") == 0) {
205                 int dataSize = getTypeSize("float");
206                 paramLen = (*(vector<float>*) paramObj).size() * dataSize;
207         } else if (type.compare("double[]") == 0) {
208                 int dataSize = getTypeSize("double");
209                 paramLen = (*(vector<double>*) paramObj).size() * dataSize;
210         } else if (type.compare("bool[]") == 0) {
211                 int dataSize = getTypeSize("bool");
212                 paramLen = (*(vector<bool>*) paramObj).size() * dataSize;
213         } else if (type.compare("char[]") == 0) {
214                 int dataSize = getTypeSize("char");
215                 paramLen = (*(vector<char>*) paramObj).size() * dataSize;
216         } else {
217                 string error = "IoTRMICall: Unrecognizable type: " + type;
218                 throw error;
219         }
220
221         return paramLen;
222 }
223
224
225 int IoTRMIUtil::getArrStringLength(vector<string> arrString) {
226
227         int len = 0;
228         for (string& str : arrString) {
229                 len = len + str.length();
230         }
231         return len;
232 }
233
234
235 int IoTRMIUtil::getByteStringLength(vector<string> arrString) {
236
237         int len = PARAM_LEN + (PARAM_LEN*arrString.size()) + getArrStringLength(arrString);
238         return len;
239 }
240
241
242 // ****************************
243 //    Parameters Translation
244 // ****************************
245
246 // Getting parameter object based on received byte array
247 void* IoTRMIUtil::getParamObject(void* retObj, const char* type, char* paramBytes, int len) {
248
249         if (strcmp(type, "b") == 0 ||
250                 strcmp(type, "byte") == 0) {
251                 retObj = (void*) &paramBytes[0];
252         } else if ( strcmp(type, "s") == 0 ||
253                                 strcmp(type, "short") == 0) {
254                 retObj = (void*) byteArrayToShort((short*) retObj, paramBytes);
255         } else if ( strcmp(type, "i") == 0 ||
256                                 strcmp(type, "int") == 0) {
257                 retObj = (void*) byteArrayToInt((int*) retObj, paramBytes);
258         } else if ( strcmp(type, "l") == 0 ||
259                                 strcmp(type, "long") == 0) {
260                 retObj = (void*) byteArrayToLong((int64_t*) retObj, paramBytes);
261         } else if ( strcmp(type, "f") == 0 ||
262                                 strcmp(type, "float") == 0) {
263                 retObj = (void*) byteArrayToFloat((float*) retObj, paramBytes);
264         } else if ( strcmp(type, "d") == 0 ||
265                                 strcmp(type, "double") == 0) {
266                 retObj = (void*) byteArrayToDouble((double*) retObj, paramBytes);
267         } else if ( strcmp(type, "b") == 0 ||
268                                 strcmp(type, "bool") == 0) {
269                 retObj = (void*) byteArrayToBoolean((bool*) retObj, paramBytes);
270         } else if ( strcmp(type, "c") == 0 ||
271                                 strcmp(type, "char") == 0) {
272                 retObj = (void*) byteArrayToChar((char*) retObj, paramBytes);
273         } else if ( strcmp(type, "Ss") == 0 ||
274                                 strcmp(type, "string") == 0) {
275                 retObj = (void*) byteArrayToString((string*) retObj, paramBytes, len);
276         } else if ( string(type).find("[]") != string::npos) {
277                 // This is an array type, i.e. vector
278                 retObj = getArrayParamObject(retObj, type, paramBytes, len);
279         } else {
280                 string error = "IoTRMIUtil: Unrecognizable type: " + string(type);
281                 throw error;
282         }
283
284         return retObj;
285 }
286
287
288 // Get array of objects from byte array - overload getParamObject function
289 void* IoTRMIUtil::getArrayParamObject(void* retObj, const char* type, char* paramBytes, int len) {
290
291         if (strcmp(type, "byte[]") == 0) {
292                 retObj = (vector<char>*) paramBytes;
293         } else if (strcmp(type, "short[]") == 0) {
294                 retObj = byteArrayToShortArray((vector<short>*) retObj, paramBytes, len);
295         } else if (strcmp(type, "int[]") == 0) {
296                 retObj = byteArrayToIntArray((vector<int>*) retObj, paramBytes, len);
297         } else if (strcmp(type, "long[]") == 0) {
298                 retObj = byteArrayToLongArray((vector<int64_t>*) retObj, paramBytes, len);
299         } else if (strcmp(type, "float[]") == 0) {
300                 retObj = byteArrayToFloatArray((vector<float>*) retObj, paramBytes, len);
301         } else if (strcmp(type, "double[]") == 0) {
302                 retObj = byteArrayToDoubleArray((vector<double>*) retObj, paramBytes, len);
303         } else if (strcmp(type, "bool[]") == 0) {
304                 retObj = byteArrayToBooleanArray((vector<bool>*) retObj, paramBytes, len);
305         } else if (strcmp(type, "char[]") == 0) {
306                 retObj = byteArrayToCharArray((vector<char>*) retObj, paramBytes, len);
307         } else if (strcmp(type, "string[]") == 0) {
308                 retObj = byteArrayToStringArray((vector<string>*) retObj, paramBytes, len);
309         } else {
310                 string error = "IoTRMIUtil: Unrecognizable type: " + string(type);
311                 throw error;
312         }
313
314         return retObj;
315 }
316
317
318 // Getting byte array based on parameter and its type
319 char* IoTRMIUtil::getObjectBytes(char* retObjBytes, void* obj, const char* type) {
320
321         if (strcmp(type, "b") == 0 ||
322                 strcmp(type, "byte") == 0) {
323                 retObjBytes = (char*) obj;
324         } else if ( strcmp(type, "s") == 0 ||
325                                 strcmp(type, "short") == 0) {
326                 retObjBytes = shortToByteArray(*((short*) obj), retObjBytes);
327         } else if ( strcmp(type, "i") == 0 ||
328                                 strcmp(type, "int") == 0) {
329                 retObjBytes = intToByteArray(*((int*) obj), retObjBytes);
330         } else if ( strcmp(type, "l") == 0 ||
331                                 strcmp(type, "long") == 0) {
332                 retObjBytes = longToByteArray(*((int64_t*) obj), retObjBytes);
333         } else if ( strcmp(type, "f") == 0 ||
334                                 strcmp(type, "float") == 0) {
335                 retObjBytes = floatToByteArray(*((float*) obj), retObjBytes);
336         } else if ( strcmp(type, "d") == 0 ||
337                                 strcmp(type, "double") == 0) {
338                 retObjBytes = doubleToByteArray(*((double*) obj), retObjBytes);
339         } else if ( strcmp(type, "b") == 0 ||
340                                 strcmp(type, "bool") == 0) {
341                 retObjBytes = booleanToByteArray(*((bool*) obj), retObjBytes);
342         } else if ( strcmp(type, "c") == 0 ||
343                                 strcmp(type, "char") == 0) {
344                 retObjBytes = charToByteArray(*((char*) obj), retObjBytes);
345         } else if ( strcmp(type, "Ss") == 0 ||
346                                 strcmp(type, "string") == 0) {
347                 retObjBytes = stringToByteArray(*((string*) obj), retObjBytes);
348         } else if ( string(type).find("[]") != string::npos) {
349         // This is an array type, i.e. vector
350                 retObjBytes = getArrayObjectBytes(retObjBytes, obj, type);
351         } else {
352                 string error = "IoTRMIUtil: Unrecognizable type: " + string(type);
353                 throw error;
354         }
355
356         return retObjBytes;
357 }
358
359
360 // Getting byte array for arrays of primitives
361 char* IoTRMIUtil::getArrayObjectBytes(char* retObjBytes, void* obj, const char* type) {
362
363         if (strcmp(type, "byte[]") == 0) {
364                 retObjBytes = (char*) obj;
365         } else if (strcmp(type, "short[]") == 0) {
366                 retObjBytes = arrShortToByteArray(*((vector<short>*) obj), retObjBytes);
367         } else if (strcmp(type, "int[]") == 0) {
368                 retObjBytes = arrIntToByteArray(*((vector<int>*) obj), retObjBytes);
369         } else if (strcmp(type, "long[]") == 0) {
370                 retObjBytes = arrLongToByteArray(*((vector<int64_t>*) obj), retObjBytes);
371         } else if (strcmp(type, "float[]") == 0) {
372                 retObjBytes = arrFloatToByteArray(*((vector<float>*) obj), retObjBytes);
373         } else if (strcmp(type, "double[]") == 0) {
374                 retObjBytes = arrDoubleToByteArray(*((vector<double>*) obj), retObjBytes);
375         } else if (strcmp(type, "bool[]") == 0) {
376                 retObjBytes = arrBooleanToByteArray(*((vector<bool>*) obj), retObjBytes);
377         } else if (strcmp(type, "char[]") == 0) {
378                 retObjBytes = arrCharToByteArray(*((vector<char>*) obj), retObjBytes);
379         } else if (strcmp(type, "string[]") == 0) {
380                 retObjBytes = arrStringToByteArray(*((vector<string>*) obj), retObjBytes);
381         } else {
382                 string error = "IoTRMIUtil: Unrecognizable type: " + string(type);
383                 throw error;
384         }
385
386         return retObjBytes;
387 }
388
389
390 // Conversions
391 // Array handlers - we use vector data type and not traditional arrays
392 // Array to bytes
393 char* IoTRMIUtil::arrShortToByteArray(vector<short> arrShort, char* bytes) {
394
395         int pos = 0;
396         for (short& sht : arrShort) {
397                 char tmpBytes[sizeof(short)];
398                 shortToByteArray(sht, tmpBytes);
399                 memcpy(bytes + pos, tmpBytes, sizeof(short));
400                 pos = pos + sizeof(short);
401         }
402
403         return bytes;
404 }
405
406
407 char* IoTRMIUtil::arrIntToByteArray(vector<int> arrInt, char* bytes) {
408
409         int pos = 0;
410         for (int& in : arrInt) {
411                 char tmpBytes[sizeof(int)];
412                 intToByteArray(in, tmpBytes);
413                 memcpy(bytes + pos, tmpBytes, sizeof(int));
414                 pos = pos + sizeof(int);
415         }
416
417         return bytes;
418 }
419
420
421 char* IoTRMIUtil::arrLongToByteArray(vector<int64_t> arrLong, char* bytes) {
422
423         int pos = 0;
424         for (int64_t& lng : arrLong) {
425                 char tmpBytes[sizeof(int64_t)];
426                 longToByteArray(lng, tmpBytes);
427                 memcpy(bytes + pos, tmpBytes, sizeof(int64_t));
428                 pos = pos + sizeof(int64_t);
429         }
430
431         return bytes;
432 }
433
434
435 char* IoTRMIUtil::arrFloatToByteArray(vector<float> arrFloat, char* bytes) {
436
437         int pos = 0;
438         for (float& flt : arrFloat) {
439                 char tmpBytes[sizeof(float)];
440                 floatToByteArray(flt, tmpBytes);
441                 memcpy(bytes + pos, tmpBytes, sizeof(float));
442                 pos = pos + sizeof(float);
443         }
444
445         return bytes;
446 }
447
448
449 char* IoTRMIUtil::arrDoubleToByteArray(vector<double> arrDouble, char* bytes) {
450
451         int pos = 0;
452         for (double& dbl : arrDouble) {
453                 char tmpBytes[sizeof(double)];
454                 doubleToByteArray(dbl, tmpBytes);
455                 memcpy(bytes + pos, tmpBytes, sizeof(double));
456                 pos = pos + sizeof(double);
457         }
458
459         return bytes;
460 }
461
462
463 char* IoTRMIUtil::arrCharToByteArray(vector<char> arrChar, char* bytes) {
464
465         int pos = 0;
466         for (char& chr : arrChar) {
467                 char tmpBytes[CHAR_LEN];
468                 charToByteArray(chr, tmpBytes);
469                 memcpy(bytes + pos, tmpBytes, CHAR_LEN);
470                 pos = pos + CHAR_LEN;
471         }
472
473         return bytes;
474 }
475
476
477 char* IoTRMIUtil::arrBooleanToByteArray(vector<bool> arrBoolean, char* bytes) {
478
479         int pos = 0;
480         for (bool bl : arrBoolean) {
481                 char tmpBytes[BOOL_LEN];
482                 booleanToByteArray(bl, tmpBytes);
483                 memcpy(bytes + pos, tmpBytes, BOOL_LEN);
484                 pos = pos + BOOL_LEN;
485         }
486
487         return bytes;
488 }
489
490
491 char* IoTRMIUtil::arrStringToByteArray(vector<string> arrString, char* bytes) {
492
493         int pos = 0;
494         char strArrLenBytes[PARAM_LEN];
495         intToByteArray(arrString.size(), strArrLenBytes);
496         memcpy(bytes, strArrLenBytes, PARAM_LEN);
497         pos = pos + PARAM_LEN;
498         for (string& str : arrString) {
499
500                 // Copy string length
501                 int strLen = str.length();
502                 char strLenBytes[PARAM_LEN];
503                 intToByteArray(strLen, strLenBytes);
504                 memcpy(bytes + pos, strLenBytes, PARAM_LEN);
505                 pos = pos + PARAM_LEN;
506                 // Copy string
507                 char strBytes[strLen];
508                 stringToByteArray(str, strBytes);
509                 memcpy(bytes + pos, strBytes, strLen);
510                 pos = pos + strLen;
511         }
512
513         return bytes;
514 }
515
516
517 // Bytes to array
518 vector<short>* IoTRMIUtil::byteArrayToShortArray(vector<short>* result, char* bytes, int len) {
519
520         // Single element bytes
521         char elmt[sizeof(short)];
522         // Prepare vector
523         int arrLen = len/sizeof(short);
524         for(int i = 0; i < arrLen; i++) {
525                 int offset = i * sizeof(short);
526                 memcpy(elmt, bytes + offset, sizeof(short));
527                 short res = 0;
528                 byteArrayToShort(&res, elmt);
529                 result->push_back(res);
530         }
531
532         return result;
533 }
534
535
536 vector<int>* IoTRMIUtil::byteArrayToIntArray(vector<int>* result, char* bytes, int len) {
537
538         // Single element bytes
539         char elmt[sizeof(int)];
540         // Prepare vector
541         int arrLen = len/sizeof(int);
542         for(int i = 0; i < arrLen; i++) {
543                 int offset = i * sizeof(int);
544                 memcpy(elmt, bytes + offset, sizeof(int));
545                 int res = 0;
546                 byteArrayToInt(&res, elmt);
547                 result->push_back(res);
548         }
549
550         return result;
551 }
552
553
554 vector<int64_t>* IoTRMIUtil::byteArrayToLongArray(vector<int64_t>* result, char* bytes, int len) {
555
556         // Single element bytes
557         char elmt[sizeof(int64_t)];
558         // Prepare vector
559         int arrLen = len/sizeof(int64_t);
560         for(int i = 0; i < arrLen; i++) {
561                 int offset = i * sizeof(int64_t);
562                 memcpy(elmt, bytes + offset, sizeof(int64_t));
563                 int64_t res = 0;
564                 byteArrayToLong(&res, elmt);
565                 result->push_back(res);
566         }
567
568         return result;
569 }
570
571
572 vector<float>* IoTRMIUtil::byteArrayToFloatArray(vector<float>* result, char* bytes, int len) {
573
574         // Single element bytes
575         char elmt[sizeof(float)];
576         // Prepare vector
577         int arrLen = len/sizeof(float);
578         for(int i = 0; i < arrLen; i++) {
579                 int offset = i * sizeof(float);
580                 memcpy(elmt, bytes + offset, sizeof(float));
581                 float res = 0;
582                 byteArrayToFloat(&res, elmt);
583                 result->push_back(res);
584         }
585
586         return result;
587 }
588
589
590 vector<double>* IoTRMIUtil::byteArrayToDoubleArray(vector<double>* result, char* bytes, int len) {
591
592         // Single element bytes
593         char elmt[sizeof(double)];
594         // Prepare vector
595         int arrLen = len/sizeof(double);
596         for(int i = 0; i < arrLen; i++) {
597                 int offset = i * sizeof(double);
598                 memcpy(elmt, bytes + offset, sizeof(double));
599                 double res = 0;
600                 byteArrayToDouble(&res, elmt);
601                 result->push_back(res);
602         }
603
604         return result;
605 }
606
607
608 vector<char>* IoTRMIUtil::byteArrayToCharArray(vector<char>* result, char* bytes, int len) {
609
610         // Single element bytes
611         char elmt[CHAR_LEN];
612         // Prepare vector
613         int arrLen = len/CHAR_LEN;
614         for(int i = 0; i < arrLen; i++) {
615                 int offset = i * CHAR_LEN;
616                 memcpy(elmt, bytes + offset, CHAR_LEN);
617                 char res;
618                 byteArrayToChar(&res, elmt);
619                 result->push_back(res);
620         }
621
622         return result;
623 }
624
625
626 vector<bool>* IoTRMIUtil::byteArrayToBooleanArray(vector<bool>* result, char* bytes, int len) {
627
628         // Single element bytes
629         char elmt[BOOL_LEN];
630         // Prepare vector
631         int arrLen = len/BOOL_LEN;
632         for(int i = 0; i < arrLen; i++) {
633                 int offset = i * BOOL_LEN;
634                 memcpy(elmt, bytes + offset, BOOL_LEN);
635                 bool res = false;
636                 byteArrayToBoolean(&res, elmt);
637                 result->push_back(res);
638         }
639
640         return result;
641 }
642
643
644 vector<string>* IoTRMIUtil::byteArrayToStringArray(vector<string>* result, char* bytes, int len) {
645
646         // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
647         // Get string array length
648         int pos = 0;
649         char strArrLenBytes[PARAM_LEN];
650         memcpy(strArrLenBytes, bytes, PARAM_LEN);
651         int strArrLen = 0;
652         byteArrayToInt(&strArrLen, strArrLenBytes);
653         pos = pos + PARAM_LEN;
654         // Extract array of strings
655         for(int i = 0; i < strArrLen; i++) {
656
657                 // Extract string length
658                 char strLenBytes[PARAM_LEN];
659                 memcpy(strLenBytes, bytes + pos, PARAM_LEN);
660                 int strLen = 0;
661                 byteArrayToInt(&strLen, strLenBytes);
662                 pos = pos + PARAM_LEN;
663                 // Extract string
664                 char strBytes[strLen];
665                 memcpy(strBytes, bytes + pos, strLen);
666                 pos = pos + strLen;
667                 string tmpStr = "";
668                 // Note: Somehow we need to instantiate the string
669                 //              with the length here although we are passing
670                 //              an array of bytes with an exact length
671                 byteArrayToString(&tmpStr, strBytes, strLen);
672                 result->push_back(tmpStr);
673         }
674
675         return result;
676 }
677
678
679 // Conversions
680 // Primitives to byte array
681 char* IoTRMIUtil::shortToByteArray(short s, char* bytes) {
682
683         short sInvert = htobe16(s);
684         //short sInvert = htons(s);
685         memcpy(bytes, &sInvert, sizeof(short));
686
687         return bytes;
688 }
689
690
691 char* IoTRMIUtil::intToByteArray(int i, char* bytes) {
692
693         int iInvert = htobe32(i);
694         //int iInvert = htonl(i);
695         memcpy(bytes, &iInvert, sizeof(int));
696
697         return bytes;
698 }
699
700
701 char* IoTRMIUtil::longToByteArray(int64_t l, char* bytes) {
702
703         int64_t lInvert = htobe64(l);
704         memcpy(bytes, &lInvert, sizeof(int64_t));
705
706         return bytes;
707 }
708
709
710 char* IoTRMIUtil::floatToByteArray(float f, char* bytes) {
711
712         // Copy to int to allow the usage of htobeXX() functions
713         int i = 0;
714         memcpy(&i, &f, sizeof(float));
715         int iInvert = htobe32(i);
716         memcpy(bytes, &iInvert, sizeof(int));
717         
718         return bytes;
719 }
720
721
722 char* IoTRMIUtil::doubleToByteArray(double d, char* bytes) {
723
724         // Copy to int to allow the usage of htobeXX() functions
725         int64_t i = 0;
726         memcpy(&i, &d, sizeof(double));
727         int64_t iInvert = htobe64(i);
728         memcpy(bytes, &iInvert, sizeof(int64_t));
729         
730         return bytes;
731 }
732
733
734 char* IoTRMIUtil::charToByteArray(char c, char* bytes) {
735
736         // We need 2 bytes to accommodate Java char type, whose size is 2
737         bytes[0] = 0;
738         bytes[1] = c;
739
740         return bytes;
741 }
742
743
744 char* IoTRMIUtil::booleanToByteArray(bool b, char* bytes) {
745
746         bytes[0] = (b) ? 1 : 0;
747         return bytes;
748 }
749
750
751 char* IoTRMIUtil::stringToByteArray(string str, char* bytes) {
752
753         strcpy(bytes, str.c_str());
754         return bytes;
755 }
756
757
758 // Conversions
759 // Byte array to primitives
760 short* IoTRMIUtil::byteArrayToShort(short* result, char* bytes) {
761
762         short s = 0;
763         memcpy(&s, bytes, sizeof(short));
764         //short result = be16toh(s);
765         *result = be16toh(s);
766
767         return result;
768 }
769
770
771 int* IoTRMIUtil::byteArrayToInt(int* result, char* bytes) {
772
773         int i = 0;
774         memcpy(&i, bytes, sizeof(int));
775         *result = be32toh(i);
776
777         return result;
778 }
779
780
781 int64_t* IoTRMIUtil::byteArrayToLong(int64_t* result, char* bytes) {
782
783         int64_t l = 0;
784         memcpy(&l, bytes, sizeof(int64_t));
785         *result = be64toh(l);
786
787         return result;
788 }
789
790
791 float* IoTRMIUtil::byteArrayToFloat(float* result, char* bytes) {
792
793         // Copy to int to allow the usage of beXXtoh() functions
794         int i = 0;
795         memcpy(&i, bytes, sizeof(int));
796         int iInvert = be32toh(i);
797         memcpy(result, &iInvert, sizeof(float));
798
799         return result;
800 }
801
802
803 double* IoTRMIUtil::byteArrayToDouble(double* result, char* bytes) {
804
805         // Copy to int to allow the usage of beXXtoh() functions
806         int64_t i = 0;
807         memcpy(&i, bytes, sizeof(int64_t));
808         int64_t iInvert = be64toh(i);
809         memcpy(result, &iInvert, sizeof(double));
810
811         return result;
812 }
813
814
815 char* IoTRMIUtil::byteArrayToChar(char* result, char* bytes) {
816
817         *result = bytes[1];
818         return result;
819 }
820
821
822 bool* IoTRMIUtil::byteArrayToBoolean(bool* result, char* bytes) {
823
824         *result = (bytes[0]) ? true : false;
825         return result;
826 }
827
828
829 string* IoTRMIUtil::byteArrayToString(string* result, char* bytes) {
830
831         *result = string(bytes);
832         return result;
833 }
834
835
836 string* IoTRMIUtil::byteArrayToString(string* result, char* bytes, int strLen) {
837
838         *result = string(bytes, strLen);
839         return result;
840 }
841
842
843 #endif