00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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(...)
00043 #define debugPyObject(...)
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
00078
00079
00080
00081
00082
00083
00084
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) ) {
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) ) {
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
00137
00138 PyObject* tuple=NULL;
00139 int i=0, size=0, start=0, cur=0;
00140
00141 if (!services)
00142 return PyTuple_New(0);
00143
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
00166
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
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
00210 if (!strchr(itemtypes, format[ptr]))
00211
00212 return 0;
00213 if (ptr+1 == newptr) {
00214
00215
00216
00217 if (newptr == size)
00218
00219 return 1;
00220 else
00221
00222 return 0;
00223 } else {
00224
00225 if (format[ptr+1] != ':')
00226
00227
00228
00229 return 0;
00230 if (ptr+2 == newptr)
00231
00232 return 0;
00233 for (x=ptr+2; x<=newptr-1; x++) {
00234 if (!strchr(digits, format[x]))
00235
00236 return 0;
00237 }
00238 }
00239 ptr=newptr+1;
00240 }
00241
00242 return 1;
00243 }
00244 #endif
00245
00246
00247 static int
00248 next_element(const char *schema, unsigned int *p, int *type, int *mult)
00249 {
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 char *endptr;
00262
00263
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
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
00307
00308
00309
00310
00311
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
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) {
00374 int p = (mult-1) >= 0 ? (mult -1) : 0;
00375
00376
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
00382
00383
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
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 }
00405 }
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
00429 }
00430
00431
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
00464
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
00490
00491
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
00499
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
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
00523 static unsigned int
00524 getSizeFromFormatAndObjects(PyObject *iter, const char* format)
00525 {
00526
00527
00528
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
00539 return getSizeFromFormat(format);
00540 }
00541
00542 if (!PySequence_Check(iter)) {
00543 print("Python object is not a sequence");
00544 return 0;
00545 }
00546
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
00553 obj_nr = getElemNrFromFormat(temp_format);
00554 delete temp_format;
00555 }
00556
00557
00558 iter_size=PySequence_Size(iter);
00559
00560 if (iter_size <= obj_nr) {
00561
00562
00563
00564
00565 return total_size;
00566 }
00567
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
00577
00578
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
00599
00600
00601 static int
00602 iterator_to_buffer(PyObject *iter,
00603 char *buffer,
00604 unsigned int size,
00605 const char *format)
00606 {
00607
00608
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
00656
00657
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
00665
00666
00667 memcpy(&buffer[buf_ptr], str, size-buf_ptr);
00668 } else {
00669
00670
00671
00672
00673
00674 memcpy(&buffer[buf_ptr], str, size-buf_ptr);
00675 }
00676 buf_ptr = size;
00677 } else {
00678 if (str_size < (unsigned int)mult) {
00679
00680 memcpy(&buffer[buf_ptr], str, str_size);
00681
00682 memset(&buffer[buf_ptr+str_size], '\0', mult-str_size);
00683 } else
00684
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
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
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
00764 static int
00765 iterator_to_allocated_buffer(PyObject *iter,
00766 const char *format,
00767 char **buffer,
00768 unsigned int *size )
00769 {
00770
00771
00772
00773
00774
00775 *buffer = NULL;
00776 *size = 0;
00777
00778 *size = getSizeFromFormatAndObjects(iter, format);
00779 if (!*size) {
00780
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
00790 return 1;
00791 }
00792