Endianness Converter

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MrPickle
    New Member
    • Jul 2008
    • 100

    #1

    Endianness Converter

    I am trying to make a function to read in a value, then convert it to little endian.

    I wrote this:
    Code:
    template<typename T>
    void Read(T& value, std::ifstream& in) {
    	std::vector<unsigned char> bytes(sizeof(T));
    	in.read(reinterpret_cast<char*>(&bytes[0]), sizeof(T));
    	value = 0;
    
    	for(int i = 0; i < sizeof(T); i++) {
    		value |= (bytes[i] << i * 8);
    	}
    }
    But this is only working for int and the compiler won't accept trying to give it a float or double.

    Should I scrap the template and just overload it?
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    You can't use the |= operator with double. It only works for integer types.

    You may have to use an explicit specialization for double.

    Comment

    • MrPickle
      New Member
      • Jul 2008
      • 100

      #3
      I just tried it with a unsigned short & short, it doesn't work correctly for them either? No matter what the value it's meant to be reading in, it output 7543 :3

      Comment

      • JosAH
        Recognized Expert MVP
        • Mar 2007
        • 11453

        #4
        Does a good old C union help? Something like this:

        Code:
        union enian {
           unsigned char b[sizeof(double)];
           unsigned short s;
           unsigned int i;
           unsigned long l;
           float f;
           double d;
        } buffer;
        Read n bytes in the buffer member, reverse n bytes and fetch one of the other members.

        kind regards,

        Jos

        Comment

        • MrPickle
          New Member
          • Jul 2008
          • 100

          #5
          I've never really used unions before.

          Comment

          • JosAH
            Recognized Expert MVP
            • Mar 2007
            • 11453

            #6
            Originally posted by MrPickle
            I've never really used unions before.
            Well, what's keeping you?

            kind regards,

            Jos

            Comment

            • MrPickle
              New Member
              • Jul 2008
              • 100

              #7
              Originally posted by JosAH
              Well, what's keeping you?

              kind regards,

              Jos
              I'm not to sure what they are exactly, a reduced class?

              Comment

              • JosAH
                Recognized Expert MVP
                • Mar 2007
                • 11453

                #8
                Originally posted by MrPickle
                I'm not to sure what they are exactly, a reduced class?
                Yep, a very reduced class, even a reduced struct. All the members of a union start at the same place. So in the example above the buffer member takes the same memory as the double d or the int i. So, e.g., when I change the first four bytes of the buffer I directly change the bytes that make up the int i etc.

                The buffer char member is just another 'view' of the int i or double d etc. which is exactly what you want although you may not realize that yet ;-)

                kind regards,

                Jos

                Comment

                • MrPickle
                  New Member
                  • Jul 2008
                  • 100

                  #9
                  So what that was doing was moving everything along, 4 bytes in memory? How does that change the order of the variables in memory?

                  Comment

                  • vmpstr
                    New Member
                    • Nov 2008
                    • 63

                    #10
                    What JosAH was saying is that you can have

                    Code:
                    union myunion
                    {
                        int i;
                        char bytes[4];
                    } hello;
                    then, you can do something like hello.i = 123;
                    That assigns the number 123 into the memory occupied by hello.i
                    However, because you have a union, this memory is also occupied by hello.bytes, which is a character array.

                    In turn, this means that you can manipulate the elements of hello.bytes array (like say, reverse their order), which will also change hello.i

                    You won't "change the order of the variables", but by reversing the bytes, you will... well, reverse the bytes.

                    Comment

                    • MrPickle
                      New Member
                      • Jul 2008
                      • 100

                      #11
                      OH, I see. So whatever happens to bytes, also happens to i?

                      Can I read directly into bytes then? eg;
                      in.read(&hello. bytes[0], sizeof(int));

                      Ahh, yes. I get it, thanks for all the help.

                      Comment

                      • vmpstr
                        New Member
                        • Nov 2008
                        • 63

                        #12
                        Originally posted by MrPickle
                        OH, I see. So whatever happens to bytes, also happens to i?
                        correct

                        Originally posted by MrPickle
                        Can I read directly into bytes then? eg;
                        in.read(&hello. bytes[0], sizeof(int));
                        sure, why not

                        Originally posted by MrPickle
                        Ahh, yes. I get it, thanks for all the help.
                        all the credit goes to JosAH :D

                        Comment

                        • MrPickle
                          New Member
                          • Jul 2008
                          • 100

                          #13
                          A couple questions, will this method work for std::string. I'm not sure it will, will I just have to read it in char by char until char == '\0'.

                          Have I done this right, because it's giving me linker errors when I try called Read<int>... or Read<unsigned short>...
                          Code:
                          template <typename T> union Endian {
                          	unsigned char bytes[sizeof(T)];
                          	T value;
                          };
                          
                          template<typename T> void Read(T& value, std::ifstream& in) {
                          	Endian<T> e;
                          	in.read((&e.bytes[0]), sizeof(T));
                          
                          	for(int i = 0; i < sizeof(T); i++) {
                          		bytes[i] = bytes[sizeof(T) - i]; //Not sure here, might cause access violation?
                          	}
                          
                          	value = e.value;
                          }

                          Comment

                          • Savage
                            Recognized Expert Top Contributor
                            • Feb 2007
                            • 1759

                            #14
                            [CODE=cpp]bytes[i] = bytes[sizeof(T) - i]; //Not sure here, might cause access violation?

                            //It might.You mean:

                            bytes[i] = bytes[sizeof(T) -1- i];
                            [/CODE]

                            That's the only error I see(it would compile with this error).
                            So which are the errors?
                            Can you post them?

                            Comment

                            • JosAH
                              Recognized Expert MVP
                              • Mar 2007
                              • 11453

                              #15
                              Originally posted by Savage
                              [CODE=cpp]bytes[i] = bytes[sizeof(T) - i]; //Not sure here, might cause access violation?

                              //It might.You mean:

                              bytes[i] = bytes[sizeof(T) -1- i];
                              [/CODE]

                              That's the only error I see(it would compile with this error).
                              So which are the errors?
                              Can you post them?
                              Better change the loop boundary condition as well because as it is now you haven't done anything except for juggling those bytes back and forth ;-)

                              kind regards,

                              Jos

                              Comment

                              Working...