pydim_utils.cpp

Go to the documentation of this file.
00001 /** **************************************************************************
00002  * \brief Utility functions to used for creating the PyDim module.
00003  * These are used primarily for converting between DIM C buffers and python
00004  * objects.
00005  *
00006  * \authors M. Frank, N. Neufeld, R. Stoica
00007  * \date Nov. 2007 - September 2008
00008  *
00009  * Various defines necessary for converting between the dim buffers and Python
00010  * objects.
00011  *
00012  * TODO: All the tests until were done communicating between the same
00013  * architectures (32 bits and 64 bits). Not sure DIM supports communicating
00014  * between platforms that have different sizes for the basic types.
00015  * Anyway I can't fix this if DIM doesn't support this.
00016  * *************************************************************************/
00017 
00018 // includes
00019 extern "C" {
00020 #include <Python.h>
00021 #include "structmember.h"
00022 }
00023 #include <cstdlib>
00024 #include <cstdio>
00025 
00026 #ifdef _WIN32
00027  #include <cstdarg> 
00028   static inline void ___print(const char* fmt,...)
00029   {
00030     va_list args; va_start(args,fmt); 
00031     vprintf(fmt,args); printf("\n"); va_end(args); 
00032   }
00033  #define print printf("DIM Wrapper: %s:%u ::%s: ", __FILE__, __LINE__, __FUNCTION__); ___print 
00034 #else
00035  #define print(...) printf("DIM Wrapper: %s:%u ::%s: ", __FILE__, __LINE__, __FUNCTION__); printf(__VA_ARGS__); printf("\n");
00036 #endif
00037 
00038 #ifdef __DEBUG
00039  #define debug print
00040  #define debugPyObject printPyObject
00041 #else
00042  #define debug(...) /* __VA_ARGS__ */
00043  #define debugPyObject(...) /* __VA_ARGS__ */
00044 #endif
00045 
00046 #ifndef HOST_NAME_MAX
00047 #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
00048 #endif
00049 
00050 #ifndef Py_RETURN_NONE
00051 #define Py_RETURN_NONE do { Py_INCREF(Py_None); return Py_None; } while(0);
00052 #endif
00053 #define errmsg(x) do { fprintf(stderr, "%s: %s\n", __FUNCTION__, x); } while(0);
00054 
00055 #define _DIM_INT 0
00056 #define _DIM_INT_LEN sizeof(int)
00057 
00058 #define _DIM_FLOAT 1
00059 #define _DIM_FLOAT_LEN sizeof(float)
00060 
00061 #define _DIM_DOUBLE 2
00062 #define _DIM_DOUBLE_LEN sizeof(double)
00063 
00064 #define _DIM_XTRA 3
00065 #define _DIM_XTRA_LEN sizeof(long long)
00066 
00067 #define _DIM_STRING 4
00068 #define _DIM_CHAR_LEN 1
00069 
00070 #define _DIM_SHORT 5
00071 #define _DIM_SHORT_LEN sizeof(short)
00072 
00073 #define _DIM_LONG 6
00074 #define _DIM_LONG_LEN sizeof(long)
00075 
00076 #define MUL_INFINITE -1
00077 /* multiplicity == MUL_INFINITE  means an arbitrary amount of data types
00078  *                  (e.g. ..;I)
00079  * multiplicity == 0 is an illegal value and will not be returned by this
00080  *                 function
00081  */
00082 
00083 /* **************************************************************************
00084  * Utility functions
00085  * *************************************************************************/
00086 #ifndef DIMCPP_MODULE
00087 static int listOrTuple2Int(PyObject* pyObj, int** buffer)
00088 {
00089   int size, i, res=1;
00090   PyObject* tmp;
00091 
00092   if ( PyTuple_Check(pyObj) ) { //tuple
00093     size = PyTuple_Size(pyObj);
00094     if (!size)
00095       res = 0;
00096     (*buffer) = (int*)malloc(size*sizeof(int)+1);
00097     if ( !(*buffer) )
00098       res = 0;
00099     for (i=0; i<size; i++) {
00100       tmp = PyTuple_GetItem(pyObj, i);
00101       if (!tmp)
00102         res = 0;
00103       (*buffer)[i] = (int)PyInt_AsLong(tmp);
00104     }
00105   } else if ( PyList_Check(pyObj) ) { //list
00106     size = PyList_Size(pyObj);
00107     if (!size)
00108       res = 0;
00109     (*buffer) = (int*)malloc(size*sizeof(int)+1);
00110     if ( !(*buffer) )
00111       res = 0;
00112     for (i=0; i<size; i++) {
00113       tmp = PyList_GetItem(pyObj, i);
00114       if (!tmp)
00115         res = 0;
00116       (*buffer)[i] = (int)PyInt_AsLong(tmp);
00117     }
00118   } else
00119     res = 0;
00120 
00121   if (res) {
00122     (*buffer)[size] = 0;
00123     return 1;
00124   }
00125   else {
00126     free(*buffer);
00127     buffer = NULL;
00128     return 0;
00129   }
00130 }
00131 #endif
00132 
00133 #ifndef DIMCPP_MODULE
00134 static PyObject* stringList_to_tuple (char* services)
00135 {
00136   /* Gets a list of null terminated char* and converts it to a python tuple
00137   */
00138   PyObject* tuple=NULL;
00139   int i=0, size=0, start=0, cur=0;
00140 
00141   if (!services)
00142     return PyTuple_New(0); /* reference will be owned by the caller */
00143   /* getting the number of serviecs */
00144   while (services[i] != '\0') {
00145     if (services[i] == '\n')
00146       ++size;
00147   }
00148   tuple = PyTuple_New(size);
00149   i=0;
00150   while (services[i] != '\0') {
00151     if (services[i] == '\n') {
00152       PyTuple_SetItem(tuple, cur++,
00153           PyString_FromStringAndSize(&services[start], i-start));
00154       start=i+1;
00155     }
00156   }
00157 
00158   return tuple;
00159 }
00160 #endif
00161 
00162 #ifndef DIMCPP_MODULE
00163 static PyObject* pyCallFunction (PyObject* pyFunc, PyObject* args)
00164 {
00165   /*  Is the responsibility of the caller to handle the Ref count of both the
00166    * sentobject and the result.
00167    */
00168   PyGILState_STATE gstate;
00169   PyObject* res;
00170 
00171   gstate = PyGILState_Ensure();
00172   res = PyEval_CallObject(pyFunc, args);
00173   if (!res)
00174     PyErr_Print();
00175   PyGILState_Release(gstate);
00176 
00177   return res;
00178 }
00179 #endif
00180 
00181 #ifdef __DEBUG
00182 static void printPyObject(PyObject *object)
00183 {
00184   if (!object) return;
00185   PyObject_Print(object, stdout, Py_PRINT_RAW);
00186   printf("\n");
00187 }
00188 
00189 static void printDimBuf(const char *buf, int size) {
00190   for (int i=0; i<size; i++)
00191     printf("Byte %d: ASCII %c, CODE: %d\n", i, buf[i], buf[i]);
00192 }
00193 #endif
00194 
00195 
00196 #ifndef DIMC_MODULE
00197 static int verify_dim_format(const char *format)
00198 {
00199   /* Return True in case of success and False otherwise
00200   */
00201   int ptr=0, x, newptr;
00202   int size=strlen(format);
00203   char delimiter=';';
00204   const char itemtypes[]="ICLSFDXiclsfdx";
00205   const char digits[]="0123456789";
00206 
00207   while (ptr<size) {
00208     for (newptr=ptr; newptr<size && format[newptr]!=delimiter; newptr++);
00209     /* We have found a new group of parameters */
00210     if (!strchr(itemtypes, format[ptr]))
00211       /* This means the type letter is unknown */
00212       return 0;
00213     if (ptr+1 == newptr) {
00214       /* Here we only have the item type letter. Checking to see if we are
00215        * at the end
00216        */
00217       if (newptr == size)
00218         /* We are at the end, newptr is on the \0 string terminating char */
00219         return 1;
00220       else
00221         /* in the middle of the format string the number of items is missing */
00222         return 0;
00223     } else {
00224       /* The multiplicity of the parameters is also specified */
00225       if (format[ptr+1] != ':')
00226         /* We were expecting a colon separator between the type
00227          * and the multiplicity
00228          */
00229         return 0;
00230       if (ptr+2 == newptr)
00231         /* This means that there is no digit after colon */
00232         return 0;
00233       for (x=ptr+2; x<=newptr-1; x++) {
00234         if (!strchr(digits, format[x]))
00235           /* We were expecting a digit */
00236           return 0;
00237       }
00238     } // end if-else
00239     ptr=newptr+1;
00240   } // end while
00241 
00242   return 1;
00243 } // end verify_dim_format
00244 #endif
00245 
00246 
00247   static int
00248 next_element(const char *schema, unsigned int *p, int *type, int *mult)
00249 {
00250   /** \brief Incrementally parses a DIM format and returns the next element
00251    * from it
00252    * @param schema The string containing the DIM format
00253    * @param p At entry this contains the location inside the format buffer
00254    * from where the parsing should start. At return is updated to the end
00255    * element location.
00256    * @param type The type of the next element is returned using this parameter
00257    * @param mult The multiplicity of the next element. -1 means infinite
00258    * @return The status code of the function call succedded or not
00259    * (1 for success)
00260    */
00261   char *endptr;
00262 
00263   /* check to see if we haven't gone pass the schema string limit */
00264   if (*p >= strlen(schema))
00265     return 0;
00266 
00267   if (schema[*p] == '\0') return 0;
00268   switch (toupper(schema[*p])) {
00269     case 'I':
00270     case 'L': *type = _DIM_INT; break;
00271     case 'C': *type = _DIM_STRING; break;
00272     case 'F': *type = _DIM_FLOAT; break;
00273     case 'D': *type = _DIM_DOUBLE; break;
00274     case 'X': *type = _DIM_XTRA; break;
00275     case 'S': *type = _DIM_SHORT; break;
00276     default:
00277               print("Bad type character %c", schema[*p]);
00278               *type = -1;
00279               return 0;
00280   }
00281   switch (schema[++(*p)]) {
00282     case '\0': *mult = MUL_INFINITE; break;
00283                /* this is not stricly correct from DIM point of view. */
00284     case ';': *mult = 1; ++(*p); break;
00285     case ':':
00286               (*p)++;
00287               *mult = strtoul(&schema[*p], &endptr, 10);
00288               if (endptr == &schema[*p]) {
00289                 print("illegal number\n");
00290                 return 0;
00291               }
00292               *p += (endptr - &schema[*p]) + ((*endptr == ';') ? 1 : 0);
00293               break;
00294     default:
00295               print("Bad multiplicity character %c\n", schema[*p]);
00296               return 0;
00297   }
00298 
00299   return 1;
00300 }
00301 
00302 
00303 static PyObject *
00304 dim_buf_to_list(const char *schema, const char *buf, unsigned int len)
00305 {
00306   /* NOTE: Compilers will pad structures to the arhitecture word size.
00307    * It is NOT recommended to pass the lenght of the buffer using
00308    * strlen() if the last type field of the format has multiplicity
00309    * unlimited. You will see garbage in the buffer after conversion!
00310    * Workarounds: disable padding from the declared structure and/or
00311    * specify the exact size of the buffer.
00312    */
00313   int j=0, type=0, mult=0, n=0;
00314   unsigned int m=0;
00315   PyObject *list, *tmp;
00316   float f;
00317 
00318   if (!(list = PyList_New(0))) {
00319     /* could not create a new Python list */
00320     print("ERROR: Could not create a Python list.");
00321     return NULL;
00322   }
00323   while (next_element(schema, &m, &type, &mult)) {
00324     switch (type) {
00325       case _DIM_INT:
00326         if (mult == MUL_INFINITE)
00327           mult = (len - n) / _DIM_INT_LEN;
00328         for (j = 0; j < mult; ++j)
00329           if (n + _DIM_INT_LEN <= len) {
00330             tmp = PyInt_FromLong(*(int *)&buf[n]);
00331             n += _DIM_INT_LEN;
00332             PyList_Append(list, tmp);
00333             Py_DECREF(tmp);
00334           } else goto short_buffer;
00335         break;
00336       case _DIM_FLOAT:
00337         if (mult == MUL_INFINITE)
00338           mult = (len - n) / _DIM_FLOAT_LEN;
00339         for (j = 0; j < mult; ++j)
00340           if (n + _DIM_FLOAT_LEN <= len) {
00341             f = *(float *)(&buf[n]);
00342             tmp = PyFloat_FromDouble(f);
00343             n += _DIM_FLOAT_LEN;
00344             PyList_Append(list, tmp);
00345             Py_DECREF(tmp);
00346           } else goto short_buffer;
00347         break;
00348       case _DIM_DOUBLE:
00349         if (mult == MUL_INFINITE)
00350           mult = (len - n) / _DIM_DOUBLE_LEN;
00351         for (j = 0; j < mult; ++j)
00352           if (n + _DIM_DOUBLE_LEN <= len) {
00353             tmp = PyFloat_FromDouble(*(double *)&buf[n]);
00354             n += _DIM_DOUBLE_LEN;
00355             PyList_Append(list, tmp);
00356             Py_DECREF(tmp);
00357           } else goto short_buffer;
00358         break;
00359       case _DIM_XTRA:
00360         if (mult == MUL_INFINITE)
00361           mult = (len - n) / _DIM_XTRA_LEN;
00362         for (j = 0; j < mult; ++j)
00363           if (n + _DIM_XTRA_LEN <= len) {
00364             tmp = PyLong_FromLongLong(*(long long *)&buf[n]);
00365             n += _DIM_XTRA_LEN;
00366             PyList_Append(list, tmp);
00367             Py_DECREF(tmp);
00368           } else goto short_buffer;
00369         break;
00370       case _DIM_STRING:
00371         if (mult == MUL_INFINITE)
00372           mult = (len - n) / _DIM_CHAR_LEN;
00373         if ((unsigned int)(n + mult) <= len) { // ugly
00374           int p = (mult-1) >= 0 ? (mult -1) : 0;
00375           //while (p && buf[n+p] == '\0')
00376           //  --p;
00377           tmp = PyString_FromStringAndSize(&buf[n], p+1);
00378           n += mult;
00379         } else {
00380           int p = ((int)len-n-1) >= 0 ? ((int)len-n-1) : 0;
00381           /* uncomment this is you want to strip '\0' from the string */
00382           // while (p && buf[p] == '\0')
00383           //  --p;
00384           tmp = PyString_FromStringAndSize(&buf[n], p+1);
00385           n = len;
00386         }
00387         PyList_Append(list, tmp);
00388         Py_DECREF(tmp);
00389         break;
00390       case _DIM_SHORT:
00391         if (mult == MUL_INFINITE)
00392           mult = (len - n) / _DIM_SHORT_LEN;
00393         for (j = 0; j < mult; ++j)
00394           if (n + _DIM_SHORT_LEN <= len) {
00395             // ugly
00396             tmp = PyInt_FromLong(*(short int *)&buf[n]);            
00397             n += _DIM_SHORT_LEN;
00398             PyList_Append(list, tmp);
00399             Py_DECREF(tmp);
00400           } else goto short_buffer;
00401         break;
00402       default:
00403         goto short_buffer;
00404     } // end switch
00405   } // end while
00406 
00407   return list;
00408 
00409 short_buffer:
00410   print("Provided buffer was to short to convert all the arguments using the DIM format specified." );
00411   print("Buffer size %d, format %s", len, schema);
00412   Py_XDECREF(list);
00413   return NULL;
00414 }
00415 
00416 #ifdef __DEBUG 
00417 static PyObject*
00418 list2Tuple(PyObject* list)
00419 {
00420   int size, i;
00421   PyObject* tuple;
00422 
00423   if ( !PyList_Check(list) ) return NULL;
00424   size = PyList_Size(list);
00425   tuple = PyTuple_New(size);
00426   for(i=0; i<size; i++) {
00427     PyTuple_SetItem(tuple, i, PyList_GetItem(list, i) );
00428     //PyObject_Print( PyList_GetItem(list, i), stdout, Py_PRINT_RAW );
00429   }
00430   //  printPyObject(list);
00431   //  printPyObject(tuple);
00432 
00433   return tuple;
00434 }
00435 #endif
00436 
00437 static PyObject*
00438 dim_buf_to_tuple(const char *schema, const char *buf, int len)
00439 {
00440   PyObject *list, *tuple;
00441 
00442   list = dim_buf_to_list(schema, buf, len);
00443   if (!list) {
00444     print("ERROR: Could not convert DIM buffer to "
00445           "Python objects using the specified format");
00446     return NULL;
00447   }
00448   tuple = PyList_AsTuple(list);
00449   Py_DECREF(list);
00450 
00451   return tuple;
00452 }
00453 
00454 
00455 static int
00456 getSizeFromFormat(const char* format)
00457 {
00458   int type=0, mult=0, size=0;
00459   unsigned int ptr=0;
00460 
00461   while ( next_element(format, &ptr, &type, &mult) ) {
00462     if (mult == -1) {
00463       // we can't calculate the maximum size in this case
00464       // 0 means error
00465       return 0;
00466     }
00467     switch (type) {
00468       case _DIM_LONG    : size += mult * _DIM_LONG_LEN;    break;
00469       case _DIM_INT     : size += mult * _DIM_INT_LEN;     break;
00470       case _DIM_STRING  : size += mult * _DIM_CHAR_LEN;    break;
00471       case _DIM_FLOAT   : size += mult * _DIM_FLOAT_LEN;   break;
00472       case _DIM_DOUBLE  : size += mult * _DIM_DOUBLE_LEN;  break;
00473       case _DIM_XTRA    : size += mult * _DIM_XTRA_LEN;    break;
00474       case _DIM_SHORT   : size += mult * _DIM_SHORT_LEN;   break;
00475       default:
00476         print("Bad type char extracted from (%c. Type is %d\n",
00477               format[ptr], type);
00478         return -1;
00479     }
00480   }
00481 
00482   return size;
00483 }
00484 
00485 
00486   static unsigned int
00487 getElemNrFromFormat(const char *format)
00488 {
00489   /* Receives a closed format string and returns the total number of
00490    * elements expected from it.
00491    * In case of any errors returns 0.
00492    */
00493   int type=0, mult=0, total=0;
00494   unsigned int ptr=0;
00495 
00496   while (next_element(format, &ptr, &type, &mult) ) {
00497     if (mult == -1) {
00498       // we can't calculate the maximum size in this case
00499       // 0 means error
00500       return 0;
00501     }
00502     switch (type) {
00503       case _DIM_LONG  :
00504       case _DIM_INT   :
00505       case _DIM_FLOAT :
00506       case _DIM_DOUBLE:
00507       case _DIM_XTRA  :
00508       case _DIM_SHORT : total += mult; break;
00509                         //in Python S:<number> is only one string
00510       case _DIM_STRING: ++total; break;
00511       default:
00512                         print("Bad type char extracted from (%c. Type is %d\n",
00513                             format[ptr], type);
00514                         return 0;
00515     }
00516   }
00517 
00518   return total;
00519 }
00520 
00521 
00522 //#ifndef DIMC_MODULE
00523   static unsigned int
00524 getSizeFromFormatAndObjects(PyObject *iter, const char* format)
00525 {
00526   /* Returns the size needed for converting the Python iterator to a
00527    * buffer according to a DIM format. The format can have an unlimited
00528    * number of ending variables of the same type.
00529    */
00530 
00531   unsigned int format_size=0, iter_size=0, obj_nr=0, lastobj_size=0, total_size=0;
00532   const char itemtypes[]="ICLSFDXiclsfdx";
00533   char *temp_format;
00534   PyObject *last;
00535 
00536   format_size = strlen(format);
00537   if (!strchr(itemtypes, format[format_size-1])) {
00538     // this means we can deduct the size directly from format
00539     return getSizeFromFormat(format);
00540   }
00541   // we have an open ended format string
00542   if (!PySequence_Check(iter)) {
00543     print("Python object is not a sequence");
00544     return 0;
00545   }
00546   // Get the size of all fixed number of arguments (if they exist)
00547   if (format_size>1) {
00548     temp_format = new char[format_size];
00549     strncpy(temp_format, format, format_size-1);
00550     temp_format[format_size-1]='\0';
00551     total_size = getSizeFromFormat(temp_format);
00552     // Get the total number of objects for which the size was calculated
00553     obj_nr = getElemNrFromFormat(temp_format);
00554     delete temp_format;
00555   }
00556 
00557   // Get the total size of the sequence
00558   iter_size=PySequence_Size(iter);
00559 
00560   if (iter_size <= obj_nr) {
00561     /* Means the iterator does not contain enough elements
00562      * This should never be the case but i'm returning the total size
00563      * for the fixed parameters
00564      */
00565     return total_size;
00566   }
00567   // Get the size of the objects that follows
00568   switch (toupper(format[format_size-1])) {
00569     case 'L' :
00570     case 'I' : lastobj_size = _DIM_INT_LEN   ; break;
00571     case 'F' : lastobj_size = _DIM_FLOAT_LEN ; break;
00572     case 'D' : lastobj_size = _DIM_DOUBLE_LEN; break;
00573     case 'X' : lastobj_size = _DIM_XTRA_LEN  ; break;
00574     case 'S' : lastobj_size = _DIM_SHORT_LEN ; break;
00575     case 'C' :
00576                /* this is tricky: we only have a string of unlimited size
00577                 * I have to get the string length and add it.
00578                 * TODO: subsequent objects are ignored.
00579                 */
00580                last = PySequence_GetItem(iter, obj_nr);
00581                if (!PyString_Check(last)) {
00582                  print("Invalid Python object expected a string");
00583                  return 0;
00584                }
00585                total_size += PyString_Size(last);
00586                Py_DECREF(last);
00587                return total_size;
00588                break;
00589     default:
00590                print("Bad type char (%c) extracted from %s",
00591                    format[format_size-1], format);
00592                return 0;
00593   }
00594   total_size = total_size + lastobj_size * (iter_size - obj_nr);
00595 
00596   return total_size;
00597 }
00598 //#endif
00599 
00600 
00601 static int
00602 iterator_to_buffer(PyObject     *iter,   /* list or tuple PyObject */
00603                    char         *buffer, /* buffer to perform conversion */
00604                    unsigned int size,    /* maximum size of buffer */
00605                    const char   *format) /* the format to use */
00606 {
00607   /** \brief This function gets a Python iterator and converts it to a
00608    * char* buffer according to the format specified.
00609    */
00610   int type=0, mult=0, j;
00611   PyObject *tmp, *tmp1;
00612   unsigned int ptr=0, buf_ptr=0, str_size=0, iter_size=0, elem=0;
00613   int i;
00614   float f;
00615   double d;
00616   short s;
00617   long l;
00618   long long x;
00619   char *str;
00620 
00621   memset(buffer, '\0', size);
00622   
00623   if (!PySequence_Check(iter)) {
00624     print("Provided Python object is not a sequence");
00625     return 0;
00626   }
00627   
00628   while (next_element(format, &ptr, &type, &mult) ) {
00629     for (j=0; j<mult || (mult==-1 && buf_ptr<size); j++) {      
00630       tmp = PySequence_GetItem(iter, elem++);      
00631       if(!tmp) {
00632         print("Iterator object does not hold enough values to match format");
00633         return 0;
00634       }
00635       switch (type) {
00636         case _DIM_INT :
00637           if(size < buf_ptr + _DIM_INT_LEN)
00638             goto shortbuffer;
00639           tmp1 = PyNumber_Int(tmp);
00640           if (!tmp1) goto invalid_format;
00641           i = PyInt_AsLong(tmp1);
00642           memcpy(&buffer[buf_ptr], &i, _DIM_INT_LEN);
00643           buf_ptr += _DIM_INT_LEN;
00644           break;
00645         case _DIM_LONG :
00646           if (size < buf_ptr + _DIM_LONG_LEN)
00647             goto shortbuffer;
00648           tmp1 = PyNumber_Long(tmp);
00649           if (!tmp1) goto invalid_format;
00650           l = PyInt_AsLong(tmp1);
00651           memcpy(&buffer[buf_ptr], &l, _DIM_LONG_LEN);
00652           buf_ptr += _DIM_LONG_LEN;
00653           break;
00654         case _DIM_STRING:
00655           /* Here I explicitly want to use PyObject_Str to convert the object to a 
00656            * string. 'tmp' might be a random Python object that is converted 
00657            * to a string. 
00658            */ 
00659           tmp1 = PyObject_Str(tmp);
00660           str = PyString_AsString(tmp1);
00661           str_size = strlen(str)+1;
00662           if (mult==-1) {
00663             if ((buf_ptr+str_size)>size) {
00664               /* this means the Python string is too
00665                * big to be completely converted
00666                */
00667               memcpy(&buffer[buf_ptr], str, size-buf_ptr);
00668             } else {
00669               /* shorter string OR we have an end of line in the middle
00670                * I prefer here to copy past what size indicates. This allows
00671                * to pass also Null characters..*/
00672               //memcpy(&buffer[buf_ptr], str, str_size);
00673               //memset(&buffer[buf_ptr+str_size], '\0', size-buf_ptr-str_size);
00674               memcpy(&buffer[buf_ptr], str, size-buf_ptr);
00675             }
00676             buf_ptr = size;
00677           } else {
00678             if (str_size < (unsigned int)mult) {
00679               /* we have a shorter string */
00680               memcpy(&buffer[buf_ptr], str, str_size);
00681               /* zeroing what can't be filled */
00682               memset(&buffer[buf_ptr+str_size], '\0', mult-str_size);
00683             } else
00684               /* String is to big to fit in its place. Truncating */
00685               memcpy(&buffer[buf_ptr], str, mult);
00686             buf_ptr += _DIM_CHAR_LEN * mult;
00687             j = mult;
00688           }      
00689           break;
00690         case _DIM_FLOAT:
00691           if (size < buf_ptr + _DIM_FLOAT_LEN)
00692             goto shortbuffer;
00693           tmp1 = PyNumber_Float(tmp);
00694           if (!tmp1) goto invalid_format;
00695           f = (float)PyFloat_AsDouble(tmp1);
00696           memcpy(&buffer[buf_ptr], &f, _DIM_FLOAT_LEN);
00697           buf_ptr += _DIM_FLOAT_LEN;
00698           break;
00699         case _DIM_DOUBLE:
00700           if (size < buf_ptr + _DIM_DOUBLE_LEN)
00701             goto shortbuffer;
00702           tmp1 = PyNumber_Float(tmp);
00703           if (!tmp1) goto invalid_format;
00704           d = PyFloat_AsDouble(tmp1);
00705           memcpy(&buffer[buf_ptr], &d, _DIM_DOUBLE_LEN);
00706           buf_ptr += _DIM_DOUBLE_LEN;
00707           break;
00708         case _DIM_XTRA:
00709           if (size < buf_ptr + _DIM_XTRA_LEN)
00710             goto shortbuffer;
00711           tmp1 = PyNumber_Long(tmp);
00712           if (!tmp1) goto invalid_format;
00713           x = PyLong_AsLongLong(tmp1);
00714           memcpy(&buffer[buf_ptr], &x, _DIM_XTRA_LEN);
00715           buf_ptr += _DIM_XTRA_LEN;
00716           break;
00717         case _DIM_SHORT:
00718           if (size < buf_ptr + _DIM_SHORT_LEN)
00719             goto shortbuffer;
00720           tmp1 = PyNumber_Int(tmp);
00721           if (!tmp1) goto invalid_format;
00722           //printPyObject(tmp1);
00723           s = (short int)PyInt_AsLong(tmp1);
00724           memcpy(&buffer[buf_ptr], &s, _DIM_SHORT_LEN);
00725           buf_ptr += _DIM_SHORT_LEN;
00726           break;
00727         default:
00728           print("bad character %c. Type is %d\n", format[ptr], type);
00729           return 0;
00730       }      
00731       Py_DECREF(tmp);
00732       Py_DECREF(tmp1);
00733     }
00734   }
00735   iter_size = PySequence_Size(iter);
00736   if (iter_size != elem) {
00737     // Check to see if all the objects from the iterator were used
00738     print("WARNING: Python iterator holds more objects than DIM format specifies.");
00739     debug(" Dumping objects and format: ");
00740     debugPyObject(iter);
00741     debug("DIM Format: %s", format);
00742   }
00743 
00744   return 1;
00745 
00746 shortbuffer:
00747   print("WARNING: The provided buffer is not big enough to hold all objects."
00748         " Truncating...");
00749   return 1;
00750 
00751 invalid_format:
00752   print("WARNING: Python iterator holds more objects than DIM format specifies.");
00753     debug(" Dumping objects and format: ");
00754     debugPyObject(iter);
00755     debug("DIM Format: %s", format);
00756     
00757   Py_XDECREF(tmp);
00758   Py_XDECREF(tmp1);
00759   return 0;
00760 }
00761 
00762 
00763 //#ifdef DIMC_MODULE
00764 static int
00765 iterator_to_allocated_buffer(PyObject  *iter, /* list or tuple */
00766                              const char   *format,  /* the format to use */
00767                              char  **buffer, /* conversion buffer */
00768                              unsigned int *size )/* maximum size of buffer */
00769 {
00770   /** This function allocates a new buffer and converts the python
00771    * iterator objects according to 'format'.
00772    * Input: PyTuple or PyList
00773    * Output: pointer to the newly created buffer and its size
00774    */
00775   *buffer = NULL;
00776   *size = 0;
00777 
00778   *size = getSizeFromFormatAndObjects(iter, format);
00779   if (!*size) {
00780     // could not figure out the size of the needed buffer
00781     *buffer = NULL;
00782     return 0;
00783   }
00784   *buffer= (char*)malloc(*size);
00785   if (!iterator_to_buffer(iter, *buffer, *size, format)) {
00786     *buffer = NULL;
00787     return 0;
00788   }
00789     // the call succeded
00790     return 1;
00791 }
00792 //#endif

Generated on 5 Feb 2014 for PyDIM by  doxygen 1.4.7