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