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