1 /*
2 Copyright 2017 Skytechnology sp. z o.o..
3
4 This file is part of LizardFS.
5
6 LizardFS is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3.
9
10 LizardFS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with LizardFS If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #pragma once
20
21 #include "common/platform.h"
22
23 #include <cassert>
24 #include <algorithm>
25 #include <cstdint>
26 #include <cstring>
27
28 #ifndef _WIN32
29 #include <sys/uio.h>
30 #else // if defined(_WIN32)
31 #include <unistd.h>
32
33 struct iovec {
34 void *iov_base;
35 size_t iov_len;
36 };
37 #endif
38
39 /*!
40 * \brief Copy contiguous memory to io-vector
41 * \param iov io-vector to be filled
42 * \param iovcnt number of entries in iov
43 * \param buf memory to be copied
44 * \param len buf's size
45 */
memcpyIoVec(const struct iovec * iov,int iovcnt,const char * buf,size_t len)46 inline void memcpyIoVec(const struct iovec *iov, int iovcnt, const char *buf, size_t len) {
47 assert(iov != nullptr);
48 assert(iovcnt >= 0);
49 int iov_index = 0;
50 while (len > 0 && iov_index < iovcnt) {
51 if (iov->iov_base && iov->iov_len > 0) {
52 size_t to_copy = std::min(iov->iov_len, len);
53 std::memcpy(iov->iov_base, buf, to_copy);
54 buf += to_copy;
55 len -= to_copy;
56 }
57 iov_index++;
58 iov++;
59 }
60 }
61
62 /*!
63 * \brief Copy io-vector to another io-vector.
64 * \param buf io-vector to be filled
65 * \param bufcnt number of entries in buf
66 * \param iov io-vector to be copied
67 * \param iovcnt number of entries in iov
68 * \return number of bytes copied
69 */
copyIoVec(const struct iovec * buf,int bufcnt,const struct iovec * iov,int iovcnt)70 inline size_t copyIoVec(const struct iovec *buf, int bufcnt, const struct iovec *iov, int iovcnt) {
71 assert(buf != nullptr);
72 assert(iov != nullptr);
73 assert(bufcnt >= 0);
74 assert(iovcnt >= 0);
75 char *iov_base = (char *)iov->iov_base;
76 char *buf_base = (char *)buf->iov_base;
77 size_t iov_len = iov->iov_len;
78 size_t buf_len = buf->iov_len;
79 int iov_index = 0;
80 int buf_index = 0;
81 size_t total = 0;
82 while (buf_index < bufcnt && iov_index < iovcnt) {
83 size_t len = std::min(iov_len, buf_len);
84 total += len;
85 std::memcpy(buf_base, iov_base, len);
86
87 iov_base += len;
88 iov_len -= len;
89 while (iov_index < iovcnt && iov_len == 0) {
90 iov_index++;
91 iov++;
92 iov_base = (char *)iov->iov_base;
93 iov_len = iov->iov_len;
94 }
95
96 buf_base += len;
97 buf_len -= len;
98 while (buf_index < bufcnt && buf_len == 0) {
99 buf_index++;
100 buf++;
101 buf_base = (char *)buf->iov_base;
102 buf_len = buf->iov_len;
103 }
104 }
105
106 return total;
107 }
108