1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 // This file contains various functions that are shared between two or
34 // more field classes.
35 //
36 // Typically there's some common code for both the single-field value
37 // and multiple-field value version of the same field-type.
38 
39 // *************************************************************************
40 
41 // FIXME: SoSFEnum and SoMFEnum could probably share some of their
42 // read / write code. Ditto for SoSFImage and SoSFImage3. If so, it
43 // should be collected here. 20040630 mortene.
44 
45 // *************************************************************************
46 
47 #include "shared.h"
48 
49 #include <Inventor/SbMatrix.h>
50 #include <Inventor/SbName.h>
51 #include <Inventor/SbPlane.h>
52 #include <Inventor/SbRotation.h>
53 #include <Inventor/SbTime.h>
54 
55 #include <Inventor/SbVec2b.h>
56 #include <Inventor/SbVec2ub.h>
57 #include <Inventor/SbVec2s.h>
58 #include <Inventor/SbVec2us.h>
59 #include <Inventor/SbVec2i32.h>
60 #include <Inventor/SbVec2ui32.h>
61 #include <Inventor/SbVec2f.h>
62 #include <Inventor/SbVec2d.h>
63 
64 #include <Inventor/SbVec3b.h>
65 #include <Inventor/SbVec3ub.h>
66 #include <Inventor/SbVec3s.h>
67 #include <Inventor/SbVec3us.h>
68 #include <Inventor/SbVec3i32.h>
69 #include <Inventor/SbVec3ui32.h>
70 #include <Inventor/SbVec3f.h>
71 #include <Inventor/SbVec3d.h>
72 
73 #include <Inventor/SbVec4b.h>
74 #include <Inventor/SbVec4ub.h>
75 #include <Inventor/SbVec4s.h>
76 #include <Inventor/SbVec4us.h>
77 #include <Inventor/SbVec4i32.h>
78 #include <Inventor/SbVec4ui32.h>
79 #include <Inventor/SbVec4f.h>
80 #include <Inventor/SbVec4d.h>
81 
82 #include <Inventor/SoInput.h>
83 #include <Inventor/SoOutput.h>
84 #include <Inventor/errors/SoReadError.h>
85 #include <Inventor/fields/SoField.h>
86 #include <Inventor/nodes/SoNode.h>
87 
88 #include "tidbitsp.h"
89 #include "SbBasicP.h"
90 
91 // *************************************************************************
92 
93 // Read boolean value from input stream, return TRUE if
94 // successful. Used from SoSFBool and SoMFBool.
95 SbBool
sosfbool_read_value(SoInput * in,SbBool & val)96 sosfbool_read_value(SoInput * in, SbBool & val)
97 {
98   // accept 0 or 1
99   if (in->read(val)) {
100     if (val != 0 && val != 1) {
101       SoReadError::post(in, "Illegal value for field: %d (must be 0 or 1)",
102                         val);
103       return FALSE;
104     }
105     return TRUE;
106   }
107 
108   if (in->isBinary()) {
109     SoReadError::post(in, "Premature end of file");
110     return FALSE;
111   }
112 
113   // read TRUE/FALSE keyword
114 
115   SbName n;
116   if (!in->read(n, TRUE)) {
117     SoReadError::post(in, "Couldn't read field value");
118     return FALSE;
119   }
120 
121   if (n == "TRUE") {
122     val = TRUE;
123     return TRUE;
124   }
125 
126   if (n == "FALSE") {
127     val = FALSE;
128     return TRUE;
129   }
130 
131   SoReadError::post(in,
132                     "Invalid value \"%s\" for field (must be TRUE or FALSE)",
133                     n.getString());
134   return FALSE;
135 }
136 
137 
138 // Write boolean value to output stream. Used from SoSFBool and
139 // SoMFBool.
140 void
sosfbool_write_value(SoOutput * out,SbBool val)141 sosfbool_write_value(SoOutput * out, SbBool val)
142 {
143   if (out->isBinary()) out->write(static_cast<unsigned int>(val ? 1 : 0));
144   else out->write(val ? "TRUE" : "FALSE");
145 }
146 
147 // *************************************************************************
148 
149 // Write floating point value to output stream. Used from SoSFFloat
150 // and SoMFFloat.
151 void
sosffloat_write_value(SoOutput * out,float val)152 sosffloat_write_value(SoOutput * out, float val)
153 {
154   out->write(val);
155 }
156 
157 // Write double precision floating point value to output stream. Used from
158 // SoSFDouble and SoMFDouble.
159 void
sosfdouble_write_value(SoOutput * out,double val)160 sosfdouble_write_value(SoOutput * out, double val)
161 {
162   out->write(val);
163 }
164 
165 // *************************************************************************
166 
167 // Write SbString value to output stream. Used from SoSFString and
168 // SoMFString.
169 void
sosfstring_write_value(const SoField * f,SoOutput * out,const SbString & val)170 sosfstring_write_value(const SoField * f, SoOutput * out, const SbString & val)
171 {
172   // VRML97 needs backslashes themselves to be backslash-quoted (like
173   // in e.g. C strings), which is taken care of here instead of
174   // downstream, as this is the last place we can find out whether or
175   // not we're writing a VRML97 node.
176   const SoFieldContainer * fc = f->getContainer();
177   if (fc && fc->isOfType(SoNode::getClassTypeId()) &&
178       (coin_assert_cast<const SoNode *>(fc)->getNodeType() & SoNode::VRML2)) {
179     // FIXME: SbString should have had a replaceAll() method, so we
180     // wouldn't have to spell out the iteration loop below. 20040614 mortene.
181     SbString ws;
182     for (int i = 0; i < val.getLength(); i++) {
183       if (val[i] == '\\') { ws += '\\'; }
184       ws += val[i];
185     }
186     out->write(ws);
187   }
188   else { // *Not* a VRML97 node, so write backslashes verbatim, as
189          // dictated by the Inventor file format:
190     out->write(val);
191   }
192 }
193 
194 // *************************************************************************
195 
196 // Write matrix to output stream. Used from SoSFMatrix and SoMFMatrix.
197 void
sosfmatrix_write_value(SoOutput * out,const SbMatrix & m)198 sosfmatrix_write_value(SoOutput * out, const SbMatrix & m)
199 {
200   if (out->isBinary()) {
201     for(int i = 0; i < 4; i++) {
202       for(int j = 0; j < 4; j++) {
203         out->write(m[i][j]);
204       }
205     }
206     return;
207   }
208 
209 
210   for(int k=0; k < 4; k++) {
211     out->write(m[0][k]);
212     if(k != 3) out->write(' ');
213   }
214 
215   out->write('\n');
216   out->incrementIndent();
217 
218   for(int i=1; i < 4; i++) {
219     out->indent();
220     for(int j=0; j < 4; j++) {
221       out->write(m[i][j]);
222       if(j != 3) out->write(' ');
223     }
224     if(i != 3) out->write('\n');
225   }
226 
227   out->decrementIndent();
228 }
229 
230 // *************************************************************************
231 
232 // Read SbPlane from input stream, return TRUE if successful.  Used
233 // from SoSFPlane and SoMFPlane.
234 SbBool
sosfplane_read_value(SoInput * in,SbPlane & p)235 sosfplane_read_value(SoInput * in, SbPlane & p)
236 {
237   float f[4];
238   for (int i = 0; i < 4; i++) {
239     if (!in->read(f[i])) return FALSE;
240   }
241   p = SbPlane(SbVec3f(f[0], f[1], f[2]), f[3]);
242   return TRUE;
243 }
244 
245 // Write SbPlane value to output stream. Used from SoSFPlane and
246 // SoMFPlane.
247 void
sosfplane_write_value(SoOutput * out,const SbPlane & p)248 sosfplane_write_value(SoOutput * out, const SbPlane & p)
249 {
250   out->write(p.getNormal()[0]);
251   if (!out->isBinary()) out->write(' ');
252   out->write(p.getNormal()[1]);
253   if (!out->isBinary()) out->write(' ');
254   out->write(p.getNormal()[2]);
255   if (!out->isBinary()) out->write("  ");
256   out->write(p.getDistanceFromOrigin());
257 }
258 
259 // *************************************************************************
260 
261 // Read rotation value from input stream, return TRUE if
262 // successful. Used from SoSFRotation and SoMFRotation.
263 SbBool
sosfrotation_read_value(SoInput * in,SbRotation & r)264 sosfrotation_read_value(SoInput * in, SbRotation & r)
265 {
266   float f[4];
267   for (int i = 0; i < 4; i++) {
268     if (!in->read(f[i])) return FALSE;
269   }
270   SbVec3f axis(f[0], f[1], f[2]);
271   const float angle = f[3];
272 
273   // vrml97 identity rotations are often specified with a null vector.
274   // test for this and just set to z-axis.
275   if (axis == SbVec3f(0.0f, 0.0f, 0.0f) && angle == 0.0f) {
276     axis = SbVec3f(0.0f, 0.0f, 1.0f);
277   }
278   r.setValue(axis, angle);
279   return TRUE;
280 }
281 
282 // Write SbRotation to output stream. Used from SoSFRotation and
283 // SoMFRotation.
284 void
sosfrotation_write_value(SoOutput * out,const SbRotation & r)285 sosfrotation_write_value(SoOutput * out, const SbRotation & r)
286 {
287   SbVec3f axis;
288   float angle;
289   r.getValue(axis, angle);
290 
291   // Handle invalid rotation specifications.
292   if (axis.length() == 0.0f) {
293     axis.setValue(0.0f, 0.0f, 1.0f);
294     angle = 0.0f;
295   }
296 
297   out->write(axis[0]);
298   if(!out->isBinary()) out->write(' ');
299   out->write(axis[1]);
300   if(!out->isBinary()) out->write(' ');
301   out->write(axis[2]);
302   if(!out->isBinary()) out->write("  ");
303   out->write(angle);
304 }
305 
306 // *************************************************************************
307 
308 // Write integer value to output stream. Used from SoSFShort and
309 // SoMFShort.
310 void
sosfshort_write_value(SoOutput * out,short val)311 sosfshort_write_value(SoOutput * out, short val)
312 {
313   out->write(val);
314 }
315 
316 // *************************************************************************
317 
318 // Read SbTime from input stream, return TRUE if successful. Used from
319 // SoSFTime and SoMFTime.
320 SbBool
sosftime_read_value(SoInput * in,SbTime & t)321 sosftime_read_value(SoInput * in, SbTime & t)
322 {
323   double val;
324   if (!in->read(val)) {
325     SoReadError::post(in, "unable to read floating point value");
326     return FALSE;
327   }
328 
329   if (!coin_finite(val)) {
330     SoReadError::post(in,
331                       "Detected non-valid floating point number, replacing "
332                       "with 0.0f");
333     val = 0.0;
334     // We don't return FALSE, thereby allowing the read process to
335     // continue, as a convenience for the application programmer.
336   }
337 
338   t.setValue(val);
339   return TRUE;
340 }
341 
342 // Write SbTime value to output stream. Used from SoSFTime and
343 // SoMFTime.
344 void
sosftime_write_value(SoOutput * out,const SbTime & p)345 sosftime_write_value(SoOutput * out, const SbTime & p)
346 {
347   out->write(p.getValue());
348 }
349 
350 // *************************************************************************
351 
352 // Write integer value to output stream. Used from SoSFUInt32 and
353 // SoMFUInt32.
354 void
sosfuint32_write_value(SoOutput * out,uint32_t val)355 sosfuint32_write_value(SoOutput * out, uint32_t val)
356 {
357   unsigned int tmp = static_cast<unsigned int>(val);
358   out->write(tmp);
359 }
360 
361 // *************************************************************************
362 
363 // Write integer value to output stream. Used from SoSFUShort and
364 // SoMFUShort.
365 void
sosfushort_write_value(SoOutput * out,unsigned short val)366 sosfushort_write_value(SoOutput * out, unsigned short val)
367 {
368   out->write(val);
369 }
370 
371 // *************************************************************************
372 
373 // Write to output stream. Used from SoSFVec2b and SoMFVec2b.
374 void
sosfvec2b_write_value(SoOutput * out,SbVec2b v)375 sosfvec2b_write_value(SoOutput * out, SbVec2b v)
376 {
377   // FIXME: check how write(char & c) writes it's data (ascii) and see if
378   // that can be used.  20070520 larsa
379   out->write(static_cast<short>(v[0]));
380   if (!out->isBinary()) out->write(' ');
381   out->write(static_cast<short>(v[1]));
382 }
383 
384 // Write to output stream. Used from SoSFVec2s and SoMFVec2s.
385 void
sosfvec2s_write_value(SoOutput * out,SbVec2s v)386 sosfvec2s_write_value(SoOutput * out, SbVec2s v)
387 {
388   out->write(v[0]);
389   if (!out->isBinary()) out->write(' ');
390   out->write(v[1]);
391 }
392 
393 // Write to output stream. Used from SoSFVec2i32 and SoMFVec2i32.
394 void
sosfvec2i32_write_value(SoOutput * out,const SbVec2i32 & v)395 sosfvec2i32_write_value(SoOutput * out, const SbVec2i32 & v)
396 {
397   out->write(v[0]);
398   if (!out->isBinary()) out->write(' ');
399   out->write(v[1]);
400 }
401 
402 // Write to output stream. Used from SoSFVec2f and SoMFVec2f.
403 void
sosfvec2f_write_value(SoOutput * out,const SbVec2f & v)404 sosfvec2f_write_value(SoOutput * out, const SbVec2f & v)
405 {
406   out->write(v[0]);
407   if (!out->isBinary()) out->write(' ');
408   out->write(v[1]);
409 }
410 
411 // Write to output stream. Used from SoSFVec2d and SoMFVec2d.
412 void
sosfvec2d_write_value(SoOutput * out,const SbVec2d & v)413 sosfvec2d_write_value(SoOutput * out, const SbVec2d & v)
414 {
415   out->write(v[0]);
416   if (!out->isBinary()) out->write(' ');
417   out->write(v[1]);
418 }
419 
420 // *************************************************************************
421 
422 // Read from input stream, return TRUE if successful. Used from
423 // SoSFVec3d and SoMFVec3f.
424 SbBool
sosfvec3d_read_value(SoInput * in,SbVec3d & v)425 sosfvec3d_read_value(SoInput * in, SbVec3d & v)
426 {
427   if (!in->read(v[0]) || !in->read(v[1]) || !in->read(v[2])) {
428     SoReadError::post(in, "Couldn't read vector");
429     return FALSE;
430   }
431   return TRUE;
432 }
433 
434 // Write to output stream. Used from SoSFVec3b and SoMFVec3b.
435 void
sosfvec3b_write_value(SoOutput * out,SbVec3b v)436 sosfvec3b_write_value(SoOutput * out, SbVec3b v)
437 {
438   out->write(static_cast<short>(v[0]));
439   if (!out->isBinary()) out->write(' ');
440   out->write(static_cast<short>(v[1]));
441   if (!out->isBinary()) out->write(' ');
442   out->write(static_cast<short>(v[2]));
443 }
444 
445 // Write to output stream. Used from SoSFVec3s and SoMFVec3s.
446 void
sosfvec3s_write_value(SoOutput * out,const SbVec3s & v)447 sosfvec3s_write_value(SoOutput * out, const SbVec3s & v)
448 {
449   out->write(v[0]);
450   if (!out->isBinary()) out->write(' ');
451   out->write(v[1]);
452   if (!out->isBinary()) out->write(' ');
453   out->write(v[2]);
454 }
455 
456 // Write to output stream. Used from SoSFVec3i32 and SoMFVec3i32.
457 void
sosfvec3i32_write_value(SoOutput * out,const SbVec3i32 & v)458 sosfvec3i32_write_value(SoOutput * out, const SbVec3i32 & v)
459 {
460   out->write(v[0]);
461   if (!out->isBinary()) out->write(' ');
462   out->write(v[1]);
463   if (!out->isBinary()) out->write(' ');
464   out->write(v[2]);
465 }
466 
467 // Write to output stream. Used from SoSFVec3f and SoMFVec3f.
468 void
sosfvec3f_write_value(SoOutput * out,const SbVec3f & v)469 sosfvec3f_write_value(SoOutput * out, const SbVec3f & v)
470 {
471   out->write(v[0]);
472   if (!out->isBinary()) out->write(' ');
473   out->write(v[1]);
474   if (!out->isBinary()) out->write(' ');
475   out->write(v[2]);
476 }
477 
478 // Write to output stream. Used from SoSFVec3d and SoMFVec3d.
479 void
sosfvec3d_write_value(SoOutput * out,const SbVec3d & v)480 sosfvec3d_write_value(SoOutput * out, const SbVec3d & v)
481 {
482   out->write(v[0]);
483   if (!out->isBinary()) out->write(' ');
484   out->write(v[1]);
485   if (!out->isBinary()) out->write(' ');
486   out->write(v[2]);
487 }
488 
489 // *************************************************************************
490 
491 // Write to output stream. Used from SoSFVec4b and SoMFVec4b.
492 void
sosfvec4b_write_value(SoOutput * out,SbVec4b v)493 sosfvec4b_write_value(SoOutput * out, SbVec4b v)
494 {
495   out->write(static_cast<short>(v[0]));
496   if (!out->isBinary()) out->write(' ');
497   out->write(static_cast<short>(v[1]));
498   if (!out->isBinary()) out->write(' ');
499   out->write(static_cast<short>(v[2]));
500   if (!out->isBinary()) out->write(' ');
501   out->write(static_cast<short>(v[3]));
502 }
503 
504 // Write to output stream. Used from SoSFVec4b and SoMFVec4b.
505 void
sosfvec4ub_write_value(SoOutput * out,SbVec4ub v)506 sosfvec4ub_write_value(SoOutput * out, SbVec4ub v)
507 {
508   out->write(static_cast<unsigned short>(v[0]));
509   if (!out->isBinary()) out->write(' ');
510   out->write(static_cast<unsigned short>(v[1]));
511   if (!out->isBinary()) out->write(' ');
512   out->write(static_cast<unsigned short>(v[2]));
513   if (!out->isBinary()) out->write(' ');
514   out->write(static_cast<unsigned short>(v[3]));
515 }
516 
517 // Write to output stream. Used from SoSFVec4s and SoMFVec4s.
518 void
sosfvec4s_write_value(SoOutput * out,const SbVec4s & v)519 sosfvec4s_write_value(SoOutput * out, const SbVec4s & v)
520 {
521   out->write(v[0]);
522   if (!out->isBinary()) out->write(' ');
523   out->write(v[1]);
524   if (!out->isBinary()) out->write(' ');
525   out->write(v[2]);
526   if (!out->isBinary()) out->write(' ');
527   out->write(v[3]);
528 }
529 
530 // Write to output stream. Used from SoSFVec4s and SoMFVec4s.
531 void
sosfvec4us_write_value(SoOutput * out,const SbVec4us & v)532 sosfvec4us_write_value(SoOutput * out, const SbVec4us & v)
533 {
534   out->write(v[0]);
535   if (!out->isBinary()) out->write(' ');
536   out->write(v[1]);
537   if (!out->isBinary()) out->write(' ');
538   out->write(v[2]);
539   if (!out->isBinary()) out->write(' ');
540   out->write(v[3]);
541 }
542 
543 // Write to output stream. Used from SoSFVec4i32 and SoMFVec4i32.
544 void
sosfvec4i32_write_value(SoOutput * out,const SbVec4i32 & v)545 sosfvec4i32_write_value(SoOutput * out, const SbVec4i32 & v)
546 {
547   out->write(v[0]);
548   if (!out->isBinary()) out->write(' ');
549   out->write(v[1]);
550   if (!out->isBinary()) out->write(' ');
551   out->write(v[2]);
552   if (!out->isBinary()) out->write(' ');
553   out->write(v[3]);
554 }
555 
556 // Write to output stream. Used from SoSFVec4i32 and SoMFVec4i32.
557 void
sosfvec4ui32_write_value(SoOutput * out,const SbVec4ui32 & v)558 sosfvec4ui32_write_value(SoOutput * out, const SbVec4ui32 & v)
559 {
560   out->write(v[0]);
561   if (!out->isBinary()) out->write(' ');
562   out->write(v[1]);
563   if (!out->isBinary()) out->write(' ');
564   out->write(v[2]);
565   if (!out->isBinary()) out->write(' ');
566   out->write(v[3]);
567 }
568 
569 // Write to output stream. Used from SoSFVec4f and SoMFVec4f.
570 void
sosfvec4f_write_value(SoOutput * out,const SbVec4f & v)571 sosfvec4f_write_value(SoOutput * out, const SbVec4f & v)
572 {
573   out->write(v[0]);
574   if (!out->isBinary()) out->write(' ');
575   out->write(v[1]);
576   if (!out->isBinary()) out->write(' ');
577   out->write(v[2]);
578   if (!out->isBinary()) out->write(' ');
579   out->write(v[3]);
580 }
581 
582 // Write to output stream. Used from SoSFVec4d and SoMFVec4d.
583 void
sosfvec4d_write_value(SoOutput * out,const SbVec4d & v)584 sosfvec4d_write_value(SoOutput * out, const SbVec4d & v)
585 {
586   out->write(v[0]);
587   if (!out->isBinary()) out->write(' ');
588   out->write(v[1]);
589   if (!out->isBinary()) out->write(' ');
590   out->write(v[2]);
591   if (!out->isBinary()) out->write(' ');
592   out->write(v[3]);
593 }
594 
595 // *************************************************************************
596