Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. hacking std::copy to use pointers
Forum Updated to NodeBB v4.3 + New Features

hacking std::copy to use pointers

Scheduled Pinned Locked Moved Unsolved C++ Gurus
11 Posts 4 Posters 3.3k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Kent-DorfmanK Offline
    Kent-DorfmanK Offline
    Kent-Dorfman
    wrote on last edited by
    #1

    Is there a way to hack std::copy so that it can take simple uint8_t* as range limits? The method is passed const uint8_t* and const size_t...not a container or real iterators.

    const uint8_t* ptr = ADDRESS;
    uint8_t* dest = DESTINATION;
    constexpr size_t length = 0x20U;
    std::copy(ptr, ptr+length, dest);
    

    I'm trying to avoid the code review justification of explicitly exempting the AUTOSAR violations of using ::memcpy(). They strongly discourage <cstring>

    I should rephase: Is there a way to hack std::copy so that it can use pointers without creating an iterator wrapper class for the pointers?

    Or alternately, is there an existing stl vectorish container that supports iterators and can reference the existing memory as it's internal buffer without creating a copy of the data?

    1 Reply Last reply
    0
    • jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

      I'm confused by that code snippet. The following compiles with a selection of compilers for C++11 and later.

      #include <cstdint>
      #include <algorithm>
      #if _cplusplus >= 202002L
      #include <span>
      #endif
      
      void test(uint8_t *input, size_t length, uint8_t *output)
      {
      #if _cplusplus >= 202002L
          std::span s{input, length};
          std::copy(s.begin(), s.end(), output);
      #endif
          std::copy(input, input + length, output);
      }
      

      std::span is a C++20 non-owning wrapper container for contiguous sequences, which might meet your last request.

      I don't understand how std::copy() using a separately passed length is superior to memcpy(). I do understand following arbitrary rules to avoid spending time discussing arbitrary rules.

      Was the original formulation of the question referring to C++20 ranges?

      Asking a question about code? http://eel.is/iso-c++/testcase/

      1 Reply Last reply
      2
      • Kent-DorfmanK Offline
        Kent-DorfmanK Offline
        Kent-Dorfman
        wrote on last edited by Kent-Dorfman
        #3

        No c++20...It is to conform to AUTOSAR "Guidelines for the use of the C++14 language in critical and safety related systems". It's a coding safety standard where much of it makes sense and some of it is pure OCD on the part of the members of the standards committee. LOL Point is, trying to slowly phase out C-ish code but still working on low level embedded systems so "pointers are king". Standard requires documentation and justification each time a rule is violated.

        A custom allocator for std::vector may be a work-around but I had hoped something already existed for this use-case.

        Yes, this compiles but give erroneous results.

        void test(const uint8_t *input, const size_t length, uint8_t *output) {
            std::copy(input, input + length, output);
        }
        

        and this is the other real use-case that fails...moving into or out of the destPtr buffer

        uint32_t ip = ::htonl((127U << 24U) | 1U);
        std::copy(&ip, &ip + sizeof(ip), destPtr);
        
        JKSHJ 1 Reply Last reply
        0
        • Kent-DorfmanK Kent-Dorfman

          No c++20...It is to conform to AUTOSAR "Guidelines for the use of the C++14 language in critical and safety related systems". It's a coding safety standard where much of it makes sense and some of it is pure OCD on the part of the members of the standards committee. LOL Point is, trying to slowly phase out C-ish code but still working on low level embedded systems so "pointers are king". Standard requires documentation and justification each time a rule is violated.

          A custom allocator for std::vector may be a work-around but I had hoped something already existed for this use-case.

          Yes, this compiles but give erroneous results.

          void test(const uint8_t *input, const size_t length, uint8_t *output) {
              std::copy(input, input + length, output);
          }
          

          and this is the other real use-case that fails...moving into or out of the destPtr buffer

          uint32_t ip = ::htonl((127U << 24U) | 1U);
          std::copy(&ip, &ip + sizeof(ip), destPtr);
          
          JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by JKSH
          #4

          @Kent-Dorfman said in hacking std::copy to use pointers:

          Is there a way to hack std::copy so that it can take simple uint8_t* as range limits

          You don't need to hack it; the code you posted in your original post should already work (assuming that ADDRESS, DESTINATION, and length are correct).

          Yes, this compiles but give erroneous results.

          void test(const uint8_t *input, const size_t length, uint8_t *output) {
              std::copy(input, input + length, output);
          }
          

          Erroneous how?

          and this is the other real use-case that fails...moving into or out of the destPtr buffer

          uint32_t ip = ::htonl((127U << 24U) | 1U);
          std::copy(&ip, &ip + sizeof(ip), destPtr);
          

          This code will try to copy 16 bytes, not 4 bytes. You want std::copy(&ip, &ip + 1, destPtr);

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          Kent-DorfmanK 1 Reply Last reply
          2
          • JKSHJ JKSH

            @Kent-Dorfman said in hacking std::copy to use pointers:

            Is there a way to hack std::copy so that it can take simple uint8_t* as range limits

            You don't need to hack it; the code you posted in your original post should already work (assuming that ADDRESS, DESTINATION, and length are correct).

            Yes, this compiles but give erroneous results.

            void test(const uint8_t *input, const size_t length, uint8_t *output) {
                std::copy(input, input + length, output);
            }
            

            Erroneous how?

            and this is the other real use-case that fails...moving into or out of the destPtr buffer

            uint32_t ip = ::htonl((127U << 24U) | 1U);
            std::copy(&ip, &ip + sizeof(ip), destPtr);
            

            This code will try to copy 16 bytes, not 4 bytes. You want std::copy(&ip, &ip + 1, destPtr);

            Kent-DorfmanK Offline
            Kent-DorfmanK Offline
            Kent-Dorfman
            wrote on last edited by
            #5
            This post is deleted!
            1 Reply Last reply
            0
            • Kent-DorfmanK Offline
              Kent-DorfmanK Offline
              Kent-Dorfman
              wrote on last edited by
              #6

              std::copy(&ip, &ip + sizeof(ip), destPtr); was definitely a goof on my part.

              1 Reply Last reply
              0
              • Kent-DorfmanK Offline
                Kent-DorfmanK Offline
                Kent-Dorfman
                wrote on last edited by
                #7

                another fly in the ointment that makes std::copy unsuitable for moving memory buffers around:

                Given the above example of copying the bytes of a uint32_t to an arbitrary memory location, the destPtr (being of type uint8_t*) wont allow std::copy to copy the whole range from the input iteratores. It only copies one byte! Some would argue that destPtr should then be of type uint32_t* but that could cause other problems since there is no guarantee that the destination address would be word aligned...IOW, I don't necessarily want it to be aligned, but instead packed.

                going back to using using <cstring> methods that aren't so picky about how you address memory.

                JKSHJ 1 Reply Last reply
                0
                • Kent-DorfmanK Kent-Dorfman

                  another fly in the ointment that makes std::copy unsuitable for moving memory buffers around:

                  Given the above example of copying the bytes of a uint32_t to an arbitrary memory location, the destPtr (being of type uint8_t*) wont allow std::copy to copy the whole range from the input iteratores. It only copies one byte! Some would argue that destPtr should then be of type uint32_t* but that could cause other problems since there is no guarantee that the destination address would be word aligned...IOW, I don't necessarily want it to be aligned, but instead packed.

                  going back to using using <cstring> methods that aren't so picky about how you address memory.

                  JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on last edited by
                  #8

                  @Kent-Dorfman You can cast your input pointers to <uint8_t*> (and change your pointer arithmetic for the end iterator) before passing them to std::copy.

                  going back to using using <cstring> methods

                  I thought that was strongly discouraged?

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  1 Reply Last reply
                  0
                  • Kent-DorfmanK Offline
                    Kent-DorfmanK Offline
                    Kent-Dorfman
                    wrote on last edited by
                    #9

                    I understand why, but std::copy is just too particular about operand types for generic RAM (network buffer) manipulation. Going back to <cstring> methods that use void*...yeah, it violates the consortium rules but this is embedded programming, not high level algorithmic stuff..and rank has its privilege. I'm the one driving the conformance level so nobody is gonna complain if I make their life easier. and in the end, violations just have to be documented, if I leave the rule turned on. at this point I'm inclined to disable that particular rule as being overly strict for nodes with no safety critical functions.

                    1 Reply Last reply
                    0
                    • jeremy_kJ Offline
                      jeremy_kJ Offline
                      jeremy_k
                      wrote on last edited by
                      #10

                      memmove() or memcpy() sound like the right abstraction for a block of memory. std::copy() deals a range of items that may be noncontiguous or have copy constructors. Using it on a buffer presumably means breaking that abstraction to get char sized chunks, while having limited potential to utilize the iterator abstraction. I guess it could make sense with a scatter/gather interface.

                      Asking a question about code? http://eel.is/iso-c++/testcase/

                      1 Reply Last reply
                      1
                      • fcarneyF Offline
                        fcarneyF Offline
                        fcarney
                        wrote on last edited by
                        #11

                        I just don't get where it fails from this discussion:

                        #include <cstdint>
                        #include <algorithm>
                        #include <cassert>
                        
                        int main(int argc, char *argv[])
                        {
                            constexpr size_t length = 0x20U;
                            uint8_t* ptr = new uint8_t[length];
                            for(size_t count=0; count<length; ++count)
                                ptr[count] = count;
                            uint8_t* dest = new uint8_t[length];
                            std::copy(ptr, ptr+length, dest);
                            for(size_t count=0; count<length; ++count){
                                assert(ptr[count] == dest[count]);
                            }
                            delete[] ptr;
                            delete[] dest;
                        
                            return 0;
                        }
                        

                        I tested in both c++11 and c++17.

                        C++ is a perfectly valid school of magic.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved