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