FreeWRL/FreeX3D  3.0.0
EAI_C_swigExtras.c
1 
2 /****************************************************************************
3  This file is part of the FreeWRL/FreeX3D Distribution.
4 
5  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
6 
7  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
19 ****************************************************************************/
20 
21 
22 #include "EAI_C.h"
23 #include <config.h>
24 
25 //#include "EAI_swigMe.h"
26 #include <stdio.h>
27 //#define SWIG
28 #ifdef SWIG
29 int isMF(int nodetype)
30 {
31  return (nodetype %2 == 1) && nodetype >= 0 && nodetype <= 41;
32 }
33 int isSF(int nodetype)
34 {
35  return (nodetype % 2 == 0) && nodetype >= 0 && nodetype <= 41;
36 }
37 X3DNode *X3D_newSF(int nodetype)
38 {
39  X3DNode* retval;
40  if(isSF(nodetype))
41  {
42  /*delegate default construction to the appropriate type */
43  switch(nodetype)
44  {
45  case FIELDTYPE_SFColor:
46  retval = X3D_newSFColor(0.0f,0.0f,0.0f); break;
47  case FIELDTYPE_SFFloat:
48  retval = X3D_newSFFloat(0.0f); break;
49  case FIELDTYPE_SFTime:
50  retval = X3D_newSFTime(0.0); break;
51  case FIELDTYPE_SFInt32:
52  retval = X3D_newSFInt32(0); break;
53  case FIELDTYPE_SFString:
54  retval = X3D_newSFString(""); break;
55  case FIELDTYPE_SFNode:
56  retval = X3D_newSFNode(); break;
57  case FIELDTYPE_SFRotation:
58  retval = X3D_newSFRotation(0.0f,1.0f,0.0f,0.0f); break;
59  case FIELDTYPE_SFVec2f:
60  retval = X3D_newSFVec2f(0.0f,0.0f); break;
61  case FIELDTYPE_SFVec3f:
62  retval = X3D_newSFVec3f(0.0f,0.0f,0.0f); break;
63  case FIELDTYPE_SFColorRGBA:
64  retval = X3D_newSFColorRGBA(.5f,.5f,.5f,1.0f); break;
65  case FIELDTYPE_SFBool:
66  retval = X3D_newSFBool(0); break;
67  case FIELDTYPE_SFVec3d:
68  retval = X3D_newSFVec3d(0.0,0.0,0.0); break;
69  case FIELDTYPE_SFVec2d:
70  retval = X3D_newSFVec2d(0.0,0.0); break;
71  }
72  return retval;
73  }
74  else
75  printf ("New node not implemented yet for this type\n");return NULL;
76  return NULL;
77 }
78 int X3D_sizeof(int fieldtype)
79 {
80  /* how do you dynamic_cast<> in C? to keep the recent MF code both general and non-breaking we need the size by int type
81  if the code ever changes so the MF isn't malloced in a contiguous block ie **p instead of *p then we won't need this.
82  */
83  int retval;
84  switch(fieldtype)
85  {
86  case FIELDTYPE_SFColor:
87  retval = sizeof(_intX3D_SFColor); break;
88  case FIELDTYPE_SFFloat:
89  retval = sizeof(_intX3D_SFFloat); break;
90  case FIELDTYPE_SFTime:
91  retval = sizeof(_intX3D_SFTime); break;
92  case FIELDTYPE_SFInt32:
93  retval = sizeof(_intX3D_SFInt32); break;
94  case FIELDTYPE_SFString:
95  retval = sizeof(_intX3D_SFString); break;
96  case FIELDTYPE_SFNode:
97  retval = sizeof(_intX3D_SFNode); break;
98  case FIELDTYPE_SFRotation:
99  retval = sizeof(_intX3D_SFRotation); break;
100  case FIELDTYPE_SFVec2f:
101  retval = sizeof(_intX3D_SFVec2f); break;
102  case FIELDTYPE_SFVec3f:
103  retval = sizeof(_intX3D_SFVec3f); break;
104  case FIELDTYPE_SFColorRGBA:
105  retval = sizeof(_intX3D_SFColorRGBA); break;
106  case FIELDTYPE_SFBool:
107  retval = sizeof(_intX3D_SFBool); break;
108  case FIELDTYPE_SFVec3d:
109  retval = sizeof(_intX3D_SFVec3d); break;
110  case FIELDTYPE_SFVec2d:
111  retval = sizeof(_intX3D_SFVec2d); break;
112 
113  case FIELDTYPE_MFColor:
114  retval = sizeof(_intX3D_MFColor); break;
115  case FIELDTYPE_MFFloat:
116  retval = sizeof(_intX3D_MFFloat); break;
117  case FIELDTYPE_MFTime:
118  retval = sizeof(_intX3D_MFTime); break;
119  case FIELDTYPE_MFInt32:
120  retval = sizeof(_intX3D_MFInt32); break;
121  case FIELDTYPE_MFString:
122  retval = sizeof(_intX3D_MFString); break;
123  case FIELDTYPE_MFNode:
124  retval = sizeof(_intX3D_MFNode); break;
125  case FIELDTYPE_MFRotation:
126  retval = sizeof(_intX3D_MFRotation); break;
127  case FIELDTYPE_MFVec2f:
128  retval = sizeof(_intX3D_MFVec2f); break;
129  case FIELDTYPE_MFVec3f:
130  retval = sizeof(_intX3D_MFVec3f); break;
131  case FIELDTYPE_MFColorRGBA:
132  retval = sizeof(_intX3D_MFColorRGBA); break;
133  case FIELDTYPE_MFBool:
134  retval = sizeof(_intX3D_MFBool); break;
135  case FIELDTYPE_MFVec3d:
136  retval = sizeof(_intX3D_MFVec3d); break;
137  case FIELDTYPE_MFVec2d:
138  retval = sizeof(_intX3D_MFVec2d); break;
139  default:
140  retval = 0;
141  }
142  return retval;
143 }
144 X3DNode *_swigNewMF(int itype, int num )
145 {
146  int i;
147  char *p, *q;
148  X3DNode* retval;
149  retval = malloc (sizeof (X3DNode));
150  retval->type = itype;
151  retval->X3D_MFNode.n = num;
152  if(num > 0)
153  {
154  /* X3D_freeNode assumes the MF's SFs are in one block: free(node->X3D_MFString.p); */
155  p = malloc (sizeof (X3DNode) * num);
156  retval->X3D_MFNode.p = (_intX3D_SFNode*)p;
157  q = (char*)X3D_newSF(itype-1); /* initialized to defaults esp. strptr=NULL or whatever */
158  for (i = 0; i < num; i++) {
159  memcpy(p,q,X3D_sizeof(itype-1)); /*initialize the storage area to defaults*/
160  p+= X3D_sizeof(itype-1);
161  }
162  X3D_freeNode((X3DNode*)q);
163  }else
164  retval->X3D_MFNode.p = NULL;
165  return retval;
166 
167 }
168 X3DNode *X3D_swigNewMF(char *fieldtype, int num )
169 {
170  int itype, ftype;
171  itype = -1;
172  ftype = findFieldInFIELDTYPES(fieldtype);
173  if( isMF(ftype) ) itype = ftype;
174  if( isSF(ftype) ) itype = ftype+1; /*mf type is sf+1*/
175  if(itype > -1)
176  {
177  return _swigNewMF(itype,num);
178 
179  }else{
180  printf ("New node not implemented yet for this type\n");return NULL;
181  }
182 }
183 void _X3D_setItemSF(X3DNode* node, int item, X3DNode* value)
184 {
185  /* set a scalar value in the SF node array .r or .c */
186 
187  int vtype, ntype;
188  double v;
189  vtype = value->type;
190  ntype = node->type;
191  if( !isSF(vtype) )return;
192  if( item < 0 || item > 3) return;
193  switch(vtype)
194  {
195  case FIELDTYPE_SFTime:
196  v = value->X3D_SFTime.value; break;
197  case FIELDTYPE_SFFloat:
198  v = (double)value->X3D_SFFloat.value; break;
199  case FIELDTYPE_SFInt32:
200  v = (double)value->X3D_SFInt32.value; break;
201  case FIELDTYPE_SFBool:
202  v = (double)value->X3D_SFBool.value; break;
203  /* should have SFString ? SFBool (int 1/0)? */
204  default:
205  return;
206  }
207  switch(ntype)
208  {
209  case FIELDTYPE_SFColor:
210  if(item > 2) break;
211  node->X3D_SFColor.c[item] = (float)v; break;
212  case FIELDTYPE_SFFloat:
213  if(item > 0) break;
214  node->X3D_SFFloat.value = (float)v; break;
215  case FIELDTYPE_SFTime:
216  if(item > 0) break;
217  node->X3D_SFTime.value = (float)v; break;
218  case FIELDTYPE_SFInt32:
219  if(item > 0) break;
220  node->X3D_SFInt32.value = (int)v; break;
221  case FIELDTYPE_SFString:
222  if(item > strlen(node->X3D_SFString.strptr)) break; /* int32>>char function*/
223  node->X3D_SFString.strptr[item] = (char)((int)v); break;
224  case FIELDTYPE_SFNode:
225  if(item > 0) break;
226  node->X3D_SFNode.adr = (int)v; break;
227  case FIELDTYPE_SFRotation:
228  if(item > 3) break;
229  node->X3D_SFRotation.r[item] = (float)v; break;
230  case FIELDTYPE_SFVec2f:
231  if(item > 1) break;
232  node->X3D_SFVec2f.c[item] = (float)v; break;
233  case FIELDTYPE_SFVec3f:
234  if(item > 2) break;
235  node->X3D_SFVec3f.c[item] = (float)v; break;
236  case FIELDTYPE_SFColorRGBA:
237  if(item > 3) break;
238  node->X3D_SFColorRGBA.r[item] = (float)v; break;
239  case FIELDTYPE_SFBool:
240  if(item > 0) break;
241  node->X3D_SFBool.value = ((int)v)?1:0; break;
242  case FIELDTYPE_SFVec3d:
243  if(item > 2) break;
244  node->X3D_SFVec3d.c[item] = (double)v; break;
245  case FIELDTYPE_SFVec2d:
246  if(item > 1) break;
247  node->X3D_SFVec2d.c[item] = (double)v; break;
248  default:
249  break;
250  }
251 }
252 X3DNode* _X3D_getItemSF(X3DNode* node, int item)
253 {
254  /* get a scalar value in the SF node array .r or .c */
255 
256  int vtype,ntype;
257  union{
258  double d;
259  float f;
260  int i;
261  } v;
262  vtype = -1;
263 
264  ntype = node->type;
265  if( item < 0 || item > 3) return NULL;
266  switch(ntype)
267  {
268  case FIELDTYPE_SFColor:
269  if(item > 2) break;
270  v.f = node->X3D_SFColor.c[item]; vtype =FIELDTYPE_SFFloat; break;
271  case FIELDTYPE_SFFloat:
272  if(item > 0) break;
273  v.f = node->X3D_SFFloat.value; vtype =FIELDTYPE_SFFloat; break;
274  case FIELDTYPE_SFTime:
275  if(item > 0) break;
276  v.d = node->X3D_SFTime.value; vtype = FIELDTYPE_SFTime; break;
277  case FIELDTYPE_SFInt32:
278  if(item > 0) break;
279  v.i = node->X3D_SFInt32.value; vtype = FIELDTYPE_SFInt32; break;
280  case FIELDTYPE_SFString:
281  if(item > strlen(node->X3D_SFString.strptr)) break; /* int32>>char function*/
282  v.i = (int)(char)node->X3D_SFString.strptr[item]; vtype = FIELDTYPE_SFInt32; break;
283  case FIELDTYPE_SFNode:
284  if(item > 0) break;
285  v.i = (int)node->X3D_SFNode.adr; vtype = FIELDTYPE_SFInt32; break;
286  case FIELDTYPE_SFRotation:
287  if(item > 3) break;
288  v.f = node->X3D_SFRotation.r[item]; vtype =FIELDTYPE_SFFloat; break;
289  case FIELDTYPE_SFVec2f:
290  if(item > 1) break;
291  v.f = node->X3D_SFVec2f.c[item]; vtype =FIELDTYPE_SFFloat; break;
292  case FIELDTYPE_SFVec3f:
293  if(item > 2) break;
294  v.f = node->X3D_SFVec3f.c[item];vtype =FIELDTYPE_SFFloat; break;
295  case FIELDTYPE_SFColorRGBA:
296  if(item > 3) break;
297  v.f = node->X3D_SFColorRGBA.r[item]; vtype =FIELDTYPE_SFFloat; break;
298  case FIELDTYPE_SFBool:
299  if(item > 0) break;
300  v.i = node->X3D_SFBool.value; vtype = FIELDTYPE_SFInt32; break;
301  case FIELDTYPE_SFVec3d:
302  if(item > 2) break;
303  v.d = node->X3D_SFVec3d.c[item]; vtype =FIELDTYPE_SFTime; break;
304  case FIELDTYPE_SFVec2d:
305  if(item > 1) break;
306  v.d = node->X3D_SFVec2d.c[item]; vtype =FIELDTYPE_SFTime; break;
307  default:
308  break;
309  }
310  switch(vtype)
311  {
312  case FIELDTYPE_SFTime:
313  return X3D_newSFTime(v.d); break;
314  case FIELDTYPE_SFFloat:
315  return X3D_newSFFloat(v.f); break;
316  case FIELDTYPE_SFInt32:
317  return X3D_newSFInt32(v.i); break;
318  case FIELDTYPE_SFBool:
319  return X3D_newSFInt32(v.i); break;
320  default:
321  return NULL;
322  }
323  return NULL;
324 }
325 X3DNode* X3D_deepcopySF(X3DNode* node)
326 {
327  X3DNode* retval;
328  /*returns deep copy of field*/
329  float* f;
330  double* d;
331  char* s;
332  int n;
333  int ntype = node->type;
334  switch(ntype)
335  {
336  case FIELDTYPE_SFColor:
337  f = node->X3D_SFColor.c;
338  retval = X3D_newSFColor(f[0],f[1],f[2]); break;
339  case FIELDTYPE_SFFloat:
340  retval = X3D_newSFFloat(node->X3D_SFFloat.value); break;
341  case FIELDTYPE_SFTime:
342  retval = X3D_newSFTime(node->X3D_SFTime.value); break;
343  case FIELDTYPE_SFInt32:
344  retval = X3D_newSFInt32(node->X3D_SFInt32.value); break;
345  case FIELDTYPE_SFString:
346  retval = X3D_newSFString(node->X3D_SFString.strptr);
347  s = node->X3D_SFString.strptr;
348  n = min(strlen(s)+1,STRLEN);
349  retval->X3D_SFString.strptr = malloc(n);
350  strncpy(retval->X3D_SFString.strptr,s,n);
351  retval->X3D_SFString.len = strlen(s);
352  break;
353  case FIELDTYPE_SFNode:
354  retval = X3D_newSFNode(); break;
355  case FIELDTYPE_SFRotation:
356  f = node->X3D_SFRotation.r;
357  retval = X3D_newSFRotation(f[0],f[1],f[2],f[3]); break;
358  case FIELDTYPE_SFVec2f:
359  f = node->X3D_SFVec2f.c;
360  retval = X3D_newSFVec2f(f[0],f[1]); break;
361  case FIELDTYPE_SFVec3f:
362  f = node->X3D_SFVec3f.c;
363  retval = X3D_newSFVec3f(f[0],f[1],f[2]); break;
364  case FIELDTYPE_SFColorRGBA:
365  f = node->X3D_SFColorRGBA.r;
366  retval = X3D_newSFColorRGBA(f[0],f[1],f[2],f[3]); break;
367  case FIELDTYPE_SFBool:
368  retval = X3D_newSFBool(node->X3D_SFBool.value); break;
369  case FIELDTYPE_SFVec3d:
370  retval = NULL;
371  break;
372  case FIELDTYPE_SFVec2d:
373  d = node->X3D_SFVec2d.c;
374  retval = X3D_newSFVec2d(d[0],d[1]); break;
375  default:
376  break;
377  }
378  return retval;
379 }
380 void _X3D_setItemMF(X3DNode* node, int item, X3DNode* value)
381 {
382  unsigned long sz;
383  char * target;
384  char * newstr;
385  if( !isSF(value->type) )return; /* we're supposed to be setting an SF into an MF */
386  if( node->type != value->type+1 )return; /* must be same type ie mfstring and sfstring, or mfvec2d and sfvec2d */
387  if( item < 0 || item >= node->X3D_MFNode.n )return; /*space must have been allocated already, with swigNewMF(,#) or _grow(,,#) */
388  if( value->type == FIELDTYPE_SFString)
389  {
390  int len = min(value->X3D_SFString.len +1,STRLEN);
391  /*free(node->X3D_MFString.p[item].strptr); /* better be reasonably initialized ie to NULL in newSF */
392  FREE_IF_NZ(node->X3D_MFString.p[item].strptr);
393  newstr = malloc(len*sizeof(char));
394  strncpy(newstr,value->X3D_SFString.strptr,len); /*policy - a string is owned by only one node (no ref counting). so deep copy so SF and MF both own their own*/
395  }
396  sz = X3D_sizeof(value->type);
397  target = ((char *)(node->X3D_MFNode.p)) + sz*item;
398  memcpy(target,value,sz);
399  if( value->type == FIELDTYPE_SFString)
400  {
401  node->X3D_MFString.p[item].strptr = newstr;
402  node->X3D_MFString.p[item].len = strnlen(newstr,STRLEN);
403  }
404 }
405 X3DNode* _X3D_getItemMF(X3DNode* node, int item)
406 {
407  X3DNode* retval;
408  if( item < 0 || item >= node->X3D_MFNode.n )return NULL;
409  /* MSVC increments a pointer by the size of the data structure being pointed to
410  the way we do the p[] it is by specific type
411  */
412  retval = X3D_deepcopySF((X3DNode*)(((char *)(node->X3D_MFNode.p)) + item*X3D_sizeof(node->X3D_MFNode.p[0].type)));
413  return retval;
414 
415  /* if noncontiguous this would probably work
416  X3D_freeNode(node->X3D_MFNode.p[item]);
417  node->X3D_MFNode.p[item] = X3D_deepcopySF(value);
418  */
419  retval = X3D_newSF(node->type -1);
420  if( retval->type == FIELDTYPE_SFString) free(retval->X3D_SFString.strptr); /*should be '\0' */
421  memcpy(retval,&(node->X3D_MFNode.p[item]),X3D_sizeof(retval->type)); /*len should get copied here, strptr too though*/
422  if( retval->type == FIELDTYPE_SFString)
423  {
424  int len = min(node->X3D_SFString.len+1,STRLEN);
425  retval->X3D_SFString.strptr = malloc(len);
426  strncpy(retval->X3D_SFString.strptr,node->X3D_SFString.strptr,len);
427  }
428 
429  return retval;
430 }
431 
432 void X3D_swigSetItem(X3DNode* node, int item, X3DNode* value)
433 {
434  if(isMF(node->type)) _X3D_setItemMF(node,item,value);
435  else if( isSF(value->type) )_X3D_setItemSF(node,item,value);
436 }
437 X3DNode* X3D_swigGetItem(X3DNode* node, int item)
438 {
439  if(isMF(node->type)) return _X3D_getItemMF(node,item);
440  else if( isSF(node->type) ) return _X3D_getItemSF(node,item);
441  return NULL;
442 }
443 void _grow(X3DNode *node, int num, int more)
444 {
445  _intX3D_SFNode *tmp,*p;
446  tmp = node->X3D_MFNode.p;
447  p = malloc(sizeof (X3DNode) * (num+more));
448  bzero(p,sizeof (X3DNode) * (num+more));
449  if(num > 0)
450  {
451  memcpy(p,tmp,sizeof(X3DNode)*num);
452  free(tmp);
453  }
454  node->X3D_MFNode.p = p;
455  node->X3D_MFNode.n = num + more;
456 }
457 void X3D_swigAppendToMF(X3DNode* node, X3DNode* value)
458 {
459  int num, item;
460  if( node != NULL && value != NULL )
461  {
462  if(isMF(node->type) && isSF(value->type))
463  {
464  if(node->type == value->type+1)
465  {
466  num = node->X3D_MFNode.n;
467  _grow(node,num,1);
468  item = node->X3D_MFNode.n -1;
469  _X3D_setItemMF(node,item,value);
470  }
471  }
472  }
473 }
474 
475 int getnumtokens(char* str,char *delim)
476 {
477  int n;
478  char *tokens;
479  n = 0;
480  tokens = strtok(str,delim);
481  while(tokens != NULL)
482  {
483  n++;
484  tokens = strtok(NULL,delim);
485  }
486  return n;
487 }
488 char * _x3ditoa(int ival, char* bigbuf)
489 {
490  char *retbuf;
491  int len;
492  sprintf(bigbuf,"%d ",ival); /*note blank separator */
493  len = strlen(bigbuf);
494  retbuf = MALLOC(char *, len+1);
495  strcpy(retbuf,bigbuf);
496  return retbuf;
497 }
498 char * _x3dftoa(float fval, char* bigbuf)
499 {
500  char *retbuf;
501  int len;
502  sprintf(bigbuf,"%f ",fval); /*note blank separator */
503  len = strlen(bigbuf);
504  retbuf = MALLOC(char *, len+1);
505  strcpy(retbuf,bigbuf);
506  return retbuf;
507 }
508 char * _x3ddtoa(double dval, char* bigbuf)
509 {
510  char *retbuf;
511  int len;
512  sprintf(bigbuf,"%f ",dval); /*note blank separator */
513  len = strlen(bigbuf);
514  retbuf = MALLOC(char *, len+1);
515  strcpy(retbuf,bigbuf);
516  return retbuf;
517 }
518 char * _x3datoa(char *aval, char* bigbuf)
519 {
520  /* hello -> "hello", strlen(aval)==0? -> "" */
521  char *retbuf;
522  int len;
523  len = strlen(aval);
524  retbuf = MALLOC(char *, len+4);
525  sprintf(retbuf,"\"%s\" ",aval);
526  retbuf[len+3] = '\0';
527  return retbuf;
528 }
529 char * X3D_swigStringFromField(X3DNode* field)
530 {
531  /*
532  issue: swig treats C arrays as opaque pointers - not very helpful. How to get a specific SF from an MF field?
533  but- swig does pass a char * as scalar string properly
534  goal: convert an MF (or SF) field to a string for easy parsing from a swigged scripting language
535  "itype n sf1 sf2 sf3"
536  sffloat "0 1 -123.456" - the count will always be 1
537  mffloat "1 2 -123.456 555.444"
538  sfstring "24 \"OK folks let's rock it!\""
539  mfstring "25 2 \"You know...\" \"I'm not so sure about 'rocking' it.\"'
540  */
541  int type, ismf, count, i, size;
542  char** tokens;
543  char *string;
544  char buf[500];
545  type = field->type;
546  if(type < 0 || type > 41 ) /*yikes - is there a MAXFIELDTYPE or other validity check? */
547  return NULL; /* or should it be " 'NULL' " */
548  ismf = type % 2;
549  count = 2;
550  if( ismf )
551  count = count + field->X3D_MFNode.n;
552  else
553  count = count + 1;
554  tokens = (char** )malloc(count*sizeof(char*));
555  /*buf = MALLOC(char *, 500); /*just for 1 token - sf string might be the largest*/
556  switch (type)
557  {
558  case FIELDTYPE_SFFloat:
559  tokens[0] = _x3ditoa(FIELDTYPE_SFFloat, buf);
560  tokens[1] = _x3ditoa(1,buf);
561  tokens[2] = _x3dftoa(field->X3D_SFFloat.value, buf);
562  break;
563  case FIELDTYPE_MFFloat:
564  tokens[0] = _x3ditoa(FIELDTYPE_MFFloat,buf);
565  tokens[1] = _x3ditoa(field->X3D_MFNode.n,buf);
566  for(i=0;i<count-2;i++)
567  tokens[i+2] = _x3dftoa(field->X3D_MFFloat.p[i].value,buf);
568  break;
569  case FIELDTYPE_MFString:
570  tokens[0] = _x3ditoa(FIELDTYPE_MFString,buf);
571  tokens[1] = _x3ditoa(field->X3D_MFString.n,buf);
572  for(i=0;i<count-2;i++)
573  tokens[i+2] = _x3datoa(field->X3D_MFString.p[i].strptr,buf);
574  break;
575  }
576  size = 0;
577  for(i=0;i<count;i++) size = size + strlen(tokens[i]);
578  /* FREE_IF_NZ(buf); */
579  string = MALLOC(char *, (size+1)*sizeof(char));
580  string[0] = '\0';
581  for(i=0;i<count;i++)
582  {
583  strcat(string,tokens[i]);
584  FREE_IF_NZ(tokens[i]);
585  }
586  FREE_IF_NZ(tokens);
587  return string; /* somebody else has to free this (option: return as X3D_SFString then X3D_free */
588 }
589 
590 X3DNode* X3D_swigFieldFromString(char* fieldtype, char* values)
591 {
592  /*
593  issue: swig treats C arrays as opaque pointers - not very helpful. How to create an MF from a sequence of SF fields?
594  goal: convert string into a field - sf or mf - for easy use from swigged scripting language
595  /* mf = X3D_fieldFromString("MFString","111.11 222.22"); will do SF as well */
596  X3DNode* retval;
597  int type,count;
598  char* vals; /* **carray, *c; */
599  int len,i,n,start,end, inum;
600  float f, *farray, **f2,**f3,**f4;
601  double d,*darray, **d2,**d3,**d4;
602  char *token = NULL;
603  char *delim = " ,";
604 
605  if(fieldtype == NULL || values == NULL) return NULL;
606  type = findFieldInFIELDTYPES(fieldtype);
607  /* if( type == -1 ) return NULL; Q. is there an error return code? Where is ffift defined? */
608  /* do some qc */
609  len = strlen(values);
610  vals = (char*) malloc(len);
611  memcpy(vals,values,len); /* getnumtokens is destructive, and a const string produces error - so use copy from original*/
612  switch (type)
613  {
614  case FIELDTYPE_SFFloat:
615  /*
616  token = strtok(values,delim);
617  if( sscanf(token,"%f",&f) == 1)
618  retval = X3D_newSFFloat(f);
619  break;
620  */
621  case FIELDTYPE_MFFloat:
622  case FIELDTYPE_SFVec2f:
623  case FIELDTYPE_MFVec2f:
624  case FIELDTYPE_SFVec3f:
625  case FIELDTYPE_MFVec3f:
626  case FIELDTYPE_SFRotation:
627  case FIELDTYPE_MFRotation:
628  case FIELDTYPE_SFColorRGBA:
629  case FIELDTYPE_MFColorRGBA:
630  case FIELDTYPE_SFColor:
631  case FIELDTYPE_MFColor:
632 
633  count = getnumtokens(vals,delim);
634  farray = MALLOC(float *, count*sizeof(float));
635  memcpy(vals,values,len);
636  token = strtok(vals,delim);
637  count = 0;
638  while (token != NULL) {
639  if( sscanf(token,"%f",&f)==1 )/* = strtof(tokens);*/
640  {
641  farray[count] = f;
642  count++;
643  }
644  token = strtok(NULL,delim);
645  }
646  f2 = MALLOC(float **, count*sizeof(float*));
647  f3 = MALLOC(float **, count*sizeof(float*));
648  f4 = MALLOC(float **, count*sizeof(float*));
649  for(i=0;i<count;i++)
650  {
651  f2[i] = &farray[i*2];
652  f3[i] = &farray[i*3];
653  f4[i] = &farray[i*4];
654  }
655  switch(type)
656  {
657  case FIELDTYPE_SFFloat:
658  retval = X3D_newSFFloat(farray[0]);
659  case FIELDTYPE_MFFloat:
660  retval = X3D_newMFFloat(count, farray); break;
661  case FIELDTYPE_SFVec2f:
662  retval = X3D_newSFVec2f(farray[0],farray[1]);break;
663  case FIELDTYPE_SFVec3f:
664  retval = X3D_newSFVec3f(farray[0],farray[1],farray[2]);break;
665  case FIELDTYPE_MFVec3f:
666  retval = X3D_newMFVec3f(count,f3);break;
667  case FIELDTYPE_SFRotation:
668  retval = X3D_newSFRotation(farray[0],farray[1],farray[2],farray[3]);break;
669  case FIELDTYPE_MFRotation:
670  retval = X3D_newMFRotation(count,f4);break;
671  case FIELDTYPE_SFColorRGBA:
672  retval = X3D_newSFColorRGBA(farray[0],farray[1],farray[2],farray[3]);break;
673  case FIELDTYPE_MFColorRGBA:
674  retval = X3D_newMFColorRGBA(count,f4);break;
675  case FIELDTYPE_MFColor:
676  retval = X3D_newMFColor(count,f3);break;
677 
678  }
679  FREE_IF_NZ(farray);
680  FREE_IF_NZ(f2);
681  FREE_IF_NZ(f3);
682  FREE_IF_NZ(f4);
683  break;
684  case FIELDTYPE_SFBool:
685  case FIELDTYPE_SFInt32:
686  token = strtok(values,delim); /*string delims*/
687  if( sscanf(token,"%d",&inum) == 1)
688  {
689  if(type == FIELDTYPE_SFInt32) retval = X3D_newSFInt32(inum);
690  if(type == FIELDTYPE_SFBool) retval = X3D_newSFBool(inum);
691  }
692  break;
693  case FIELDTYPE_SFTime:
694  case FIELDTYPE_SFVec2d:
695  case FIELDTYPE_SFVec3d:
696  count = getnumtokens(vals,delim);
697  darray = MALLOC(double *, count*sizeof(double));
698  memcpy(vals,values,len);
699  token = strtok(vals,delim);
700  count = 0;
701  while (token != NULL) {
702  if( sscanf(token,"%lf",&d)==1 )/* = strtof(tokens);*/
703  {
704  darray[count] = d;
705  count++;
706  }
707  token = strtok(NULL,delim);
708  }
709  d2 = MALLOC(double **, count*sizeof(double*));
710  d3 = MALLOC(double **, count*sizeof(double*));
711  d4 = MALLOC(double **, count*sizeof(double*));
712  for(i=0;i<count;i++)
713  {
714  d2[i] = &darray[i*2];
715  d3[i] = &darray[i*3];
716  d4[i] = &darray[i*4];
717  }
718  switch(type)
719  {
720  case FIELDTYPE_SFTime:
721  retval = X3D_newSFTime(darray[0]); break;
722  case FIELDTYPE_SFVec2d:
723  retval = X3D_newSFVec2d(darray[0],darray[1]);break;
724  case FIELDTYPE_SFVec3d:
725  retval = X3D_newMFVec3d(count,d3); break;
726  }
727  FREE_IF_NZ(darray);
728  FREE_IF_NZ(d2);
729  FREE_IF_NZ(d3);
730  FREE_IF_NZ(d4);
731  break;
732 
733 
734  case FIELDTYPE_SFString:
735  /*
736  retval->X3D_SFString.type = FIELDTYPE_SFString;
737  len = strlen(values);
738  retval->X3D_SFString.p[count].strptr = MALLOC(char *, (len+1)*sizeof(char));
739  strncpy(retval->X3D_SFString.p[count].strptr,values,len);
740  retval->X3D_SFString.strptr[len] = '\0';
741  retval->X3D_SFString.len = len;
742  */
743  retval = X3D_newSFString(values);
744  break;
745 
746  case FIELDTYPE_MFString:
747  retval = malloc(sizeof(X3DNode));
748  retval->X3D_MFString.type = FIELDTYPE_MFString;
749  n = 0;
750  for(i=0;i<(int)strlen(vals);i++)
751  if( vals[i] == '\"' )n++;
752  n = n/2;
753  /*
754  c = MALLOC(char *, n*STRLEN*sizeof(char));
755  carray = MALLOC(char **, n*(sizeof(char*)));
756  for(i=0;i<n;i++)
757  carray[i] = &c[i*STRLEN];
758  */
759  retval->X3D_MFString.n = n;
760  retval->X3D_MFString.p = malloc(sizeof(X3DNode)*retval->X3D_MFString.n);
761  count = 0;
762  for(i=0,n=0;i<(int)strlen(vals);i++)
763  {
764  if( vals[i] == '\"' )
765  {
766  n++;
767  if(n%2) start = i;
768  else
769  {
770  end = i;
771  len = end - start; /* if "Y" start=0,end=2 need a string 2 long for Y and \0. len=end-start= 2-0=2 */
772  retval->X3D_MFString.p[count].strptr = MALLOC(char *, len*sizeof(char));
773  strncpy(retval->X3D_MFString.p[count].strptr,&vals[start+1],len-1);
774  /*strncpy(carray[count],&vals[start+1],len-1);
775  carray[count][len-1] = '\0';*/
776  retval->X3D_MFString.p[count].strptr[len-1] = '\0';
777  retval->X3D_MFString.p[count].len = len-1;
778  count++;
779  }
780  }
781  }
782  /*retval = X3D_newMFString(count, carray);*/
783  break;
784  }
785  FREE_IF_NZ(vals); /*free(vals);*/
786  return retval;
787 }
788 X3DNode* anyVrml2X3DNode(int type, union anyVrml* node)
789 {
790  /*
791  anyVrml - see CParseGeneral.h L.39 and VrmlTypeList.h and Structs.h L.1270
792  Uni_String - see structs.h L.38
793  X3DNode - see X3DNode.h
794  Strategy: deepcopy from anyVrml to X3DNode (put .type on front of everything) and return
795  */
796  X3DNode* retval;
797  retval = NULL;
798  if( type%2 == 0) /* SF */
799  {
800  int i;
801  retval = X3D_newSF(type);
802  switch(type)
803  {
804  case FIELDTYPE_SFInt32:
805  retval->X3D_SFInt32.value = node->sfint32; break;
806  case FIELDTYPE_SFBool:
807  retval->X3D_SFBool.value = node->sfbool; break;
808  case FIELDTYPE_SFFloat:
809  retval->X3D_SFFloat.value = node->sffloat; break;
810  case FIELDTYPE_SFTime:
811  retval->X3D_SFTime.value = node->sftime; break;
812  case FIELDTYPE_SFColorRGBA:
813  case FIELDTYPE_SFRotation:
814  for(i=0;i<4;i++)
815  retval->X3D_SFRotation.r[i] = node->sfrotation.r[i];
816  break;
817  case FIELDTYPE_SFVec2f:
818  for(i=0;i<2;i++)
819  retval->X3D_SFVec2f.c[i] = node->sfvec2f.c[i];
820  break;
821  case FIELDTYPE_SFVec3f:
822  case FIELDTYPE_SFColor:
823  for(i=0;i<3;i++)
824  retval->X3D_SFVec3f.c[i] = node->sfvec3f.c[i];
825  break;
826  case FIELDTYPE_SFVec3d:
827  for(i=0;i<3;i++)
828  retval->X3D_SFVec3d.c[i] = node->sfvec3d.c[i];
829  break;
830  case FIELDTYPE_SFVec2d:
831  for(i=0;i<2;i++)
832  retval->X3D_SFVec2d.c[i] = node->sfvec2d.c[i];
833  break;
834  case FIELDTYPE_SFString:
835  retval->X3D_SFString.len = node->sfstring->len;
836  retval->X3D_SFString.strptr = (char*)malloc(node->sfstring->len + 1);
837  strncpy(retval->X3D_SFString.strptr,node->sfstring->strptr,node->sfstring->len+1);
838  break;
839  }
840  }
841  if( type%2 != 0) /* MF */
842  {
843  int i,j,n, sftype;
844 
845  n = node->mfnode.n;
846  retval = _swigNewMF(type, n);
847  sftype = type -1;
848  switch(sftype)
849  {
850  case FIELDTYPE_SFInt32:
851  for(j=0;j<n;j++)
852  retval->X3D_MFInt32.p[j].value = node->mfint32.p[j];
853  break;
854  case FIELDTYPE_SFBool:
855  for(j=0;j<n;j++)
856  retval->X3D_MFBool.p[j].value = node->mfbool.p[j];
857  break;
858  case FIELDTYPE_SFFloat:
859  for(j=0;j<n;j++)
860  retval->X3D_MFFloat.p[j].value = node->mffloat.p[j];
861  break;
862  case FIELDTYPE_SFTime:
863  for(j=0;j<n;j++)
864  retval->X3D_MFTime.p[j].value = node->mftime.p[j];
865  break;
866  case FIELDTYPE_SFColorRGBA:
867  case FIELDTYPE_SFRotation:
868  for(j=0;j<n;j++)
869  for(i=0;i<4;i++)
870  retval->X3D_MFRotation.p[j].r[i] = node->mfrotation.p[j].r[i];
871  break;
872  case FIELDTYPE_SFVec2f:
873  for(j=0;j<n;j++)
874  for(i=0;i<2;i++)
875  retval->X3D_MFVec2f.p[j].c[i] = node->mfvec2f.p[j].c[i];
876  break;
877  case FIELDTYPE_SFVec3f:
878  case FIELDTYPE_SFColor:
879  for(j=0;j<n;j++)
880  for(i=0;i<3;i++)
881  retval->X3D_MFVec3f.p[j].c[i] = node->mfvec3f.p[j].c[i];
882  break;
883  case FIELDTYPE_SFVec3d:
884  for(j=0;j<n;j++)
885  for(i=0;i<3;i++)
886  retval->X3D_MFVec3d.p[j].c[i] = node->mfvec3d.p[j].c[i];
887  break;
888  case FIELDTYPE_SFString:
889  for(j=0;j<n;j++)
890  {
891  retval->X3D_MFString.p[j].len = node->mfstring.p[j]->len;
892  retval->X3D_MFString.p[j].strptr = (char*)malloc(node->mfstring.p[j]->len + 1);
893  strncpy(retval->X3D_MFString.p[j].strptr,node->mfstring.p[j]->strptr,node->mfstring.p[j]->len+1);
894  }
895  break;
896  }
897  }
898  return retval;
899 }
900 union anyVrml* getListenerData(int index);
901 int getListenerType(int index);
902 X3DNode* X3D_swigCallbackDataFetch(char *ListenerTableIndex)
903 {
904  /* relies on:
905  a) what sarah said:
906  "the data is sent as a binary block of data, basically as the contents of X3DNode.p or equivalent.
907  If you know what type of data you are receiving from the socket (which you should after reading
908  the first number: the advise index should tie you to a specific callback function),
909  can you not read the information from the socket directly?"
910  b) doug's assumption - anyVrml:
911  When I trace it looks like if you pass coffset=0 into Parser_scanStringValueToMem as we are doing in _handleFreeWRLcallback(),
912  you get back something like SFVec2f L.1278 Structs.h which looks like our X3DNode except missing the .type,
913  and I assume it is:
914  union anyVrml - see CParseGeneral.h L.39 and VrmlTypeList.h and Structs.h L.1270
915  c) slow - the events are coming spaced out with enough time for you to fetch the data from the listenertable before it gets overwritten
916  there's no table locking.
917  Alternative: But if this isn't a good assumption, then in the handler below you can anyVrml2X3DNode right there
918  and send the malloced address instead of the listenertable index. Then on fetch, cast the address to an X3DNode.
919  */
920 
921  int index, type;
922  X3DNode* retval;
923  union anyVrml* anynode;
924 
925  retval = NULL;
926  if( sscanf(ListenerTableIndex,"%d",&index) < 1)
927  return retval;
928  //anynode = (union anyVrml*)EAI_ListenerTable[index].dataArea;
929  //type = EAI_ListenerTable[index].type;
930  anynode = getListenerData(index);
931  type = getListenerType(index);
932  retval = anyVrml2X3DNode(type, anynode);
933  return retval;
934 }
935 
936 #endif