Kopiowanie tablicy char

0

Witam.
Zmagam się od jakiegoś czasu z problemem zrobienia czegoś takiego:

[code] unsigned char* tmpChar = (unsigned char*)msg.getOutputBuffer();
std::string dane((char*)&tmpChar[2]);
packetsMap[(OTSYS_TIME()-startTime)] = dane;
[/code]

Chodzi o to żeby tmpChar zmienić do stringa, lecz nie ważne co dam otrzymuje stringa o długości 3 lub 1...

Obecnie mam funkcje
[code] char* tmpChar = (char*)msg.getOutputBuffer();
std::string dane;
for(int32_t i = 0; i < messageLength; i++)
dane += tmpChar[i];
packetsMap[(OTSYS_TIME()-startTime)] = dane;
[/code]
Ale ona chyba nie jest odpowiednio wydajna...

getOutputBuffer() wygląda tak
[code]
char* getOutputBuffer() {return (char*)&m_buffer[m_outputBufferStart];}
[/code]

Co mam zrobić aby w jak najbardziej optymalny sposób zamienić to na string?
Pozdrawiam.

1

Jeśli w buforze są bajty zerowe ('\0') i chcesz je przerzucić do string to musisz użyć innego konstruktora np.
string(const char * s, size_t n)

packetsMap[(OTSYS_TIME()-startTime)] = std::string(msg.getOutputBuffer() + 2, messageLength - 2);
0

Tak, są to dane bianarne, nulle też są.

Tak jeszcze zapytam, jak najprościej przenieślibyście te dane tmpChar wraz z tablicą na wątek? Ja używałem to tego stringa, ale może są wydajniejsze opcje.

Mapa wygląda tak
[code] std::map<int32_t, std::string> packetsMap;
[/code]

Potem dalej jest wysłanie na wątek danych
[code] Tasker::getInstance().addTask(createTask(boost::bind(&Game::recordPlayer, &g_game, playerName, startTime, packetsMap, false)));
[/code]

I zapis do pliku danych
[code]
void Game::recordPlayer(std::string playerName, uint64_t time, std::map<int32_t, std::string> packetsMap, bool end)
{
std::stringstream save(std::in | std::out | std::binary);

std::stringstream path;
path << "data/logs/records_temp/" << playerName << "-" << time <<".rec";

for(std::map<int32_t, std::string>::iterator it = packetsMap.begin(); it != packetsMap.end(); it++) {
	std::string decoded = (it->second);
	int16_t fullSize = decoded.length()+2;
	int16_t dSize = decoded.length();
	save.write((char*)&fullSize,2);
	save.write((char*)&it->first,4);
	save.write((char*)&dSize,2);
	save << decoded;
	save.write((char*)&it->first,4);
}

std::fstream zapis;
zapis.open(path.str().c_str(), std::ios::out | std::ios::binary | std::ios::app);	
if(zapis.is_open()) {
zapis << save.str();
zapis.close();		
} else 
	std::clog << "Critical error with open file: " << path.str().c_str() << std::endl;	

...
[/code]

Macie może pomysły jakby to zrobić optymalnej?

1

Tak, są to dane bianarne, nulle też
trzymanie danych binarnych w stringu to zuy pomysł. właśnie przez tego typu problemy — sam sobie go stworzyłeś.

jakby to zrobić optymalnej?
zaraz cię zjedzą.

0

W takim razie jak proponował być przechowywać te dane?

0

jako std::vector albo boost::array

1

Jeśli pracujesz na danych stricte binarnych to użyj vector. Możesz je trzymać w mapie, będzie optymalnie, ale trzeba się nią prawidłowo posługiwać.

Np. wrzucanie wektora do mapy:

packetsMap[(OTSYS_TIME()-startTime)] = std::vector<unsigned char>(poczatek, koniec);

Dzięki optymalizacji być może wektor będzie utworzony od razu w mapie. Ale żeby mieć pewność że wektor nie będzie niepotrzebnie kopiowany można to zastąpić takim kodem:

std::vector<unsigned char> &packet = packetsMap[(OTSYS_TIME()-startTime)];
packet.insert(packet.end(), poczatek, koniec);

Albo tutaj:

void Game::recordPlayer(std::string playerName, uint64_t time, std::map<int32_t, std::string> packetsMap, bool end)

Nie przekazuj całej mapy przez wartość! Wszystko będzie niepotrzebnie kopiowane! Przekaż mapę przez wskaźnik/referencję.

0
adf88 napisał(a)

Jeśli pracujesz na danych stricte binarnych to użyj vector. Możesz je trzymać w mapie, będzie optymalnie, ale trzeba się nią prawidłowo posługiwać.

Np. wrzucanie wektora do mapy:

packetsMap[(OTSYS_TIME()-startTime)] = std::vector<unsigned char>(poczatek, koniec);

Dzięki optymalizacji być może wektor będzie utworzony od razu w mapie. Ale żeby mieć pewność że wektor nie będzie niepotrzebnie kopiowany można to zastąpić takim kodem:

std::vector<unsigned char> &packet = packetsMap[(OTSYS_TIME()-startTime)];
packet.insert(packet.end(), poczatek, koniec);

Albo tutaj:

void Game::recordPlayer(std::string playerName, uint64_t time, std::map<int32_t, std::string> packetsMap, bool end)

Nie przekazuj całej mapy przez wartość! Wszystko będzie niepotrzebnie kopiowane! Przekaż mapę przez wskaźnik/referencję.

Nie mogę przekazać przez wskakźnik, ten proces recordPlayer działa na wątku i zazwyczaj ta mapa już poza nim nie istnieje po wysłaniu... Byłby seg fal.
Pomyśle i poczytam dziś o vectorze i żeby więcej z tej funkcji było w game i na wątku, za godzinę wyślę to co stworzyłem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1