There are two ways that integers can get read/written<br><br>1) by calling the function<br><br>Error readInteger<T>(T& Dest)<br><br>In this case the endianness of the integer is assumed to be that which you constructed the Reader/Writer with.  This is the only way to read something where the endianness is only known at runtime <br><br>2) By calling<br><br>Error readObject<T>(const T*& Dest)<br><br>In this the underlying bytes are reinterpet_casted to a const T*.  So if endianness matters to you when using this function, it will have to be part of the type T<br><br>So it's not ideal, but you could read each field out of a struct independently using #1.  This kills any performance gain you get by eliminating copying, but I suspect this is already how the code you have in mind works.<br><br>Or You can do what you said with multiple types and a runtime dispatch<br><br>Also you mention byte size.  There is currently no mechanism for reading/writing pointer sized values with runtime specified pointer size, but this would be only a couple of lines to add.<br><br>Also, you can always inherit from the readers/writers and add new methods if the core methods are insufficient <br><div class="gmail_quote"><div dir="ltr">On Thu, Feb 23, 2017 at 2:25 AM Pavel Labath <<a href="mailto:labath@google.com">labath@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 22 February 2017 at 19:57, Zachary Turner via llvm-dev<br class="gmail_msg">
<<a href="mailto:llvm-dev@lists.llvm.org" class="gmail_msg" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br class="gmail_msg">
>> Oh, reinterpret casting... hrm. That kind of file reading/writing scheme<br class="gmail_msg">
>> usually makes me a bit uncomfortable due to portability concerns (having to<br class="gmail_msg">
>> align, byte swap, etc, structs to match the on-disk format can make those<br class="gmail_msg">
>> structures problematic to work with - if you have to byte swap anyway, you'd<br class="gmail_msg">
>> need to copy the data out of the underlying buffer anyway, right?)<br class="gmail_msg">
><br class="gmail_msg">
> For byte swapping usually this is done by using llvm's endian aware types.<br class="gmail_msg">
> If you have a struct with a bunch of llvm::support::ulittle16_t's, then it<br class="gmail_msg">
> doesn't matter what platform you're on, you can reinterpret_cast the pointer<br class="gmail_msg">
> to that struct, and when you read the values they will be correct.<br class="gmail_msg">
<br class="gmail_msg">
How would this work if the endiannes and byte size of the struct (e.g.<br class="gmail_msg">
ELF header) is only decided at runtime. For example, if I need a<br class="gmail_msg">
single piece of code to handle both x86_64 little endian and arm32 big<br class="gmail_msg">
endian versions of a struct. Am I supposed to template everything<br class="gmail_msg">
based byte size and endiannes (with some runtime dispatch at the top<br class="gmail_msg">
level)? Or is this not a use case that you have in mind here?<br class="gmail_msg">
<br class="gmail_msg">
pl<br class="gmail_msg">
</blockquote></div>