GetPrivateProfileString - c++ class - return string - memory pre calculation
In GetPrivateProfileString
, lpReturnedString
returns the string value present in the key of a particular section of an ini file.
My question is tha开发者_C百科t how will i know exactly, how much memory has to be allocated, rather than just allocation a large chunk prior to calling this function.
DWORD WINAPI GetPrivateProfileString(
__in LPCTSTR lpAppName,
__in LPCTSTR lpKeyName,
__in LPCTSTR lpDefault,
__out LPTSTR lpReturnedString,
__in DWORD nSize,
__in LPCTSTR lpFileName
);
Standard case
The return value from GetPrivateProfileString
is the number of characters copied to the buffer, not including the null terminator.
Therefore, you could start with (say) a buffer of 100 _TCHAR
s and check the return value. If it’s 99, then either you exactly guessed the size of the string or (more likely) your buffer is too small, so enlarge it and try again.
“Enumerating” case
The above applies to the standard case of retrieving one string value from an .ini
file. If you are instead passing NULL
as either the lpAppName
or lpKeyName
parameters, in order to enumerate all available values, and you have provided too small of a buffer, the return value will be two less than the buffer size.
Allocation Strategy
You’re going to have to dynamically allocate the buffer. So you’ll probably use std::auto_ptr
or std::unique_ptr
, or maybe a std::vector<_TCHAR>
that you can resize()
as needed. If you don’t know in advance how big the strings will be, I’d recommend starting with something like 250 _TCHAR
s and doubling the size each time you find out the buffer is too small. In practice, I’d bet 250 is enough 99.9999% of the time.
Alternatives
XML file stored under %APPDATA%
; JSON file stored under %APPDATA%
, the Registry…
That's weird, generally Windows API functions allow you to pass in a NULL and return to you the size to make your buffer. This function doesn't seem to do that. I'd say you should just pick a reasonable size. If it's not big enough, keep doubling the buffer size until you get it.
From your question I suppose that you want allocate memory on the heap with new
, malloc
, LocalAlloc
or some other function working with heap. You want probably use as less heap memory as possible.
If you works with the memory on the stack it is not so important to be so exactly. Memory allocation is very quickly (about 100 or 1000 time quicker as on the heap) and after you return from the current function the memory will be automatically freed. So you can just define a variable
TCHAR szBuffer[16384];
16K on the stack is almost nothing. Then you can call GetPrivateProfileString
with szBuffer
as the lpReturnedString
. The function GetPrivateProfileString
returns the number of characters copied to the buffer. If the value is less then 16K-1, then you will be know the the exact buffer size. You can allocate now the memory block of the size on the heap and copy the data from szBuffer
to the block. If the returned value of GetPrivateProfileString
is equal to 16K-1, then you the buffer was too small. In the case you can implement any doubling of the buffer size (and working with buffer of the heap now), but I prefer to interpret this as an error in the ini-file. All real ini-files which I used before was small. The size of an entry is mostly less then 260 characters. So the entry size grater as 16K you can interpret as the error.
By the way you can verify the size of the INI-file with respect of GetFileSizeEx. The entry size must be less then the size of the INI-File.
Some restriction to the INI-size you have to include in your program. If the entry size will be measured in GBs, that you can do receive a problem. Why not restrict the size of permitted entry with 16K for example?
精彩评论