views:

75

answers:

3

Hi - In GetPrivateProfileString, lpReturnedString returns the string value present in the key of a particular section of an ini file.

My question is that 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
);
+2  A: 

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.

miked
Oh, I see why it's not like a normal Windows API function. It's old-school, back in the Win16 era. That should only be used by old code, if you're writing new stuff, look for a more modern API.
miked
Any suggestions for a more modern API?
Nope, I haven't done Windows API programming for years, so I don't know what they provide now for INI stuff. Check MSDN, they probably have something,
miked
@user164054 - if you have the option, migrate the app data from the ,INI file to the registry.
Steve Townsend
+2  A: 

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 _TCHARs 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 _TCHARs 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…

Nate
+1  A: 

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?

Oleg