Fork of the official mbed C/C++ SDK provides the software platform and libraries to build your applications. The fork has the documentation converted to Doxygen format

Dependents:   NervousPuppySprintOne NervousPuppySprint2602 Robot WarehouseBot1 ... more

Fork of mbed by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rpc.h Source File

rpc.h

00001 /* mbed Microcontroller Library - RPC
00002  * Copyright (c) 2008-2009 ARM Limited. All rights reserved.
00003  */ 
00004  
00005 #ifndef MBED_RPC_H
00006 #define MBED_RPC_H
00007 
00008 /**  Helpers for rpc handling.
00009  */
00010 
00011 #include <stdlib.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <ctype.h>
00015 #include "Base.h"
00016 
00017 #include "PinNames.h"
00018 #include <stdint.h>
00019 
00020 namespace mbed {
00021 
00022 /** Parses and returns a value from a string.
00023  *
00024  *  @param arg The string to pase
00025  *  @param next If not NULL a pointer to after the last 
00026  *    character parsed is written here
00027  */
00028 template<typename T> T parse_arg(const char *arg, const char **next);
00029 
00030 inline char parse_char(const char *arg, const char **next) {
00031     char c = *arg++;
00032     if(c == '\\') {
00033         c = *arg++;
00034         switch(c) {
00035         case 'a': c = '\a'; break;
00036         case 'b': c = '\b'; break;
00037         case 't': c = '\t'; break;
00038         case 'n': c = '\n'; break;
00039         case 'v': c = '\v'; break;
00040         case 'f': c = '\f'; break;
00041         case 'r': c = '\r'; break;
00042         case 'x': 
00043             {
00044                 /* two-character hexadecimal */
00045                 char buf[3];
00046                 buf[0] = *arg++;
00047                 buf[1] = *arg++;
00048                 buf[2] = 0;
00049                 c = strtol(buf, NULL, 16); 
00050             }
00051             break;
00052         default: 
00053             if(isdigit(c)) {
00054                 /* three-character octal */
00055                 char buf[4];
00056                 buf[0] = c;
00057                 buf[1] = *arg++;
00058                 buf[2] = *arg++;
00059                 buf[3] = 0;
00060                 c = strtol(buf, NULL, 8); 
00061             }
00062             break;
00063         }
00064     }
00065     *next = arg;
00066     return c;
00067 }
00068 
00069 /* signed integer types */
00070 
00071 template<> inline int parse_arg<int>(const char *arg, const char **next) {
00072     if(arg[0] == '\'') {
00073         char c = parse_char(arg+1, &arg);
00074         if(next != NULL) *next = arg+1;
00075         return c;
00076     } else {
00077         return strtol(arg, const_cast<char**>(next), 0);        
00078     }
00079 }
00080 
00081 template<> inline char parse_arg<char>(const char *arg, const char **next) {
00082     return parse_arg<int>(arg,next);
00083 }
00084 
00085 template<> inline short int parse_arg<short int>(const char *arg, const char **next) {
00086     return parse_arg<int>(arg,next);
00087 }
00088 
00089 template<> inline long int parse_arg<long int>(const char *arg, const char **next) {
00090     return parse_arg<int>(arg,next);
00091 }
00092 
00093 template<> inline long long parse_arg<long long>(const char *arg, const char **next) {
00094     return strtoll(arg, const_cast<char**>(next), 0);
00095 }
00096 
00097 /* unsigned integer types */
00098 
00099 template<> inline unsigned int parse_arg<unsigned int>(const char *arg, const char **next) {
00100     if(arg[0] == '\'') {
00101         char c = parse_char(arg+1, &arg);
00102         if(next != NULL) *next = arg+1;
00103         return c;
00104     } else {
00105         return strtoul(arg, const_cast<char**>(next), 0);        
00106     }
00107 }
00108 
00109 template<> inline unsigned char parse_arg<unsigned char>(const char *arg, const char **next) {
00110     return parse_arg<unsigned int>(arg,next);
00111 }
00112 
00113 template<> inline unsigned short int parse_arg<unsigned short int>(const char *arg, const char **next) {
00114     return parse_arg<unsigned int>(arg,next);
00115 }
00116 
00117 template<> inline unsigned long int parse_arg<unsigned long int>(const char *arg, const char **next) {
00118     return parse_arg<unsigned int>(arg,next);
00119 }
00120 
00121 template<> inline unsigned long long parse_arg<unsigned long long>(const char *arg, const char **next) {
00122     return strtoull(arg, const_cast<char**>(next), 0);
00123 }
00124 
00125 /* floating types */
00126 
00127 template<> inline float parse_arg<float>(const char *arg, const char **next) {
00128 #if !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 410000
00129     return strtof(arg,const_cast<char**>(next));
00130 #elif __ARMCC_VERSION >= 310000
00131     /* bug in header means no using declaration for strtof */
00132     return std::strtof(arg,const_cast<char**>(next));    
00133 #else
00134     /* strtof not supported */
00135     return strtod(arg,const_cast<char**>(next));
00136 #endif
00137 }
00138 
00139 template<> inline double parse_arg<double>(const char *arg, const char **next) {
00140     return strtod(arg,const_cast<char**>(next));
00141 }
00142 
00143 template<> inline long double parse_arg<long double>(const char *arg, const char **next) {
00144     return strtod(arg,const_cast<char**>(next));
00145 }
00146 
00147 /* string */
00148 
00149 template<> inline char *parse_arg<char*>(const char *arg, const char **next) {
00150     const char *ptr = arg;
00151     char *res = NULL;
00152     if(*arg == '"') {
00153         /* quoted string */
00154         ptr = ++arg;
00155         int len = 0;
00156         /* find the end (and length) of the quoted string */
00157         for(char c = *ptr; c != 0 && c != '"'; c = *++ptr) {
00158             len++;
00159             if(c == '\\') {
00160                 ptr++;
00161             }
00162         }
00163         /* copy the quoted string, and unescape characters */
00164         if(len != 0) {
00165             res = new char[len+1];
00166             char *resptr = res;
00167             while(arg != ptr) {
00168                 *resptr++ = parse_char(arg, &arg);
00169             }
00170             *resptr = 0;
00171         }
00172     } else {
00173         /* unquoted string */
00174         while(isalnum(*ptr) || *ptr=='_') {
00175             ptr++;
00176         }
00177         int len = ptr-arg;
00178         if(len!=0) {
00179             res = new char[len+1];
00180             memcpy(res, arg, len);
00181             res[len] = 0;
00182         }
00183     }
00184 
00185     if(next != NULL) {
00186         *next = ptr;
00187     }
00188     return res;
00189 }
00190 
00191 template<> inline const char *parse_arg<const char*>(const char *arg, const char **next) {
00192     return parse_arg<char*>(arg,next);
00193 }
00194 
00195 /* Pins */
00196 
00197 
00198 inline PinName parse_pins(const char *str) {
00199     const PinName pin_names[] = {p5, p6, p7, p8, p9, p10, p11, p12, p13, p14
00200                                 , p15, p16, p17, p18, p19, p20, p21, p22, p23
00201                                 , p24, p25, p26, p27, p28, p29, p30};
00202 
00203     if(str[0] == 'P') { // Pn_n
00204         uint32_t port = str[1] - '0';
00205         uint32_t pin = str[3] - '0'; // Pn_n
00206         uint32_t pin2 = str[4] - '0'; // Pn_nn
00207         if(pin2 <= 9) {
00208             pin = pin * 10 + pin2;
00209         }
00210 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
00211         return (PinName)(LPC_GPIO0_BASE + port * 32 + pin);
00212 #elif defined(TARGET_LPC11U24)
00213         return (PinName)(port * 32 + pin);
00214 #endif
00215     } else if(str[0] == 'p') {  // pn
00216         uint32_t pin = str[1] - '0'; // pn
00217         uint32_t pin2 = str[2] - '0'; // pnn
00218         if(pin2 <= 9) {
00219                   pin = pin * 10 + pin2;
00220         }
00221         if(pin < 5 || pin > 30) {
00222               return NC;
00223         }
00224         return pin_names[pin - 5];
00225     } else if(str[0] == 'L') {  // LEDn
00226         switch(str[3]) {
00227             case '1' : return LED1;
00228             case '2' : return LED2;
00229             case '3' : return LED3;
00230             case '4' : return LED4;
00231         }
00232     } else if(str[0] == 'U') {  // USB?X
00233         switch(str[3]) {
00234             case 'T' : return USBTX;
00235             case 'R' : return USBRX;
00236         }
00237     }
00238     return NC;
00239 }
00240 
00241 template<> inline PinName parse_arg<PinName>(const char *arg, const char **next) {
00242     const char *ptr = arg;
00243     PinName pinname = NC;
00244     while(isalnum(*ptr) || *ptr=='_') {
00245         ptr++;
00246     }
00247     int len = ptr-arg;
00248     if(len!=0) {
00249         pinname = parse_pins(arg);
00250     
00251     }
00252     if(next != NULL) {
00253         *next = ptr;
00254     }
00255     return pinname;
00256 }
00257 
00258 
00259 /** Writes a value in to a result string in an appropriate manner
00260  *
00261  *  @param val The value to write
00262  *  @param result A pointer to the array to write the value into
00263  */
00264 template<typename T> void write_result(T val, char *result);
00265 
00266 /* signed integer types */
00267 
00268 template<> inline void write_result<char>(char val, char *result) {
00269     result[0] = val;
00270     result[1] = '\0';
00271 }
00272 
00273 template<> inline void write_result<short int>(short int val, char *result) {
00274     sprintf(result, "%hi", val); 
00275 }
00276 
00277 template<> inline void write_result<int>(int val, char *result) {
00278     sprintf(result, "%i", val); 
00279 }
00280 
00281 template<> inline void write_result<long int>(long int val, char *result) {
00282     sprintf(result, "%li", val); 
00283 }
00284 
00285 template<> inline void write_result<long long int>(long long int val, char *result) {
00286     sprintf(result, "%lli", val); 
00287 }
00288 
00289 /* unsigned integer types */
00290 
00291 template<> inline void write_result<unsigned char>(unsigned char val, char *result) {
00292     result[0] = val;
00293     result[1] = '\0';
00294 }
00295 
00296 template<> inline void write_result<unsigned short int>(unsigned short int val, char *result) {
00297     sprintf(result, "%hu", val); 
00298 }
00299 
00300 template<> inline void write_result<unsigned int>(unsigned int val, char *result) {
00301     sprintf(result, "%u", val); 
00302 }
00303 
00304 template<> inline void write_result<unsigned long int>(unsigned long int val, char *result) {
00305     sprintf(result, "%lu", val); 
00306 }
00307 
00308 template<> inline void write_result<unsigned long long int>(unsigned long long int val, char *result) {
00309     sprintf(result, "%llu", val); 
00310 }
00311 
00312 /* floating types */
00313 
00314 template<> inline void write_result<float>(float val, char *result) {
00315     sprintf(result, "%.17g", val); 
00316 }
00317 
00318 template<> inline void write_result<double>(double val, char *result) {
00319     sprintf(result, "%.17g", val); 
00320 }
00321 
00322 template<> inline void write_result<long double>(long double val, char *result) {
00323     sprintf(result, "%.17Lg", val); 
00324 }
00325 
00326 
00327 /* string */
00328 
00329 template<> inline void write_result<char*>(char *val, char *result) {
00330     if(val==NULL) {
00331         result[0] = 0;
00332     } else {
00333         strcpy(result, val);
00334     }
00335 }
00336 
00337 template<> inline void write_result<const char*>(const char *val, char *result) {
00338     if(val==NULL) {
00339         result[0] = 0;
00340     } else {
00341         strcpy(result, val);
00342     }
00343 }
00344 
00345 
00346 inline const char *next_arg(const char* next) {
00347     while(*next == ' ') next++;
00348     if(*next == ',' || *next == '?') next++;
00349     while(*next == ' ') next++;
00350     return next;
00351 }
00352 
00353 
00354 /** rpc_method_caller
00355  */
00356 template<class T, void (T::*member)(const char *,char *)> 
00357 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00358     (static_cast<T*>(this_ptr)->*member)(arguments,result); 
00359 }
00360 
00361 
00362 /** rpc_method_caller
00363  */
00364 template<class T, void (T::*member)()> 
00365 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) { 
00366     (static_cast<T*>(this_ptr)->*member)(); 
00367     if(result != NULL) {
00368         result[0] = '\0';
00369     }
00370 }
00371 
00372 
00373 /** rpc_method_caller
00374  */
00375 template<class T, typename A1, void (T::*member)(A1)> 
00376 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00377 
00378     const char *next = arguments;
00379     A1 arg1 = parse_arg<A1>(next_arg(next),NULL);
00380 
00381     (static_cast<T*>(this_ptr)->*member)(arg1); 
00382     if(result != NULL) {
00383         result[0] = '\0';
00384     }
00385 }
00386 
00387 
00388 /** rpc_method_caller
00389  */
00390 template<class T, typename A1, typename A2, void (T::*member)(A1,A2)> 
00391 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00392 
00393     const char *next = arguments;
00394     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00395     A2 arg2 = parse_arg<A2>(next_arg(next),NULL);
00396 
00397     (static_cast<T*>(this_ptr)->*member)(arg1,arg2);
00398     if(result != NULL) {
00399         result[0] = '\0';
00400     }
00401 }
00402 
00403 
00404 /** rpc_method_caller
00405  */
00406 template<class T, typename A1, typename A2, typename A3, void (T::*member)(A1,A2,A3)> 
00407 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00408 
00409     const char *next = arguments;
00410     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00411     A2 arg2 = parse_arg<A2>(next_arg(next),&next);
00412     A3 arg3 = parse_arg<A3>(next_arg(next),NULL);
00413 
00414     (static_cast<T*>(this_ptr)->*member)(arg1,arg2,arg3);
00415     if(result != NULL) {
00416         result[0] = '\0';
00417     }
00418 }
00419 
00420 
00421 /** rpc_method_caller
00422  */
00423 template<typename R, class T, R (T::*member)()> 
00424 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) { 
00425     R res = (static_cast<T*>(this_ptr)->*member)();
00426     if(result != NULL) {
00427         write_result<R>(res, result);
00428     }
00429 }
00430 
00431 
00432 /** rpc_method_caller
00433  */
00434 template<typename R, class T, typename A1, R (T::*member)(A1)> 
00435 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00436 
00437     const char *next = arguments;
00438     A1 arg1 = parse_arg<A1>(next_arg(next),NULL);
00439 
00440     R res = (static_cast<T*>(this_ptr)->*member)(arg1);
00441     if(result != NULL) {
00442         write_result<R>(res, result);
00443     }
00444 }
00445 
00446 
00447 /** rpc_method_caller
00448  */
00449 template<typename R, class T, typename A1, typename A2, R (T::*member)(A1,A2)> 
00450 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00451 
00452     const char *next = arguments;
00453     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00454     A2 arg2 = parse_arg<A2>(next_arg(next),NULL);
00455 
00456     R res = (static_cast<T*>(this_ptr)->*member)(arg1,arg2);
00457     if(result != NULL) {
00458         write_result<R>(res, result);
00459     }
00460 }
00461 
00462 
00463 /** rpc_method_caller
00464  */
00465 template<typename R, class T, typename A1, typename A2, typename A3, R (T::*member)(A1,A2,A3)> 
00466 void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
00467 
00468     const char *next = arguments;
00469     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00470     A2 arg2 = parse_arg<A2>(next_arg(next),&next);
00471     A3 arg3 = parse_arg<A3>(next_arg(next),NULL);
00472 
00473     R res = (static_cast<T*>(this_ptr)->*member)(arg1,arg2,arg3);
00474     if(result != NULL) {
00475         write_result<R>(res, result);
00476     }
00477 }
00478 
00479 
00480 /** rpc_function caller
00481  */
00482 template<typename R, R (*func)()>
00483 void rpc_function_caller(const char *arguments, char *result) {
00484     R res = (*func)();
00485     if(result != NULL) {
00486         write_result<R>(res, result);
00487     }
00488 }
00489 
00490 
00491 /** rpc_function caller
00492  */
00493 template<typename R, typename A1, R (*func)(A1)>
00494 void rpc_function_caller(const char *arguments, char *result) {
00495     A1 arg1 = parse_arg<A1>(next_arg(arguments),NULL);
00496     R res = (*func)(arg1);
00497     if(result != NULL) {
00498         write_result<R>(res, result);
00499     }
00500 }
00501 
00502 
00503 /** rpc_function caller
00504  */
00505 template<typename R, typename A1, typename A2, R (*func)(A1,A2)>
00506 void rpc_function_caller(const char *arguments, char *result) {
00507 
00508     const char *next = arguments;
00509     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00510     A2 arg2 = parse_arg<A2>(next_arg(next),NULL);
00511 
00512     R res = (*func)(arg1,arg2);
00513     if(result != NULL) {
00514         write_result<R>(res, result);
00515     }
00516 }
00517 
00518 
00519 /** rpc_function caller
00520  */
00521 template<typename R, typename A1, typename A2, typename A3, R (*func)(A1,A2,A3)>
00522 void rpc_function_caller(const char *arguments, char *result) {
00523 
00524     const char *next = arguments;
00525     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00526     A2 arg2 = parse_arg<A2>(next_arg(next),&next);
00527     A3 arg3 = parse_arg<A3>(next_arg(next),NULL);
00528 
00529     R res = (*func)(arg1,arg2,arg3);
00530     if(result != NULL) {
00531         write_result<R>(res, result);
00532     }
00533 }
00534 
00535 
00536 /** rpc_function caller
00537  */
00538 template<typename R, typename A1, typename A2, typename A3, typename A4, R (*func)(A1,A2,A3,A4)>
00539 void rpc_function_caller(const char *arguments, char *result) {
00540 
00541     const char *next = arguments;
00542     A1 arg1 = parse_arg<A1>(next_arg(next),&next);
00543     A2 arg2 = parse_arg<A2>(next_arg(next),&next);
00544     A3 arg3 = parse_arg<A3>(next_arg(next),&next);
00545     A4 arg4 = parse_arg<A4>(next_arg(next),NULL);
00546 
00547     R res = (*func)(arg1,arg2,arg3,arg4);
00548     if(result != NULL) {
00549         write_result<R>(res, result);
00550     }
00551 }
00552 
00553 
00554 struct rpc_method { 
00555     const char *name;
00556     typedef void (*caller_t)(Base*, const char*, char*);
00557     typedef const struct rpc_method *(*super_t)(Base*);
00558     union {
00559         caller_t caller;
00560         super_t super;
00561     };
00562 };
00563 
00564 template<class C>
00565 const struct rpc_method *rpc_super(Base *this_ptr) {
00566     return static_cast<C*>(this_ptr)->C::get_rpc_methods();
00567 }
00568 
00569 #define RPC_METHOD_END { NULL, NULL }
00570 #define RPC_METHOD_SUPER(C) { NULL, (rpc_method::caller_t)(rpc_method::super_t)rpc_super<C> }
00571 
00572 /** Parse a string describing a call and then do it
00573  *
00574  * @param call A pointer to a string describing the call, which has
00575  *   the form /object/method arg ... argn. Arguments are
00576  *   delimited by space characters, and the string is terminated
00577  *   by a null character.
00578  * @param result A pointer to an array to write the result into.
00579  */
00580 bool rpc(const char *buf, char *result = 0);
00581 
00582 
00583 } // namespace mbed
00584 
00585 #endif