ImfXdr.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. //
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Copyright (c) Contributors to the OpenEXR Project.
  4. //
  5. #ifndef INCLUDED_IMF_XDR_H
  6. #define INCLUDED_IMF_XDR_H
  7. //----------------------------------------------------------------------------
  8. //
  9. // Xdr -- routines to convert data between the machine's native
  10. // format and a machine-independent external data representation:
  11. //
  12. // write<R> (T &o, S v); converts a value, v, of type S
  13. // into a machine-independent
  14. // representation and stores the
  15. // result in an output buffer, o.
  16. //
  17. // read<R> (T &i, S &v); reads the machine-independent
  18. // representation of a value of type
  19. // S from input buffer i, converts
  20. // the value into the machine's native
  21. // representation, and stores the result
  22. // in v.
  23. //
  24. // size<S>(); returns the size, in bytes, of the
  25. // machine-independent representation
  26. // of an object of type S.
  27. //
  28. // The write() and read() routines are templates; data can be written
  29. // to and read from any output or input buffer type T for which a helper
  30. // class, R, exits. Class R must define a method to store a char array
  31. // in a T, and a method to read a char array from a T:
  32. //
  33. // struct R
  34. // {
  35. // static void
  36. // writeChars (T &o, const char c[/*n*/], int n)
  37. // {
  38. // ... // Write c[0], c[1] ... c[n-1] to output buffer o.
  39. // }
  40. //
  41. // static void
  42. // readChars (T &i, char c[/*n*/], int n)
  43. // {
  44. // ... // Read n characters from input buffer i
  45. // // and copy them to c[0], c[1] ... c[n-1].
  46. // }
  47. // };
  48. //
  49. // Example - writing to and reading from iostreams:
  50. //
  51. // struct CharStreamIO
  52. // {
  53. // static void
  54. // writeChars (ostream &os, const char c[], int n)
  55. // {
  56. // os.write (c, n);
  57. // }
  58. //
  59. // static void
  60. // readChars (istream &is, char c[], int n)
  61. // {
  62. // is.read (c, n);
  63. // }
  64. // };
  65. //
  66. // ...
  67. //
  68. // Xdr::write<CharStreamIO> (os, 3);
  69. // Xdr::write<CharStreamIO> (os, 5.0);
  70. //
  71. //----------------------------------------------------------------------------
  72. #include "ImfNamespace.h"
  73. #include "IexMathExc.h"
  74. #include <half.h>
  75. #include <limits.h>
  76. #include <cstdint>
  77. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
  78. namespace Xdr {
  79. //-------------------------------
  80. // Write data to an output stream
  81. //-------------------------------
  82. template <class S, class T>
  83. void
  84. write (T &out, bool v);
  85. template <class S, class T>
  86. void
  87. write (T &out, char v);
  88. template <class S, class T>
  89. void
  90. write (T &out, signed char v);
  91. template <class S, class T>
  92. void
  93. write (T &out, unsigned char v);
  94. template <class S, class T>
  95. void
  96. write (T &out, signed short v);
  97. template <class S, class T>
  98. void
  99. write (T &out, unsigned short v);
  100. template <class S, class T>
  101. void
  102. write (T &out, signed int v);
  103. template <class S, class T>
  104. void
  105. write (T &out, unsigned int v);
  106. template <class S, class T>
  107. void
  108. write (T &out, int64_t v);
  109. template <class S, class T>
  110. void
  111. write (T &out, uint64_t v);
  112. template <class S, class T>
  113. void
  114. write (T &out, float v);
  115. template <class S, class T>
  116. void
  117. write (T &out, double v);
  118. template <class S, class T>
  119. void
  120. write (T &out, half v);
  121. template <class S, class T>
  122. void
  123. write (T &out, const char v[/*n*/], int n); // fixed-size char array
  124. template <class S, class T>
  125. void
  126. write (T &out, const char v[]); // zero-terminated string
  127. //-----------------------------------------
  128. // Append padding bytes to an output stream
  129. //-----------------------------------------
  130. template <class S, class T>
  131. void
  132. pad (T &out, int n); // write n padding bytes
  133. //-------------------------------
  134. // Read data from an input stream
  135. //-------------------------------
  136. template <class S, class T>
  137. void
  138. read (T &in, bool &v);
  139. template <class S, class T>
  140. void
  141. read (T &in, char &v);
  142. template <class S, class T>
  143. void
  144. read (T &in, signed char &v);
  145. template <class S, class T>
  146. void
  147. read (T &in, unsigned char &v);
  148. template <class S, class T>
  149. void
  150. read (T &in, signed short &v);
  151. template <class S, class T>
  152. void
  153. read (T &in, unsigned short &v);
  154. template <class S, class T>
  155. void
  156. read (T &in, signed int &v);
  157. template <class S, class T>
  158. void
  159. read (T &in, unsigned int &v);
  160. template <class S, class T>
  161. void
  162. read (T &in, int64_t &v);
  163. template <class S, class T>
  164. void
  165. read (T &in, uint64_t &v);
  166. template <class S, class T>
  167. void
  168. read (T &in, float &v);
  169. template <class S, class T>
  170. void
  171. read (T &in, double &v);
  172. template <class S, class T>
  173. void
  174. read (T &in, half &v);
  175. template <class S, class T>
  176. void
  177. read (T &in, char v[/*n*/], int n); // fixed-size char array
  178. template <class S, class T>
  179. void
  180. read (T &in, int n, char v[/*n*/]); // zero-terminated string
  181. //-------------------------------------------
  182. // Skip over padding bytes in an input stream
  183. //-------------------------------------------
  184. template <class S, class T>
  185. void
  186. skip (T &in, int n); // skip n padding bytes
  187. //--------------------------------------
  188. // Size of the machine-independent
  189. // representation of an object of type S
  190. //--------------------------------------
  191. template <class S>
  192. int
  193. size ();
  194. //---------------
  195. // Implementation
  196. //---------------
  197. template <class S, class T>
  198. inline void
  199. writeSignedChars (T &out, const signed char c[], int n)
  200. {
  201. S::writeChars (out, (const char *) c, n);
  202. }
  203. template <class S, class T>
  204. inline void
  205. writeUnsignedChars (T &out, const unsigned char c[], int n)
  206. {
  207. S::writeChars (out, (const char *) c, n);
  208. }
  209. template <class S, class T>
  210. inline void
  211. readSignedChars (T &in, signed char c[], int n)
  212. {
  213. S::readChars (in, (char *) c, n);
  214. }
  215. template <class S, class T>
  216. inline void
  217. readUnsignedChars (T &in, unsigned char c[], int n)
  218. {
  219. S::readChars (in, (char *) c, n);
  220. }
  221. template <class S, class T>
  222. inline void
  223. write (T &out, bool v)
  224. {
  225. char c = !!v;
  226. S::writeChars (out, &c, 1);
  227. }
  228. template <class S, class T>
  229. inline void
  230. write (T &out, char v)
  231. {
  232. S::writeChars (out, &v, 1);
  233. }
  234. template <class S, class T>
  235. inline void
  236. write (T &out, signed char v)
  237. {
  238. writeSignedChars<S> (out, &v, 1);
  239. }
  240. template <class S, class T>
  241. inline void
  242. write (T &out, unsigned char v)
  243. {
  244. writeUnsignedChars<S> (out, &v, 1);
  245. }
  246. template <class S, class T>
  247. void
  248. write (T &out, signed short v)
  249. {
  250. signed char b[2];
  251. b[0] = (signed char) (v);
  252. b[1] = (signed char) (v >> 8);
  253. writeSignedChars<S> (out, b, 2);
  254. }
  255. template <class S, class T>
  256. void
  257. write (T &out, unsigned short v)
  258. {
  259. unsigned char b[2];
  260. b[0] = (unsigned char) (v);
  261. b[1] = (unsigned char) (v >> 8);
  262. writeUnsignedChars<S> (out, b, 2);
  263. }
  264. template <class S, class T>
  265. void
  266. write (T &out, signed int v)
  267. {
  268. signed char b[4];
  269. b[0] = (signed char) (v);
  270. b[1] = (signed char) (v >> 8);
  271. b[2] = (signed char) (v >> 16);
  272. b[3] = (signed char) (v >> 24);
  273. writeSignedChars<S> (out, b, 4);
  274. }
  275. template <class S, class T>
  276. void
  277. write (T &out, unsigned int v)
  278. {
  279. unsigned char b[4];
  280. b[0] = (unsigned char) (v);
  281. b[1] = (unsigned char) (v >> 8);
  282. b[2] = (unsigned char) (v >> 16);
  283. b[3] = (unsigned char) (v >> 24);
  284. writeUnsignedChars<S> (out, b, 4);
  285. }
  286. template <class S, class T>
  287. void
  288. write (T &out, int64_t v)
  289. {
  290. signed char b[8];
  291. b[0] = (signed char) (v);
  292. b[1] = (signed char) (v >> 8);
  293. b[2] = (signed char) (v >> 16);
  294. b[3] = (signed char) (v >> 24);
  295. b[4] = (signed char) (v >> 32);
  296. b[5] = (signed char) (v >> 40);
  297. b[6] = (signed char) (v >> 48);
  298. b[7] = (signed char) (v >> 56);
  299. writeSignedChars<S> (out, b, 8);
  300. }
  301. template <class S, class T>
  302. void
  303. write (T &out, uint64_t v)
  304. {
  305. unsigned char b[8];
  306. b[0] = (unsigned char) (v);
  307. b[1] = (unsigned char) (v >> 8);
  308. b[2] = (unsigned char) (v >> 16);
  309. b[3] = (unsigned char) (v >> 24);
  310. b[4] = (unsigned char) (v >> 32);
  311. b[5] = (unsigned char) (v >> 40);
  312. b[6] = (unsigned char) (v >> 48);
  313. b[7] = (unsigned char) (v >> 56);
  314. writeUnsignedChars<S> (out, b, 8);
  315. }
  316. template <class S, class T>
  317. void
  318. write (T &out, float v)
  319. {
  320. union {unsigned int i; float f;} u;
  321. u.f = v;
  322. unsigned char b[4];
  323. b[0] = (unsigned char) (u.i);
  324. b[1] = (unsigned char) (u.i >> 8);
  325. b[2] = (unsigned char) (u.i >> 16);
  326. b[3] = (unsigned char) (u.i >> 24);
  327. writeUnsignedChars<S> (out, b, 4);
  328. }
  329. template <class S, class T>
  330. void
  331. write (T &out, double v)
  332. {
  333. union {uint64_t i; double d;} u;
  334. u.d = v;
  335. unsigned char b[8];
  336. b[0] = (unsigned char) (u.i);
  337. b[1] = (unsigned char) (u.i >> 8);
  338. b[2] = (unsigned char) (u.i >> 16);
  339. b[3] = (unsigned char) (u.i >> 24);
  340. b[4] = (unsigned char) (u.i >> 32);
  341. b[5] = (unsigned char) (u.i >> 40);
  342. b[6] = (unsigned char) (u.i >> 48);
  343. b[7] = (unsigned char) (u.i >> 56);
  344. writeUnsignedChars<S> (out, b, 8);
  345. }
  346. template <class S, class T>
  347. inline void
  348. write (T &out, half v)
  349. {
  350. unsigned char b[2];
  351. b[0] = (unsigned char) (v.bits());
  352. b[1] = (unsigned char) (v.bits() >> 8);
  353. writeUnsignedChars<S> (out, b, 2);
  354. }
  355. template <class S, class T>
  356. inline void
  357. write (T &out, const char v[], int n) // fixed-size char array
  358. {
  359. S::writeChars (out, v, n);
  360. }
  361. template <class S, class T>
  362. void
  363. write (T &out, const char v[]) // zero-terminated string
  364. {
  365. while (*v)
  366. {
  367. S::writeChars (out, v, 1);
  368. ++v;
  369. }
  370. S::writeChars (out, v, 1);
  371. }
  372. template <class S, class T>
  373. void
  374. pad (T &out, int n) // add n padding bytes
  375. {
  376. for (int i = 0; i < n; i++)
  377. {
  378. const char c = 0;
  379. S::writeChars (out, &c, 1);
  380. }
  381. }
  382. template <class S, class T>
  383. inline void
  384. read (T &in, bool &v)
  385. {
  386. char c;
  387. S::readChars (in, &c, 1);
  388. v = !!c;
  389. }
  390. template <class S, class T>
  391. inline void
  392. read (T &in, char &v)
  393. {
  394. S::readChars (in, &v, 1);
  395. }
  396. template <class S, class T>
  397. inline void
  398. read (T &in, signed char &v)
  399. {
  400. readSignedChars<S> (in, &v, 1);
  401. }
  402. template <class S, class T>
  403. inline void
  404. read (T &in, unsigned char &v)
  405. {
  406. readUnsignedChars<S> (in, &v, 1);
  407. }
  408. template <class S, class T>
  409. void
  410. read (T &in, signed short &v)
  411. {
  412. signed char b[2];
  413. readSignedChars<S> (in, b, 2);
  414. v = (static_cast <unsigned char> (b[0]) & 0x00ff) |
  415. (static_cast <unsigned char> (b[1]) << 8);
  416. }
  417. template <class S, class T>
  418. void
  419. read (T &in, unsigned short &v)
  420. {
  421. unsigned char b[2];
  422. readUnsignedChars<S> (in, b, 2);
  423. v = (b[0] & 0x00ff) |
  424. (b[1] << 8);
  425. }
  426. template <class S, class T>
  427. void
  428. read (T &in, signed int &v)
  429. {
  430. signed char b[4];
  431. readSignedChars<S> (in, b, 4);
  432. v = (static_cast <unsigned char> (b[0]) & 0x000000ff) |
  433. ((static_cast <unsigned char> (b[1]) << 8) & 0x0000ff00) |
  434. ((static_cast <unsigned char> (b[2]) << 16) & 0x00ff0000) |
  435. (static_cast <unsigned char> (b[3]) << 24);
  436. }
  437. template <class S, class T>
  438. void
  439. read (T &in, unsigned int &v)
  440. {
  441. unsigned char b[4];
  442. readUnsignedChars<S> (in, b, 4);
  443. v = (b[0] & 0x000000ff) |
  444. ((b[1] << 8) & 0x0000ff00) |
  445. ((b[2] << 16) & 0x00ff0000) |
  446. (b[3] << 24);
  447. }
  448. template <class S, class T>
  449. void
  450. read (T &in, int64_t &v)
  451. {
  452. signed char b[8];
  453. readSignedChars<S> (in, b, 8);
  454. v = (static_cast <int64_t> (b[0]) & 0x00000000000000ff) |
  455. ((static_cast <int64_t> (b[1]) << 8) & 0x000000000000ff00) |
  456. ((static_cast <int64_t> (b[2]) << 16) & 0x0000000000ff0000) |
  457. ((static_cast <int64_t> (b[3]) << 24) & 0x00000000ff000000) |
  458. ((static_cast <int64_t> (b[4]) << 32) & 0x000000ff00000000) |
  459. ((static_cast <int64_t> (b[5]) << 40) & 0x0000ff0000000000) |
  460. ((static_cast <int64_t> (b[6]) << 48) & 0x00ff000000000000) |
  461. (static_cast <int64_t> (b[7]) << 56);
  462. }
  463. template <class S, class T>
  464. void
  465. read (T &in, uint64_t &v)
  466. {
  467. unsigned char b[8];
  468. readUnsignedChars<S> (in, b, 8);
  469. v = ((uint64_t) b[0] & 0x00000000000000ffLL) |
  470. (((uint64_t) b[1] << 8) & 0x000000000000ff00LL) |
  471. (((uint64_t) b[2] << 16) & 0x0000000000ff0000LL) |
  472. (((uint64_t) b[3] << 24) & 0x00000000ff000000LL) |
  473. (((uint64_t) b[4] << 32) & 0x000000ff00000000LL) |
  474. (((uint64_t) b[5] << 40) & 0x0000ff0000000000LL) |
  475. (((uint64_t) b[6] << 48) & 0x00ff000000000000LL) |
  476. ((uint64_t) b[7] << 56);
  477. }
  478. template <class S, class T>
  479. void
  480. read (T &in, float &v)
  481. {
  482. unsigned char b[4];
  483. readUnsignedChars<S> (in, b, 4);
  484. union {unsigned int i; float f;} u;
  485. u.i = (b[0] & 0x000000ff) |
  486. ((b[1] << 8) & 0x0000ff00) |
  487. ((b[2] << 16) & 0x00ff0000) |
  488. (b[3] << 24);
  489. v = u.f;
  490. }
  491. template <class S, class T>
  492. void
  493. read (T &in, double &v)
  494. {
  495. unsigned char b[8];
  496. readUnsignedChars<S> (in, b, 8);
  497. union {uint64_t i; double d;} u;
  498. u.i = ((uint64_t) b[0] & 0x00000000000000ffULL) |
  499. (((uint64_t) b[1] << 8) & 0x000000000000ff00ULL) |
  500. (((uint64_t) b[2] << 16) & 0x0000000000ff0000ULL) |
  501. (((uint64_t) b[3] << 24) & 0x00000000ff000000ULL) |
  502. (((uint64_t) b[4] << 32) & 0x000000ff00000000ULL) |
  503. (((uint64_t) b[5] << 40) & 0x0000ff0000000000ULL) |
  504. (((uint64_t) b[6] << 48) & 0x00ff000000000000ULL) |
  505. ((uint64_t) b[7] << 56);
  506. v = u.d;
  507. }
  508. template <class S, class T>
  509. inline void
  510. read (T &in, half &v)
  511. {
  512. unsigned char b[2];
  513. readUnsignedChars<S> (in, b, 2);
  514. v.setBits ((b[0] & 0x00ff) | (b[1] << 8));
  515. }
  516. template <class S, class T>
  517. inline void
  518. read (T &in, char v[], int n) // fixed-size char array
  519. {
  520. S::readChars (in, v, n);
  521. }
  522. template <class S, class T>
  523. void
  524. read (T &in, int n, char v[]) // zero-terminated string
  525. {
  526. while (n >= 0)
  527. {
  528. S::readChars (in, v, 1);
  529. if (*v == 0)
  530. break;
  531. --n;
  532. ++v;
  533. }
  534. }
  535. template <class S, class T>
  536. void
  537. skip (T &in, int n) // skip n padding bytes
  538. {
  539. char c[1024];
  540. while (n >= (int) sizeof (c))
  541. {
  542. if (!S::readChars (in, c, sizeof (c)))
  543. return;
  544. n -= sizeof (c);
  545. }
  546. if (n >= 1)
  547. S::readChars (in, c, n);
  548. }
  549. template <> inline int size <bool> () {return 1;}
  550. template <> inline int size <char> () {return 1;}
  551. template <> inline int size <signed char> () {return 1;}
  552. template <> inline int size <unsigned char> () {return 1;}
  553. template <> inline int size <signed short> () {return 2;}
  554. template <> inline int size <unsigned short> () {return 2;}
  555. template <> inline int size <signed int> () {return 4;}
  556. template <> inline int size <unsigned int> () {return 4;}
  557. template <> inline int size <signed long> () {return 8;}
  558. template <> inline int size <unsigned long> () {return 8;}
  559. template <> inline int size <unsigned long long> () {return 8;}
  560. template <> inline int size <float> () {return 4;}
  561. template <> inline int size <double> () {return 8;}
  562. template <> inline int size <half> () {return 2;}
  563. } // namespace Xdr
  564. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
  565. #if defined (OPENEXR_IMF_INTERNAL_NAMESPACE_AUTO_EXPOSE)
  566. namespace Imf{using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;}
  567. #endif
  568. #endif