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