Beispiel #1
0
StreamBuffer StreamBuffer::cut(std::size_t size){
	StreamBuffer ret;
	if(m_size <= size){
		ret.swap(*this);
	} else {
		AUTO(it, m_chunks.begin());
		std::size_t total = 0; // 这是 [m_chunks.begin(), it) 的字节数,不含零头。
		while(total < size){
			assert(it != m_chunks.end());

			const std::size_t remaining = size - total;
			const std::size_t avail = it->writePos - it->readPos;
			if(remaining < avail){
				AUTO_REF(back, pushBackPooled(ret.m_chunks));
				std::memcpy(back.data, it->data + it->readPos, remaining);
				back.writePos = remaining;
				it->readPos += remaining;
				ret.m_size += remaining;
				m_size -= remaining;
				break;
			}
			total += avail;
			++it;
		}
		ret.m_chunks.splice(ret.m_chunks.begin(), m_chunks, m_chunks.begin(), it);
		ret.m_size += total;
		m_size -= total;
	}
	return ret;
}
Beispiel #2
0
StreamBuffer StreamBuffer::cut_off(std::size_t bytes){
	StreamBuffer ret;

	const AUTO(bytes_to_copy, std::min(bytes, m_size));
	if(bytes_to_copy == 0){
		return ret;
	}

	if(m_size <= bytes_to_copy){
		ret.swap(*this);
		return ret;
	}

	std::size_t bytes_copied = 0;
	AUTO(cut_end, m_first);
	for(;;){
		const AUTO(bytes_remaining, bytes_to_copy - bytes_copied);
		const AUTO(bytes_avail, cut_end->end - cut_end->begin);
		if(bytes_remaining <= bytes_avail){
			if(bytes_remaining == bytes_avail){
				cut_end = cut_end->next;
			} else {
				const AUTO(chunk, new Chunk);
				chunk->next = cut_end;
				chunk->prev = cut_end->prev;
				chunk->begin = 0;
				chunk->end = bytes_remaining;

				std::memcpy(chunk->data, cut_end->data + cut_end->begin, bytes_remaining);
				cut_end->begin += bytes_remaining;

				if(cut_end->prev){
					cut_end->prev->next = chunk;
				} else {
					m_first = chunk;
				}
				cut_end->prev = chunk;
			}
			break;
		}
		bytes_copied += bytes_avail;
		cut_end = cut_end->next;
	}

	const AUTO(cut_first, m_first);
	const AUTO(cut_last, cut_end->prev);
	cut_last->next = NULLPTR;
	cut_end->prev = NULLPTR;

	m_first = cut_end;
	m_size -= bytes_to_copy;

	ret.m_first = cut_first;
	ret.m_last = cut_last;
	ret.m_size = bytes_to_copy;
	return ret;
}
	void swap(StreamBuffer &lhs, StreamBuffer &rhs)
	{
		lhs.swap(rhs);
	}
Beispiel #4
0
	long ClientWriter::put_request(RequestHeaders request_headers, StreamBuffer entity){
		PROFILE_ME;

		StreamBuffer data;

		data.put(get_string_from_verb(request_headers.verb));
		data.put(' ');
		data.put(request_headers.uri);
		if(!request_headers.get_params.empty()){
			data.put('?');
			data.put(url_encoded_from_optional_map(request_headers.get_params));
		}
		char temp[64];
		const unsigned ver_major = request_headers.version / 10000, ver_minor = request_headers.version % 10000;
		unsigned len = (unsigned)std::sprintf(temp, " HTTP/%u.%u\r\n", ver_major, ver_minor);
		data.put(temp, len);

		AUTO_REF(headers, request_headers.headers);
		if(entity.empty()){
			headers.erase("Content-Type");
			headers.erase("Transfer-Encoding");

			if((request_headers.verb == V_POST) || (request_headers.verb == V_PUT)){
				headers.set(sslit("Content-Length"), STR_0);
			} else {
				headers.erase("Content-Length");
			}
		} else {
			if(!headers.has("Content-Type")){
				headers.set(sslit("Content-Type"), "application/x-www-form-urlencoded; charset=utf-8");
			}

			AUTO(transfer_encoding, headers.get("Transfer-Encoding"));
			AUTO(pos, transfer_encoding.find(';'));
			if(pos != std::string::npos){
				transfer_encoding.erase(pos);
			}
			transfer_encoding = to_lower_case(trim(STD_MOVE(transfer_encoding)));

			if(transfer_encoding.empty() || (transfer_encoding == STR_IDENTITY)){
				headers.set(sslit("Content-Length"), boost::lexical_cast<std::string>(entity.size()));
			} else {
				// 只有一个 chunk。
				StreamBuffer chunk;
				len = (unsigned)std::sprintf(temp, "%llx\r\n", (unsigned long long)entity.size());
				chunk.put(temp, len);
				chunk.splice(entity);
				chunk.put("\r\n0\r\n\r\n");
				entity.swap(chunk);
			}
		}
		for(AUTO(it, headers.begin()); it != headers.end(); ++it){
			data.put(it->first.get());
			data.put(": ");
			data.put(it->second);
			data.put("\r\n");
		}
		data.put("\r\n");

		data.splice(entity);

		return on_encoded_data_avail(STD_MOVE(data));
	}