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