title: Unpacking hex-encoded floats
body: <p>I'm trying to translate the following Python code into C++:</p>
  
  <pre><code>import struct
  import binascii
  
  
  inputstring = ("0000003F" "0000803F" "AD10753F" "00000080")
  num_vals = 4
  
  for i in range(num_vals):
      rawhex = inputstring[i*8:(i*8)+8]
  
      # &lt;f for little endian float
      val = struct.unpack("&lt;f", binascii.unhexlify(rawhex))[0]
      print val
  
      # Output:
      # 0.5
      # 1.0
      # 0.957285702229
      # -0.0
  </code></pre>
  
  <p>So it reads 32-bit worth of the hex-encoded string, turns it into a byte-array with the <code>unhexlify</code> method, and interprets it as a little-endian float value.</p>
  
  <p>The following almost works, but the code is kind of crappy (and the last <code>00000080</code> parses incorrectly):</p>
  
  <pre><code>#include &lt;sstream&gt;
  #include &lt;iostream&gt;
  
  
  int main()
  {
      // The hex-encoded string, and number of values are loaded from a file.
      // The num_vals might be wrong, so some basic error checking is needed.
      std::string inputstring = "0000003F" "0000803F" "AD10753F" "00000080";
      int num_vals = 4;
  
  
      std::istringstream ss(inputstring);
  
      for(unsigned int i = 0; i &lt; num_vals; ++i)
      {
          char rawhex[8];
  
  // The ifdef is wrong. It is not the way to detect endianness (it's
  // always defined)
  #ifdef BIG_ENDIAN
          rawhex[6] = ss.get();
          rawhex[7] = ss.get();
  
          rawhex[4] = ss.get();
          rawhex[5] = ss.get();
  
          rawhex[2] = ss.get();
          rawhex[3] = ss.get();
  
          rawhex[0] = ss.get();
          rawhex[1] = ss.get();
  #else
          rawhex[0] = ss.get();
          rawhex[1] = ss.get();
  
          rawhex[2] = ss.get();
          rawhex[3] = ss.get();
  
          rawhex[4] = ss.get();
          rawhex[5] = ss.get();
  
          rawhex[6] = ss.get();
          rawhex[7] = ss.get();
  #endif
  
          if(ss.good())
          {
              std::stringstream convert;
              convert &lt;&lt; std::hex &lt;&lt; rawhex;
              int32_t val;
              convert &gt;&gt; val;
  
              std::cerr &lt;&lt; (*(float*)(&amp;val)) &lt;&lt; "\n";
          }
          else
          {
              std::ostringstream os;
              os &lt;&lt; "Not enough values in LUT data. Found " &lt;&lt; i;
              os &lt;&lt; ". Expected " &lt;&lt; num_vals;
              std::cerr &lt;&lt; os.str() &lt;&lt; std::endl;
              throw std::exception();
          }
      }
  }
  </code></pre>
  
  <p>(compiles on OS X 10.7/gcc-4.2.1, with a simple <code>g++ blah.cpp</code>)</p>
  
  <p>Particularly, I'd like to get rid of the <code>BIG_ENDIAN</code> macro stuff, as I'm sure there is a nicer way to do this, as <a href="http://commandcenter.blogspot.com.au/2012/04/byte-order-fallacy.html" rel="nofollow">this post</a> discusses.</p>
  
  <p>Few other random details - I can't use Boost (too large a dependency for the project). The string will usually contain between 1536 (8<sup>3</sup>*3) and 98304 float values (32<sup>3</sup>*3), at most 786432 (64<sup>3</sup>*3)</p>
  
  <p>(edit2: added another value, <code>00000080</code> == <code>-0.0</code>)</p>