Advertisement

converting std::vector to std::string easily..

Started by May 31, 2001 06:24 AM
0 comments, last by gimp 23 years, 8 months ago
I have exported two functions on my file loader class: void Load(const string& a_Filename, vector& a_Data); void Load(const string& a_Filename, string& a_Data); Since the container are essentially similar I''d like to get the string to hijack the vector function so I don''t need to maintain identical code sets. What I thought to do was just load the data in to a string then tack on a null. The idea here to to do this without memcpy''ing the whole file for the conversion. So... I did this: Load(a_Filename, reinterpret_cast>(a_Data)); Bzzzt, that didn''t work. Load internally treats string and vector the same way(the code it cut\pasted unmodified). In case your curious, this is all it does:
  
	HANDLE Handle = CreateFile(	a_Filename.c_str(),	GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,	FILE_ATTRIBUTE_NORMAL, NULL);
	if (Handle == 0)
		throw FileNotFound();

	DWORD Size = GetFileSize(Handle, NULL);
	HANDLE Mapping = CreateFileMapping(Handle, NULL, PAGE_READONLY, 0, Size, NULL);
	CloseHandle(Handle);
	LPVOID BaseAddress = MapViewOfFile(Mapping, FILE_MAP_READ, 0, 0, 0);
	a_Data.resize(Size);
	memcpy(a_Data.begin(), BaseAddress, Size);
	CloseHandle(Mapping);
	UnmapViewOfFile( BaseAddress );
  
As you can see resize and begin is all I use, both templates support this. So, how so I create a string version of Load() that just uses the vector version internally. I''m sure there is some casting trick I can use... Many thanks Chris
Chris Brodie
Converting a vector to string (or the other way around) makes no sense, since both objects are very different.

If you want to copy the contents of a string to a vector (or the other way around), you could use std::copy:
string str("1234");vector v;// ...v.clear();v.reserve(str.size());copy(str.begin(), str.end(), back_inserter(v));  

The destination is cleared (just in case), and enough storage is allocated so that the vector can be filled without reallocation (which takes time). copy uses back_inserter because copy in itself doesn't insert an element, it just accesses an element in the destination to overwrite its value.

So, a version of Load(const string& filename, string&) that uses Load(const string& filename, vector& data) internally:
void Load(const string& filename, vector& data){  string tmp;  Load(filename, tmp);  data.clear();  data.reserve(tmp.size());  copy(tmp.begin(), tmp.end(), back_inserter(data));}  

This will lead to two memory copies: one to fill the tmp string, and one to fill the vector, because each object has its own copy of the data it contains.

Final note: do not use memcpy on STL containers. You cannot presume that they implement storage in a certain way. vector is the one exception though. If you knew that a vector's size is 10, you could do a memcpy to copy its elements. The reason for this is that you can use vector as a C-style array in legacy code.

So, to fill a string from a memory region, you can do the following:
string s;// get size of file, create mapping etcs.clear();s.reserve(Size);s.insert(s.begin(), (const char*)BaseAddress, Size); 

Reserve makes sure that enough memory is allocated to use push_back without reallocating. Reserve doesn't change the size of the vector: after the reserve call, the vector is still empty.

HTH

Edited by - JungleJim on May 31, 2001 11:02:42 AM

This topic is closed to new replies.

Advertisement