Testing for list/vector data types
[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 if ( (string(type).find("<") != string::npos) &&
304                                 (string(type).find(">") != string::npos)) {
305                 // This is a vector/list type
306                 retObj = getArrayParamObject(retObj, type, paramBytes, len);
307         } else {
308                 cerr << "IoTRMIUtil: Unrecognizable type: " << type << endl;
309                 exit(-1);
310         }
311
312         return retObj;
313 }
314
315
316 // Get array of objects from byte array
317 void* IoTRMIUtil::getArrayParamObject(void* retObj, const char* type, char* paramBytes, int len) {
318
319         if ((strcmp(type, "byte*") == 0) ||
320                 (strcmp(type, "Byte*") == 0) ||
321                 (strcmp(type, "vector<Byte>") == 0)) {
322                 retObj = byteArrayToByteArray((vector<char>*) retObj, paramBytes, len);
323         } else if ( (strcmp(type, "short*") == 0) ||
324                                 (strcmp(type, "Short*") == 0) ||
325                                 (strcmp(type, "vector<Short>") == 0)) {
326                 retObj = byteArrayToShortArray((vector<short>*) retObj, paramBytes, len);
327         } else if ( (strcmp(type, "int*") == 0) ||
328                                 (strcmp(type, "Integer*") == 0) ||
329                                 (strcmp(type, "vector<Integer>") == 0)) {
330                 retObj = byteArrayToIntArray((vector<int>*) retObj, paramBytes, len);
331         } else if ( (strcmp(type, "long*") == 0) ||
332                                 (strcmp(type, "Long*") == 0) ||
333                                 (strcmp(type, "vector<Long>") == 0)) {
334                 retObj = byteArrayToLongArray((vector<int64_t>*) retObj, paramBytes, len);
335         } else if ( (strcmp(type, "float*") == 0) ||
336                                 (strcmp(type, "Float*") == 0) ||
337                                 (strcmp(type, "vector<Float>") == 0)) {
338                 retObj = byteArrayToFloatArray((vector<float>*) retObj, paramBytes, len);
339         } else if ( (strcmp(type, "double*") == 0) ||
340                                 (strcmp(type, "Double*") == 0) ||
341                                 (strcmp(type, "vector<Double>") == 0)) {
342                 retObj = byteArrayToDoubleArray((vector<double>*) retObj, paramBytes, len);
343         } else if ( (strcmp(type, "boolean*") == 0) ||
344                                 (strcmp(type, "Boolean*") == 0) ||
345                                 (strcmp(type, "vector<Boolean>") == 0)) {
346                 retObj = byteArrayToBooleanArray((vector<bool>*) retObj, paramBytes, len);
347         } else if ( (strcmp(type, "char*") == 0)      ||
348                                 (strcmp(type, "Character*") == 0) ||
349                                 (strcmp(type, "vector<Character>") == 0)) {
350                 retObj = byteArrayToCharArray((vector<char>*) retObj, paramBytes, len);
351         } else if ( (strcmp(type, "String*") == 0) ||
352                                 (strcmp(type, "vector<String>") == 0)) {
353                 retObj = byteArrayToStringArray((vector<string>*) retObj, paramBytes, len);
354         } else {
355                 cerr << "IoTRMIUtil: Unrecognizable type: " << type << endl;
356                 exit(-1);       
357         }
358
359         return retObj;
360 }
361
362
363 // Getting byte array based on parameter and its type
364 char* IoTRMIUtil::getObjectBytes(char* retObjBytes, void* obj, const char* type) {
365
366         if (strcmp(type, "b") == 0 ||
367                 strcmp(type, "byte") == 0) {
368                 retObjBytes = byteToByteArray(*((char*) obj), retObjBytes);             
369         } else if ( strcmp(type, "s") == 0 ||
370                                 strcmp(type, "short") == 0) {
371                 retObjBytes = shortToByteArray(*((short*) obj), retObjBytes);
372         } else if ( strcmp(type, "i") == 0 ||
373                                 strcmp(type, "int") == 0) {
374                 retObjBytes = intToByteArray(*((int*) obj), retObjBytes);
375         } else if ( strcmp(type, "l") == 0 ||
376                                 strcmp(type, "long") == 0) {
377                 retObjBytes = longToByteArray(*((int64_t*) obj), retObjBytes);
378         } else if ( strcmp(type, "f") == 0 ||
379                                 strcmp(type, "float") == 0) {
380                 retObjBytes = floatToByteArray(*((float*) obj), retObjBytes);
381         } else if ( strcmp(type, "d") == 0 ||
382                                 strcmp(type, "double") == 0) {
383                 retObjBytes = doubleToByteArray(*((double*) obj), retObjBytes);
384         } else if ( strcmp(type, "b") == 0 ||
385                                 strcmp(type, "boolean") == 0) {
386                 retObjBytes = booleanToByteArray(*((bool*) obj), retObjBytes);
387         } else if ( strcmp(type, "c") == 0 ||
388                                 strcmp(type, "char") == 0) {
389                 retObjBytes = charToByteArray(*((char*) obj), retObjBytes);
390         } else if ( strcmp(type, "Ss") == 0 ||
391                                 strcmp(type, "String") == 0) {
392                 retObjBytes = stringToByteArray(*((string*) obj), retObjBytes);
393         } else if ( string(type).find("*") != string::npos) {
394         // This is an array type, i.e. vector
395                 retObjBytes = getArrayObjectBytes(retObjBytes, obj, type);
396         } else if ( (string(type).find("<") != string::npos) &&
397                                 (string(type).find(">") != string::npos)) {
398         // This is a vector/list type
399                 retObjBytes = getArrayObjectBytes(retObjBytes, obj, type);
400         } else {
401                 cerr << "IoTRMIUtil: Unrecognizable type: " << type << endl;
402                 exit(-1);
403         }
404
405         return retObjBytes;
406 }
407
408
409 // Getting byte array for arrays of primitives
410 char* IoTRMIUtil::getArrayObjectBytes(char* retObjBytes, void* obj, const char* type) {
411
412         if ((strcmp(type, "byte*") == 0) ||
413                 (strcmp(type, "Byte*") == 0) ||
414                 (strcmp(type, "vector<Byte>") == 0)) {
415                 retObjBytes = arrByteToByteArray(*((vector<char>*) obj), retObjBytes);
416         } else if ( (strcmp(type, "short*") == 0) ||
417                                 (strcmp(type, "Short*") == 0) ||
418                                 (strcmp(type, "vector<Short>") == 0)) {
419                 retObjBytes = arrShortToByteArray(*((vector<short>*) obj), retObjBytes);
420         } else if ( (strcmp(type, "int*") == 0) ||
421                                 (strcmp(type, "Integer*") == 0) ||
422                                 (strcmp(type, "vector<Integer>") == 0)) {
423                 retObjBytes = arrIntToByteArray(*((vector<int>*) obj), retObjBytes);
424         } else if ( (strcmp(type, "long*") == 0) ||
425                                 (strcmp(type, "Long*") == 0) ||
426                                 (strcmp(type, "vector<Long>") == 0)) {
427                 retObjBytes = arrLongToByteArray(*((vector<int64_t>*) obj), retObjBytes);
428         } else if ( (strcmp(type, "float*") == 0) ||
429                                 (strcmp(type, "Float*") == 0) ||
430                                 (strcmp(type, "vector<Float>") == 0)) {
431                 retObjBytes = arrFloatToByteArray(*((vector<float>*) obj), retObjBytes);
432         } else if ( (strcmp(type, "double*") == 0) ||
433                                 (strcmp(type, "Double*") == 0) ||
434                                 (strcmp(type, "vector<Double>") == 0)) {
435                 retObjBytes = arrDoubleToByteArray(*((vector<double>*) obj), retObjBytes);
436         } else if ( (strcmp(type, "boolean*") == 0) ||
437                                 (strcmp(type, "Boolean*") == 0) ||
438                                 (strcmp(type, "vector<Boolean>") == 0)) {
439                 retObjBytes = arrBooleanToByteArray(*((vector<bool>*) obj), retObjBytes);
440         } else if ( (strcmp(type, "char*") == 0) ||
441                                 (strcmp(type, "Character*") == 0) ||
442                                 (strcmp(type, "vector<Character>") == 0)) {
443                 retObjBytes = arrCharToByteArray(*((vector<char>*) obj), retObjBytes);
444         } else if ( (strcmp(type, "String*") == 0) ||
445                                 (strcmp(type, "vector<String>") == 0)) {
446                 retObjBytes = arrStringToByteArray(*((vector<string>*) obj), retObjBytes);
447         } else {
448                 cerr << "IoTRMIUtil: Unrecognizable type: " << type << endl;
449                 exit(-1);
450         }
451
452         return retObjBytes;
453 }
454
455
456 // Conversions
457 // Array handlers - we use vector data type and not traditional arrays
458 // Array to bytes
459 char* IoTRMIUtil::arrByteToByteArray(vector<char> arrByte, char* bytes) {
460
461         int pos = 0;
462         for (char chr : arrByte) {
463                 char tmpBytes[BYTE_LEN];
464                 byteToByteArray(chr, tmpBytes);
465                 memcpy(bytes + pos, tmpBytes, BYTE_LEN);
466                 pos = pos + BYTE_LEN;
467         }
468
469         return bytes;
470 }
471
472
473 char* IoTRMIUtil::arrShortToByteArray(vector<short> arrShort, char* bytes) {
474
475         int pos = 0;
476         for (short& sht : arrShort) {
477                 char tmpBytes[sizeof(short)];
478                 shortToByteArray(sht, tmpBytes);
479                 memcpy(bytes + pos, tmpBytes, sizeof(short));
480                 pos = pos + sizeof(short);
481         }
482
483         return bytes;
484 }
485
486
487 char* IoTRMIUtil::arrIntToByteArray(vector<int> arrInt, char* bytes) {
488
489         int pos = 0;
490         for (int& in : arrInt) {
491                 char tmpBytes[sizeof(int)];
492                 intToByteArray(in, tmpBytes);
493                 memcpy(bytes + pos, tmpBytes, sizeof(int));
494                 pos = pos + sizeof(int);
495         }
496
497         return bytes;
498 }
499
500
501 char* IoTRMIUtil::arrLongToByteArray(vector<int64_t> arrLong, char* bytes) {
502
503         int pos = 0;
504         for (int64_t& lng : arrLong) {
505                 char tmpBytes[sizeof(int64_t)];
506                 longToByteArray(lng, tmpBytes);
507                 memcpy(bytes + pos, tmpBytes, sizeof(int64_t));
508                 pos = pos + sizeof(int64_t);
509         }
510
511         return bytes;
512 }
513
514
515 char* IoTRMIUtil::arrFloatToByteArray(vector<float> arrFloat, char* bytes) {
516
517         int pos = 0;
518         for (float& flt : arrFloat) {
519                 char tmpBytes[sizeof(float)];
520                 floatToByteArray(flt, tmpBytes);
521                 memcpy(bytes + pos, tmpBytes, sizeof(float));
522                 pos = pos + sizeof(float);
523         }
524
525         return bytes;
526 }
527
528
529 char* IoTRMIUtil::arrDoubleToByteArray(vector<double> arrDouble, char* bytes) {
530
531         int pos = 0;
532         for (double& dbl : arrDouble) {
533                 char tmpBytes[sizeof(double)];
534                 doubleToByteArray(dbl, tmpBytes);
535                 memcpy(bytes + pos, tmpBytes, sizeof(double));
536                 pos = pos + sizeof(double);
537         }
538
539         return bytes;
540 }
541
542
543 char* IoTRMIUtil::arrCharToByteArray(vector<char> arrChar, char* bytes) {
544
545         int pos = 0;
546         for (char& chr : arrChar) {
547                 char tmpBytes[CHAR_LEN];
548                 charToByteArray(chr, tmpBytes);
549                 memcpy(bytes + pos, tmpBytes, CHAR_LEN);
550                 pos = pos + CHAR_LEN;
551         }
552
553         return bytes;
554 }
555
556
557 char* IoTRMIUtil::arrBooleanToByteArray(vector<bool> arrBoolean, char* bytes) {
558
559         int pos = 0;
560         for (bool bl : arrBoolean) {
561                 char tmpBytes[BOOL_LEN];
562                 booleanToByteArray(bl, tmpBytes);
563                 memcpy(bytes + pos, tmpBytes, BOOL_LEN);
564                 pos = pos + BOOL_LEN;
565         }
566
567         return bytes;
568 }
569
570
571 char* IoTRMIUtil::arrStringToByteArray(vector<string> arrString, char* bytes) {
572
573         int pos = 0;
574         char strArrLenBytes[PARAM_LEN];
575         intToByteArray(arrString.size(), strArrLenBytes);
576         memcpy(bytes, strArrLenBytes, PARAM_LEN);
577         pos = pos + PARAM_LEN;
578         for (string& str : arrString) {
579
580                 // Copy string length
581                 int strLen = str.length();
582                 char strLenBytes[PARAM_LEN];
583                 intToByteArray(strLen, strLenBytes);
584                 memcpy(bytes + pos, strLenBytes, PARAM_LEN);
585                 pos = pos + PARAM_LEN;
586                 // Copy string
587                 char strBytes[strLen];
588                 stringToByteArray(str, strBytes);
589                 memcpy(bytes + pos, strBytes, strLen);
590                 pos = pos + strLen;
591         }
592
593         return bytes;
594 }
595
596
597 // Bytes to array
598 vector<char>* IoTRMIUtil::byteArrayToByteArray(vector<char>* result, char* bytes, int len) {
599
600         // Single element bytes
601         char elmt[BYTE_LEN];
602         // Prepare vector
603         int arrLen = len/BYTE_LEN;
604         for(int i = 0; i < arrLen; i++) {
605                 int offset = i * BYTE_LEN;
606                 memcpy(elmt, bytes + offset, BYTE_LEN);
607                 char res;
608                 byteArrayToByte(&res, elmt);
609                 result->push_back(res);
610         }
611
612         return result;
613 }
614
615
616 vector<short>* IoTRMIUtil::byteArrayToShortArray(vector<short>* result, char* bytes, int len) {
617
618         // Single element bytes
619         char elmt[sizeof(short)];
620         // Prepare vector
621         int arrLen = len/sizeof(short);
622         for(int i = 0; i < arrLen; i++) {
623                 int offset = i * sizeof(short);
624                 memcpy(elmt, bytes + offset, sizeof(short));
625                 short res = 0;
626                 byteArrayToShort(&res, elmt);
627                 result->push_back(res);
628         }
629
630         return result;
631 }
632
633
634 vector<int>* IoTRMIUtil::byteArrayToIntArray(vector<int>* result, char* bytes, int len) {
635
636         // Single element bytes
637         char elmt[sizeof(int)];
638         // Prepare vector
639         int arrLen = len/sizeof(int);
640         for(int i = 0; i < arrLen; i++) {
641                 int offset = i * sizeof(int);
642                 memcpy(elmt, bytes + offset, sizeof(int));
643                 int res = 0;
644                 byteArrayToInt(&res, elmt);
645                 result->push_back(res);
646         }
647
648         return result;
649 }
650
651
652 vector<int64_t>* IoTRMIUtil::byteArrayToLongArray(vector<int64_t>* result, char* bytes, int len) {
653
654         // Single element bytes
655         char elmt[sizeof(int64_t)];
656         // Prepare vector
657         int arrLen = len/sizeof(int64_t);
658         for(int i = 0; i < arrLen; i++) {
659                 int offset = i * sizeof(int64_t);
660                 memcpy(elmt, bytes + offset, sizeof(int64_t));
661                 int64_t res = 0;
662                 byteArrayToLong(&res, elmt);
663                 result->push_back(res);
664         }
665
666         return result;
667 }
668
669
670 vector<float>* IoTRMIUtil::byteArrayToFloatArray(vector<float>* result, char* bytes, int len) {
671
672         // Single element bytes
673         char elmt[sizeof(float)];
674         // Prepare vector
675         int arrLen = len/sizeof(float);
676         for(int i = 0; i < arrLen; i++) {
677                 int offset = i * sizeof(float);
678                 memcpy(elmt, bytes + offset, sizeof(float));
679                 float res = 0;
680                 byteArrayToFloat(&res, elmt);
681                 result->push_back(res);
682         }
683
684         return result;
685 }
686
687
688 vector<double>* IoTRMIUtil::byteArrayToDoubleArray(vector<double>* result, char* bytes, int len) {
689
690         // Single element bytes
691         char elmt[sizeof(double)];
692         // Prepare vector
693         int arrLen = len/sizeof(double);
694         for(int i = 0; i < arrLen; i++) {
695                 int offset = i * sizeof(double);
696                 memcpy(elmt, bytes + offset, sizeof(double));
697                 double res = 0;
698                 byteArrayToDouble(&res, elmt);
699                 result->push_back(res);
700         }
701
702         return result;
703 }
704
705
706 vector<char>* IoTRMIUtil::byteArrayToCharArray(vector<char>* result, char* bytes, int len) {
707
708         // Single element bytes
709         char elmt[CHAR_LEN];
710         // Prepare vector
711         int arrLen = len/CHAR_LEN;
712         for(int i = 0; i < arrLen; i++) {
713                 int offset = i * CHAR_LEN;
714                 memcpy(elmt, bytes + offset, CHAR_LEN);
715                 char res;
716                 byteArrayToChar(&res, elmt);
717                 result->push_back(res);
718         }
719
720         return result;
721 }
722
723
724 vector<bool>* IoTRMIUtil::byteArrayToBooleanArray(vector<bool>* result, char* bytes, int len) {
725
726         // Single element bytes
727         char elmt[BOOL_LEN];
728         // Prepare vector
729         int arrLen = len/BOOL_LEN;
730         for(int i = 0; i < arrLen; i++) {
731                 int offset = i * BOOL_LEN;
732                 memcpy(elmt, bytes + offset, BOOL_LEN);
733                 bool res = false;
734                 byteArrayToBoolean(&res, elmt);
735                 result->push_back(res);
736         }
737
738         return result;
739 }
740
741
742 vector<string>* IoTRMIUtil::byteArrayToStringArray(vector<string>* result, char* bytes, int len) {
743
744         // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
745         // Get string array length
746         int pos = 0;
747         char strArrLenBytes[PARAM_LEN];
748         memcpy(strArrLenBytes, bytes, PARAM_LEN);
749         int strArrLen = 0;
750         byteArrayToInt(&strArrLen, strArrLenBytes);
751         pos = pos + PARAM_LEN;
752         // Extract array of strings
753         for(int i = 0; i < strArrLen; i++) {
754
755                 // Extract string length
756                 char strLenBytes[PARAM_LEN];
757                 memcpy(strLenBytes, bytes + pos, PARAM_LEN);
758                 int strLen = 0;
759                 byteArrayToInt(&strLen, strLenBytes);
760                 pos = pos + PARAM_LEN;
761                 // Extract string
762                 char strBytes[strLen];
763                 memcpy(strBytes, bytes + pos, strLen);
764                 pos = pos + strLen;
765                 string tmpStr = "";
766                 // Note: Somehow we need to instantiate the string
767                 //              with the length here although we are passing
768                 //              an array of bytes with an exact length
769                 byteArrayToString(&tmpStr, strBytes, strLen);
770                 result->push_back(tmpStr);
771         }
772
773         return result;
774 }
775
776
777 // Conversions
778 // Primitives to byte array
779 char* IoTRMIUtil::byteToByteArray(char c, char* bytes) {
780
781         // Just copy the char into char*
782         bytes[0] = c;
783
784         return bytes;
785 }
786
787
788 char* IoTRMIUtil::shortToByteArray(short s, char* bytes) {
789
790         short sInvert = htobe16(s);
791         //short sInvert = htons(s);
792         memcpy(bytes, &sInvert, sizeof(short));
793
794         return bytes;
795 }
796
797
798 char* IoTRMIUtil::intToByteArray(int i, char* bytes) {
799
800         int iInvert = htobe32(i);
801         //int iInvert = htonl(i);
802         memcpy(bytes, &iInvert, sizeof(int));
803
804         return bytes;
805 }
806
807
808 char* IoTRMIUtil::longToByteArray(int64_t l, char* bytes) {
809
810         int64_t lInvert = htobe64(l);
811         memcpy(bytes, &lInvert, sizeof(int64_t));
812
813         return bytes;
814 }
815
816
817 char* IoTRMIUtil::floatToByteArray(float f, char* bytes) {
818
819         // Copy to int to allow the usage of htobeXX() functions
820         int i = 0;
821         memcpy(&i, &f, sizeof(float));
822         int iInvert = htobe32(i);
823         memcpy(bytes, &iInvert, sizeof(int));
824         
825         return bytes;
826 }
827
828
829 char* IoTRMIUtil::doubleToByteArray(double d, char* bytes) {
830
831         // Copy to int to allow the usage of htobeXX() functions
832         int64_t i = 0;
833         memcpy(&i, &d, sizeof(double));
834         int64_t iInvert = htobe64(i);
835         memcpy(bytes, &iInvert, sizeof(int64_t));
836         
837         return bytes;
838 }
839
840
841 char* IoTRMIUtil::charToByteArray(char c, char* bytes) {
842
843         // We need 2 bytes to accommodate Java char type, whose size is 2
844         bytes[0] = 0;
845         bytes[1] = c;
846
847         return bytes;
848 }
849
850
851 char* IoTRMIUtil::booleanToByteArray(bool b, char* bytes) {
852
853         bytes[0] = (b) ? 1 : 0;
854         return bytes;
855 }
856
857
858 char* IoTRMIUtil::stringToByteArray(string str, char* bytes) {
859
860         strcpy(bytes, str.c_str());
861         return bytes;
862 }
863
864
865 // Conversions
866 // Byte array to primitives
867 short* IoTRMIUtil::byteArrayToShort(short* result, char* bytes) {
868
869         short s = 0;
870         memcpy(&s, bytes, sizeof(short));
871         //short result = be16toh(s);
872         *result = be16toh(s);
873
874         return result;
875 }
876
877
878 int* IoTRMIUtil::byteArrayToInt(int* result, char* bytes) {
879
880         int i = 0;
881         memcpy(&i, bytes, sizeof(int));
882         *result = be32toh(i);
883
884         return result;
885 }
886
887
888 int64_t* IoTRMIUtil::byteArrayToLong(int64_t* result, char* bytes) {
889
890         int64_t l = 0;
891         memcpy(&l, bytes, sizeof(int64_t));
892         *result = be64toh(l);
893
894         return result;
895 }
896
897
898 float* IoTRMIUtil::byteArrayToFloat(float* result, char* bytes) {
899
900         // Copy to int to allow the usage of beXXtoh() functions
901         int i = 0;
902         memcpy(&i, bytes, sizeof(int));
903         int iInvert = be32toh(i);
904         memcpy(result, &iInvert, sizeof(float));
905
906         return result;
907 }
908
909
910 double* IoTRMIUtil::byteArrayToDouble(double* result, char* bytes) {
911
912         // Copy to int to allow the usage of beXXtoh() functions
913         int64_t i = 0;
914         memcpy(&i, bytes, sizeof(int64_t));
915         int64_t iInvert = be64toh(i);
916         memcpy(result, &iInvert, sizeof(double));
917
918         return result;
919 }
920
921
922 char* IoTRMIUtil::byteArrayToByte(char* result, char* bytes) {
923
924         *result = bytes[0];
925         return result;
926 }
927
928
929 char* IoTRMIUtil::byteArrayToChar(char* result, char* bytes) {
930
931         *result = bytes[1];
932         return result;
933 }
934
935
936 bool* IoTRMIUtil::byteArrayToBoolean(bool* result, char* bytes) {
937
938         *result = (bytes[0]) ? true : false;
939         return result;
940 }
941
942
943 string* IoTRMIUtil::byteArrayToString(string* result, char* bytes) {
944
945         *result = string(bytes);
946         return result;
947 }
948
949
950 string* IoTRMIUtil::byteArrayToString(string* result, char* bytes, int strLen) {
951
952         *result = string(bytes, strLen);
953         return result;
954 }
955
956
957 #endif