void writeBitsImpl(DataType value, int bitCount, StreamBuffer& streamBuffer, int& holdingBitCount, int& totalBitCount) { assert(isEnoughBits<DataType>(bitCount)); if (! isEnoughBits<DataType>(bitCount)) { throw StreamingException(__FILE__, __LINE__, "invalid bitCount"); } DataType theValue = resetUnusedBits(value, bitCount); if (holdingBitCount > 0) { if (streamBuffer.empty()) { throw StreamingException(__FILE__, __LINE__, "buffer is empty"); } streamBuffer.back() |= UInt8(theValue << holdingBitCount); } else { streamBuffer.push(UInt8(theValue)); } const int bitShiftCount = CHAR_BIT - holdingBitCount; if (bitCount > bitShiftCount) { int leftBitCount = bitCount - bitShiftCount; theValue >>= bitShiftCount; do { streamBuffer.push(UInt8(theValue)); theValue >>= CHAR_BIT; leftBitCount -= CHAR_BIT; } while (leftBitCount > 0); }
bool getLine(StreamBuffer &buffer, std::string &line){ line.clear(); if(buffer.empty()){ return false; } do { const int ch = buffer.get(); if(ch == '\n'){ break; } else if(ch == '\r'){ if(buffer.peek() == '\n'){ continue; } break; } line.push_back(ch); } while(!buffer.empty()); return true; }
long ClientWriter::put_chunk(StreamBuffer entity){ PROFILE_ME; if(entity.empty()){ LOG_POSEIDON_ERROR("You are not allowed to send an empty chunk"); DEBUG_THROW(BasicException, sslit("You are not allowed to send an empty chunk")); } StreamBuffer chunk; char temp[64]; unsigned len = (unsigned)std::sprintf(temp, "%llx\r\n", (unsigned long long)entity.size()); chunk.put(temp, len); chunk.splice(entity); chunk.put("\r\n"); return on_encoded_data_avail(STD_MOVE(chunk)); }
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)); }
void CsvParser::load(const char *file){ LOG_POSEIDON_DEBUG("Loading CSV file: ", file); StreamBuffer buffer; fileGetContents(buffer, file); buffer.put('\n'); std::vector<OptionalMap> data; std::vector<std::vector<std::string> > rows; { std::vector<std::string> row; std::string token; bool first = true; bool inQuote = false; do { char ch = buffer.get(); if(ch == '\r'){ if(buffer.peek() == '\n'){ buffer.get(); } ch = '\n'; } if(first){ first = false; if(ch == '\"'){ inQuote = true; continue; } } if(ch == '\"'){ if(inQuote){ if(buffer.peek() == '\"'){ buffer.get(); token.push_back('\"'); } else { inQuote = false; } continue; } } if(!inQuote){ if((ch == ',') || (ch == '\n')){ std::string trimmed; const std::size_t begin = token.find_first_not_of(" \t\r\n"); if(begin != std::string::npos){ const std::size_t end = token.find_last_not_of(" \t\r\n") + 1; trimmed = token.substr(begin, end - begin); } row.push_back(STD_MOVE(trimmed)); token.clear(); first = true; if(ch == '\n'){ rows.push_back(STD_MOVE(row)); row.clear(); } continue; } } token.push_back(ch); } while(!buffer.empty()); } if(rows.empty() || rows.front().empty()){ LOG_POSEIDON_ERROR("The first line of a CSV file may not be empty."); DEBUG_THROW(Exception, sslit("Bad CSV header")); } const std::size_t columnCount = rows.front().size(); std::vector<SharedNts> keys(columnCount); for(std::size_t i = 0; i < columnCount; ++i){ AUTO_REF(key, rows.front().at(i)); for(std::size_t j = 0; j < i; ++j){ if(keys.at(j) == key){ LOG_POSEIDON_ERROR("Duplicate key: ", key); DEBUG_THROW(Exception, sslit("Duplicate key")); } } keys.at(i).assign(key.c_str()); } for(std::size_t i = 1; i < rows.size(); ++i){ rows.at(i - 1).swap(rows.at(i)); } rows.pop_back(); { std::size_t line = 1; std::size_t i = 0; while(i < rows.size()){ AUTO_REF(row, rows.at(i)); ++line; if((row.size() == 1) && row.front().empty()){ for(std::size_t j = i + 1; j < rows.size(); ++j){ rows.at(j - 1).swap(rows.at(j)); } rows.pop_back(); continue; } if(row.size() != columnCount){ LOG_POSEIDON_ERROR("There are ", row.size(), " column(s) on line ", line, " but there are ", columnCount, " in the header"); DEBUG_THROW(Exception, sslit("Inconsistent CSV column numbers")); } ++i; } } const std::size_t rowCount = rows.size(); data.resize(rowCount); for(std::size_t i = 0; i < rowCount; ++i){ AUTO_REF(row, rows.at(i)); AUTO_REF(map, data.at(i)); for(std::size_t j = 0; j < columnCount; ++j){ map.create(keys.at(j))->second.swap(row.at(j)); } } LOG_POSEIDON_DEBUG("Done loading CSV file: ", file); m_data.swap(data); m_row = static_cast<std::size_t>(-1); }