Click here to Skip to main content
Email Password   helpLost your password?

Introduction  

This is a total re-write of the code written in 2005. Originally the data structures underlying the CIniFile object were MFC CList objects. This was extremely inefficient when dealing with huge ini files. People contacted me about a version which would work in Ansi C++\STL. After posting a version which would compile without MFC under an Ansi C++\STL compiler, it became quite obvious that there should be another revision which would get rid of the slow (MFC)CList or (STL)std::list. The new versions of CIniFile use the std::map which greatly improve the efficiency. When used in a MFC project CStrings should either be cast to (LPCTSTR) or the GetString() member of CString should be used when passing CStrings to CIniFile functions. The CIniFile class stores strings as std::wstring or std::string depending on whether you are compiling your MFC project Unicode or Multibyte. During my testing, CString when used with std::map<CString,Object*> performed horribly which is why std::wstring and std::string are used internally. Previous versions which used CString internally have been removed since the current CIniFile class works fine in MFC projects. Support for streams was recently added.

The CIniClass can be used in MFC. However when passing CString types to CIniFile functions, it is necessary to call the CString::GetSting() method or cast the CString to (LPCTSTR). The following examples will be demonstrated below:

Sample Code Provided

To help with understanding how to use the code, many versions have been provided for download. The following downloads are provided:

If you don't want entire projects, a source only version is available for download. Please see the section on "Using the source in a Windows MFC project". This explains what changes need to be made when using pre-compiled headers.

Efficiency

During testing on Ubuntu Linux 9.10 running on a Lenovo T60 w\2gb ram, CIniFile could generate an ini file holding 10000 sections with 100 keys per section and write it to disk in ~1 second. After increasing the keys per section to 1000, the file was generated in ~3 seconds. The file was 10,000,000 lines long and was roughly 140mb in size. Reading the data back from file into memory was in the same ball park. The same test was performed in an MFC project. The results were not quite as impressive taking around 3 seconds for the prior and 40 for the latter test. The sections and keys were written in the format below for both tests.

[Section0]
Key0=KeyValue
Key1=KeyValue
Key2=KeyValue
...
[Section1]
Key0=KeyValue
Key1=KeyValue
Key2=KeyValue
...

Preprocessor Definitions

The following values apply the Ansi C++\STL CIniFile library

Note: The CIniFile class currently supports (STL) std::wstring or std::string.

The typedef of CIniFile changes depending whether or not _UNICODE is defined. If _UNICODE is defined in your project, the CIniFile typedef is a CIniFileW if _UNICODE is not defined, then CIniFile typedef is a CIniFileA object. CIniFileW uses std::wstring for the support of wide characters. See the following preprocessor directives:

// Additional defines
#ifdef _UNICODE
	#define INI_TOKEN_A INI_TOKEN_UNICODE
	#define INI_TOKEN_B INI_TOKEN_UNICODE
	#define INI_EMPTY INI_EMPTY_UNICODE
    typedef CIniFileW CIniFile;
    typedef CIniSectionW CIniSection;
    typedef CIniKeyW CIniKey;
    typedef PCINIW PCINI;
    typedef PCINIKEYW PCINIKEY;
    typedef PCINISECW PCINISEC;
    typedef KeyMapW KeyMap;
    typedef SecMapW SecMap;
#else
	#define INI_TOKEN_A INI_TOKEN_ANSI
	#define INI_TOKEN_B INI_TOKEN_ANSI
	#define INI_EMPTY INI_EMPTY_ANSI
    typedef CIniFileA CIniFile;
    typedef CIniSectionA CIniSection;
    typedef CIniKeyA CIniKey;
    typedef PCINIA PCINI;
    typedef PCINIKEYA PCINIKEY;
    typedef PCINISECA PCINISEC;
    typedef KeyMapA KeyMap;
    typedef SecMapA SecMap;
#endif

The CIniFile library under Visual Studio expects that _WIN32 is defined at compile time. Since windows doesn't support strcasecmp or wcscasecmp defining _WIN32 switches the functions to the respective windows versions. These functions are used by std::map to provide for a case insensitive key value. See the following preprocessor directives:

struct ci_less_a
{
  bool operator() (const std::string & s1, const std::string & s2) const
  {
      #ifndef _WIN32
            return strcasecmp(s1.c_str(), s2.c_str()) < 0;
      #else
            return _stricmp(s1.c_str(), s2.c_str()) < 0;
      #endif
  }
};

struct ci_less_w
{
  bool operator() (const std::wstring & s1, const std::wstring & s2) const
  {
      #ifndef _WIN32
            return wcscasecmp(s1.c_str(), s2.c_str()) < 0;
      #else
            return _wcsicmp(s1.c_str(), s2.c_str()) < 0;
      #endif
  }
};

Defines of interest:

Parsing and Behavior

Currently the CIniFile is designed to read most ini files. Ini Sections should start with "[" and end with a "]". Whitespace between "[" and "]" will be trimmed. For example, the section defined below would be interpreted as "SECTION" not "          SECTION            ".

[          SECTION            ]
...
...
...

Ini Key\Value pairs should have a key value separated by an "=" to the right of the key value. Key values are also trimmed to remove whitespace. For example the key defined below would be interpreted as "MyKeyValue=SomeData". The resulting key would be "MyKeyValue" and value would be "SomeData".

[          SECTION            ]
         MyKeyValue        =SomeData
...
...

Ini key values however are not trimmed and whitespace is preserved. For example the key defined below would be interpreted as "MyIniKey=        SomeDataWithSpaces        ". The resulting key would be "MyKeyValue" and value would be "        SomeDataWithSpaces        ".

[          SECTION            ]
         MyKeyValue        =        SomeDataWithSpaces        
...
...

Functions and Returns

The following examples will show std::string for function arguments. Using CIniFileA or CIniFileW will result in the usage of std::string or std::wstring respectively. The typedef of CIniFile is based on the preprocessor directive _UNICODE. The constructors and destructors of the CIniSection and CIniKey object are private. The CIniFile class is responsible for creating CIniSection objects. The CIniSection object is responsible for creating CIniKey objects. This encapsulation prevents someone from deleting internally managed pointers. Each child class has a pointer to the parent object. CIniKey has a pointer to its parent CIniSection. CIniSection has a pointer back to the CIniObject it is associated with.

// Methods of CIniFile

// Used to save the data back to the file or your choice. Returns true if saved
bool CIniFile::Save( const std::string& fileName );

// Used to save the ini data to an output stream
bool CIniFile::Save( std::ostream& output );

// Loads the data in the ini file into the IniFile object, 
// Returns true if loaded, false if failed to open file
// If bMerge is passed true, ini data will be merged into the existing ini object. 
// Merger overwrite similar section key values
bool CIniFile::Load( const std::string& fileName , bool bMerge = false );

// Loads data from an input stream which contains ini data. 
// If bMerge is passed true, ini data will be merged into the
// existing ini object. Merger overwrite similar section key values
void Load( std::istream& input , bool bMerge = false );

// Returns a const ref  to the internal section map 
// ( can be used to get number of sections or enumerate them )
// See section on "Using CIniFile::GetSections and CIniSection::GetKeys"
const SecMap& GetSections() const;

// Methods of CIniSection

// Adds a key to the CIniSection object, 
// returns a CIniKey pointer to the new or existing object
CIniKey* AddKey( std::string sKeyName );

// Removes a single key by pointer
void RemoveKey( CIniKey* pKey );

// Removes a single key by string
void RemoveKey( std::string sKey );

// Removes all the keys in the section
void RemoveAllKeys( );

// Returns a CIniKey pointer to the key by name, NULL if it was not found
CIniKey* GetKey( std::string sKeyName ) const;

// Returns a const ref to the internal key map 
// ( can be used to get number of keys or enumerate them  )
// See section on "Using CIniFile::GetSections and CIniSection::GetKeys"
const KeyMap& GetKeys() const;

// Returns a KeyValue at a certain section
std::string GetKeyValue( std::string sKey ) const;

// Sets a KeyValuePair at a certain section
void SetKeyValue( std::string sKey, std::string sValue );

// Sets the section name, returns true on success, fails if the section
// name sSectionName already exists
bool SetSectionName( std::string sSectionName );

// Returns the section name [sectionname]
std::string GetSectionName() const;

// Methods of CIniKey

// Sets the string "value" of key=value
void SetValue( std::string sValue );

// Returns the string "value" of the key=value
std::string GetValue() const;

// Sets the key name, returns true on success, 
// fails if the key name sKeyName already exists in the parent section
bool SetKeyName( std::string sKeyName );

// Returns the string "key" of key=value
std::string GetKeyName() const;

// Operator overloads for ostream
std::ostream& operator<<(std::ostream& output, CIniFile& obj);

// Operator overloads for istream
std::istream& operator>>(std::istream& input, CIniFile& obj);

// Used to manipulate CIniFile input behavior. Allows >> to merge rather than overwrite.
std::istream& operator>>(std::istream& input, CIniMerge merger)

Using CIniFile::GetSections and CIniSection::GetKeys

The following code will demonstrate how to use the GetSection and GetKeys functions.

    // The code will print the [SECTIONS] and Key=Value for the ini file

    CIniFile ini;

    ini.Load("/tmp/inifile.ini");

    // ini.GetSections().size() will return the number of ini sections in the file.

    // Print all sections and keys...
    for( SecMap::const_iterator itr = ini.GetSections().begin() ; 
	itr != ini.GetSections().end() ; itr++ )
    {
      // Note itr->first is the name of the section 
      // you can also call itr->second->GetSectionName() to get the name;
      // itr->second->GetKeys().size() will return the number of keys 
      // associated with this section
      std::cout << "[" << itr->first << "]" << std::endl;
      for( KeyMap::const_iterator kitr = itr->second->GetKeys().begin() ; 
		kitr != itr->second->GetKeys().end() ; kitr++ )
      {
          // Note kitr->first is the name of the key 
          // you can also call kitr->second->GetName() it will return the same.
          std::cout << kitr->first << "=" << kitr->second->GetValue() << std::endl;
      }
    }

Using CIniMerge Manipulator and C++ Streams

The following code will demonstrate how to use the CIniMerge with the >> operator.

    stringstream ss1;

    ss1 << "[SOMESECTION]" << CIniFile::LF;
    ss1 << "key1=value" << CIniFile::LF;
    ss1 << "key2=value" << CIniFile::LF;
    ss1 << "key3=value" << CIniFile::LF;

    stringstream ss2;

    ss2 << "[SOMESECTION2]" << CIniFile::LF;
    ss2 << "key1=value" << CIniFile::LF;
    ss2 << "key2=value" << CIniFile::LF;
    ss2 << "key3=value" << CIniFile::LF;

    CIniFile ini;

    // Load ini using Load and stream
    ini.Load( ss1 );

    // Append to ini using Load and stream
    // The resulting ini will be both sections
    ini.Load( ss2 , true );

    // Load ini using >>
    // Note: The full contents of the existing ini file object 
    // are dumped and the ss1 data is imported.
    ss1 >> ini;

    // Append to ini using >>
    // The resulting ini will be both sections
    ss2 >> CIniMerge(ini);

    // Saving ini to stream using Save()
    // The following will print the entire ini to standard out.
    ini.Save( std::cout );

    // Saving ini to stream using <<
    // The following will print the entire ini to standard out.
    std::cout << ini

Linux - Sample of Usage

#include "inifile.h"
#include <iostream>

int main()
{
    // Note if _UNICODE would be defined CIniFile would require wide strings.
    // It is 100% valid to also use either CIniFileW or CIniFileA explicitly
    CIniFile ini;

    // Loading an existing INI file
    ini.Load("/tmp/test.ini");

    // Adding Sections
    ini.AddSection("Test1");

    // Adding sections and keys
    ini.AddSection("Test2")->AddKey("Test2Key");

    // Adding sections, keys, and values
    ini.AddSection("Test3")->AddKey("Test3Key")->SetValue("Test3KeyValue");

    // Getting an existing section of the ini
    CIniSection* pSection = ini.GetSection("Test3");

    if( pSection )
    {
            // Do stuff with that section
            pSection->SetSectionName("Test3NewSectionName");

            // Getting an existing key of the ini section
            CIniKey* pKey = pSection->GetKey("Test3Key");
            if( pKey )
            {
                    pKey->SetKeyName("Test3KeyNewName");
            }
    }

    // Getting key value using the ini function v.s getting the objects
    std::cout << "KeyValue: " << ini.GetKeyValue
	( "Test3NeWSECtionName" , "Test3KeyNewName" ) << std::endl;

    ini.Save("/tmp/testout.ini");

    return 0;
}

Windows (NON-MFC VS6 or VS 2005.NET) - Sample of Usage

#include "inifile.h"
#include "tchar.h"
#include <iostream>

int _tmain()
{
    // Note if _UNICODE would be defined CIniFile would require 
    // wide strings (Note the _T(x) macro).
    // It is 100% valid to also use either CIniFileW or CIniFileA explicitly
    CIniFile ini;

    ini.Load(_T("C:\\temp\\testout.ini"));

    // Adding Sections
    ini.AddSection(_T("Test1"));

    // Adding sections and keys
    ini.AddSection(_T("Test2"))->AddKey(_T("Test2Key"));

    // Adding sections, keys, and values
    ini.AddSection(_T("Test3"))->AddKey(_T("Test3Key"))->SetValue(_T("Test3KeyValue"));

    // Getting an existing section of the ini
    CIniSection* pSection = ini.GetSection(_T("Test3"));

    if( pSection )
    {
            // Do stuff with that section
            pSection->SetSectionName(_T("Test3NewSectionName"));

            // Getting an existing key of the ini section
            CIniKey* pKey = pSection->GetKey(_T("Test3Key"));
            if( pKey )
            {
                    pKey->SetKeyName(_T("Test3KeyNewName"));
            }
    }

    // Getting key value using the ini function v.s getting the objects
    std::cout << _T("KeyValue: ") << ini.GetKeyValue
	( _T("Test3NeWSECtionName") , _T("Test3KeyNewName") ) << std::endl;

    ini.Save(_T("C:\\temp\\testout.ini"));

    return 0;
}

Windows (MFC) Visual Studio .NET 2005 - Sample of Usage

#include "stdafx.h"
#include "inifile_mfc_vs.h"
#include "inifile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only application object

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
		nRetCode = 1;
	}
	else
	{
	// Using CString
	CString fileToSave = _T("C:\\temp\\testout.ini");

	// Note if _UNICODE would be defined CIniFile would require 
         // wide strings (Note the _T(x) macro).
    	// It is 100% valid to also use either CIniFileW or CIniFileA explicitly
	// Works Unicode or Multibyte
	CIniFile ini;

	// Load an existing INI
	ini.Load(_T("C:\\temp\\testout.ini"));

	// Adding Sections
	ini.AddSection(_T("Test1"));

	// Adding sections and keys
	ini.AddSection(_T("Test2"))->AddKey(_T("Test2Key"));

	// Adding sections, keys, and values
	ini.AddSection(_T("Test3"))->AddKey(_T("Test3Key"))->
				SetValue(_T("Test3KeyValue"));

	// Getting an existing section of the ini
	CIniSection* pSection = ini.GetSection(_T("Test3"));

    	if( pSection )
	    {
	            // Do stuff with that section
	            pSection->SetSectionName(_T("Test3NewSectionName"));

	            // Getting an existing key of the ini section
	            CIniKey* pKey = pSection->GetKey(_T("Test3Key"));
	            if( pKey )
	            {
	                    pKey->SetKeyName(_T("Test3KeyNewName"));
	            }
	    }

	// Getting key value using the ini function v.s getting the objects
	_tprintf(_T("KeyValue: %s\n"), 
		ini.GetKeyValue( _T("Test3NeWSECtionName") , _T("Test3KeyNewName") ) );

	// Note you must call GetString() to make the conversion
	ini.Save(fileToSave.GetString());

	}

	return nRetCode;
}

Windows (MFC) Visual Studio 6.0 - Sample of Usage

#include "stdafx.h"
#include "inifile_mb_wide_mfc_vc6.h"
#include "inifile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		nRetCode = 1;
	}
	else
	{
	// Using CString
	CString fileToSave = "C:\\temp\\testout.ini";

	CIniFile ini;

	// Adding Sections
	ini.AddSection("Test1");

       	// Adding sections and keys
        ini.AddSection("Test2")->AddKey("Test2Key");

    	// Adding sections, keys, and values
	ini.AddSection("Test3")->AddKey("Test3Key")->SetValue("Test3KeyValue");

	// Getting an existing section of the ini
	CIniSection* pSection = ini.GetSection("Test3");

	if( pSection )
	{
        	// Do stuff with that section
        	pSection->SetSectionName("Test3NewSectionName");

        	// Getting an existing key of the ini section
        	CIniKey* pKey = pSection->GetKey("Test3Key");
        	if( pKey )
        	{
         		pKey->SetKeyName("Test3KeyNewName");
            	}
    	}

	// Getting key value using the ini function v.s getting the objects
	std::cout << "KeyValue: " << ini.GetKeyValue
		( "Test3NeWSECtionName" , "Test3KeyNewName" ) << std::endl;

	// Note to use CString in VC6 you must cast to LPCTSTR 
         // since GetString() is not available
	ini.Save((LPCTSTR)fileToSave);
	}

	return nRetCode;
}

Using the Source in a Windows MFC Project

To use the Ansi C++\STL version of the code in an MFC project using pre compiled headers. The precompiled header file must be added as the first line in the cinifile.cpp. See the example below:

--------------- cinifile.cpp ---------------
#include "stdafx.h"
#include "inifile.h"
...
--------------- end of file ----------------

The #include entries in the cinifile.h file need to be moved to the precompiled header file.

#include <map>       <-- Move to stdafx.h
#include <string>    <-- Move to stdafx.h
#include <string.h>  <-- Move to stdafx.h
#include <wchar.h>   <-- Move to stdafx.h

Future Enhancements

Add a case sensitive version of the class by utilizing templates.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalreturn std::string template variable, there may be have some error!
poptang
21:43 31 Jan '10  
I have downloaded the VS2005 project, and found this question. I think it must be std::string& return, that's OK?
Generalnot suppert UTF-8 ini file?
dnybz
16:39 31 Dec '09  
not suppert UTF-8 ini file? Smile
GeneralMultiple, identical keys
prcarp
4:55 19 Oct '09  
First, great class. I used the previous version before and it helped a lot.

In your previous version (before the re-write), you supported multiple, identical key names such as:
[Modules]
filename=module1.sys
filename=abc.def
filename=qwerty.abc
filename=yada_yada_yada.txt

The previous CRecord class supported an iterator that would move through the list.

In the re-write, I see you went to a std::map approach which although greatly aids the key lookup, does not support multiple identical keys.

What are your thoughts on this:
1. In the CIniSection::AddKey, always add a new key, regardless if it exists or not (don't do a find and return ->second).
2. In the CIniSection::RemoveKey (both), put the find() in a while loop and remove all the keys in the map with the given name.
3. Add new methods so that the host application can get an iterator to move through the iterator and get each key/value pair.

I am going to give this a shot. There might be other issues lurking (e.g. GetKeyValue -> which one does it return?)
GeneralRe: Multiple, identical keys
prcarp
9:17 19 Oct '09  
Got something going and I found a few issues with what I said above. Email me if interested.
GeneralRe: Multiple, identical keys
Ludvik Jerabek
14:46 21 Oct '09  
prcarp,

Thanks for the message and I'm glad you like the class.

I think you may be confused with another author of a CIniFile class. My previous version didn't have a CRecord.

Yes the lookup speed was an issue, so that is exactly why I used std::map. Most ini files is based on unique key value pairs. The way the code is currently, it would probably be much harder to shoehorn that feature in than meets the eye. It would be possible to use std::multimap to accomplish maps which allow for duplicate keys but retain optimisation. Perhaps even creating the ability to have an inikey's value be one of two types ie: string and multistring where the multi string would be a std::list. Thanks for the idea and feel free to let me know your take on that idea.

Regards,

Lu
Generalbug
Chris Losinger
8:59 15 Sep '09  
in RemoveAllSections, the last line is:

m_sections.empty();

but empty just tests that the container is empty, it doesn't actually empty the container. i think you want:

m_sections.clear();

this will clear the contents.

RemoveAllKeys has the same problem.


GeneralRe: bug
Ludvik Jerabek
19:06 17 Sep '09  
Chris,

Thanks much! I will get this pumped out in a fix.

Regards,

Lu
Generalnew feature? load from memory, save to memory
Gergely Mancz
0:10 30 Jul '09  
It's a great article!
But, it could be a good feature if it could load from memory and save to memory.

BR,
gmancz
GeneralRe: new feature? load from memory, save to memory
Ludvik Jerabek
17:41 30 Jul '09  
Gergely,

Thanks for your input.
Could you give a basic idea of how that feature would work (conceptually)?

Currently the Load() call (which is optional) the data is loaded into memory from a file. In the event you just want to have an ini structure in memory you can simply create an ini object like follows:

// Global ini file pointer
CIniFile* g_pini; // This could be global or a pointer or array of pointers to ini(s), or just a global object

int main()
{
// Create the object
g_pini = new CIniFile();

// Adding Sections
g_pini->AddSection("Test1");

// Adding sections and keys
g_pini->AddSection("Test2")->AddKey("Test2Key");

// Adding sections, keys, and values
g_pini->AddSection("Test3")->AddKey("Test3Key")->SetValue("Test3KeyValue");

// The data loaded above can be used in memory alone

// If you want to save it to a file you can but it's optional
g_pini->Save("C:\\SomeFileOptional.txt");

// Free the memory
delete g_pini; // Free memory and iniobject

}

I hope this makes sense. The ini file object can be used to read ini's and write them or just to have a memory based ini object.

Regards,

Lu
GeneralRe: new feature? load from memory, save to memory
Gergely Mancz
20:03 30 Jul '09  
Hi Lu!

I mean, if you want to encrypt your ini file, you can't do it in one way, or (the ugly solution) you have to load and encrypt it and save back the encrypted ini file and after delete the unencrypted ini file when the encryption ends. Or if you use your own resource file which contains an ini file, you can't load it.
If you support to load/save ini file from memory you can encrypt/decrypt your ini before save it or load it from the disk, and you can use your own resource manager.
The solution: you can make an other function: void Load(char* data, size_t size);
Or you can change the original Load/Save function (or keep it). You using fstream to load/save ini file. You should use iostream instead. The Load and Save function accepts an iostream object. You use the iostream as you used the fstream, because the fstream is the child of the iostream class.
This is an elegant solution to use streams, but not the fastest. The standard C fread(), fwrite() much faster than fstream and using char* is also faster than iostream. If you want to increase the performance, you have to leave the streams.

BR,
gmancz
GeneralRe: new feature? load from memory, save to memory
Ludvik Jerabek
15:48 31 Jul '09  
Gergely,

Thanks for that detail. I will look into allowing for that function in a future release. Thanks for your input.

Regards,

Lu
General#ifdef for MSC_VER typo in VS2005 version
vvbignigvv
19:48 25 Jul '09  
In a couple places you have a typo for the #define _MSC_VER.

you have omitted the first underscore on the line 766 and line 675.


thanks
GeneralRe: #ifdef for MSC_VER typo in VS2005 version [modified]
Ludvik Jerabek
7:51 26 Jul '09  
Great catch! Thanks I will update the source and have them repost this. Amazing how you can miss something like that.

I have submitted the update hopefully they will get it updated soon. Thanks again!

Lu

modified on Sunday, July 26, 2009 1:42 PM

Generaladdition
grandmasta1
23:46 5 Jul '09  
i have in my Ini-Parser a request for Line per Section

[Section0]
Filename1.exe
Filename2.txt
Filename2.csv


enum Key without Value - e.g. "GetLine(LineNumber, Section);"
GeneralRe: addition
Ludvik Jerabek
3:22 6 Jul '09  
Yes this is interesting idea.

Since the internal class uses maps and maps rearrange the data it would be hard to go by line number. For this I am thinking the internals of the class would need to be modified a bit. My original class written which used list would have been perfect for this however was terribly inefficient for finding key value pairs in large ini files. I will give it some thought. The current class could can handle a key without a value if modified slightly. However it would require using the Section::GetKeys call to make it work. Is array\index access needed or could enumerating the keys work?
GeneralRe: addition
Rozis
12:42 27 Sep '09  
To attach to Grandmasta1, in my implementation I also support this. With the addition to arrays, like this:

[section]
test.exe,readonly,system
getridof,readonly,folder

My implementation is that you can alternatively read a section as a iteration of lines, optionally these lines can also be parsed to an array.

You could augment this to a more general approach of keys that can be arrays:

token=name,adress,place

But I myself never came that far...

To be honest: i don't know your work enough to find out if I could construct a function that mimics the behaviour of 'keyless' sections (nor the array-option). But my experience is that they are handy sometimes.

Rozis
GeneralThank you
Ludvik Jerabek
19:54 3 Jul '09  
I just wanted to thank all the people who have contacted me with issues and advice. I hope everyone enjoys the added documentation and additional downloads.

Regards,

Ludvik
GeneralVC6 MFC : 'string' is not a member of 'std'
kitcad
23:23 29 Jun '09  
Hi.. Downloaded your Download MFC Version (Source) source code.
But, compiled got above title error.
Googling on web; ppl said added #include <string>

But, still no help and even more errors.

Any help?
GeneralVC6 MFC : 'string' is not a member of 'std'
Ludvik Jerabek
8:37 30 Jun '09  
.
GeneralRe: VC6 MFC : 'string' is not a member of 'std' [modified]
Ludvik Jerabek
8:39 30 Jun '09  
Also are you using precomiled headers? ie. stdafx.h ?

I remember years ago where older versions may expect #include <string.h> instead of #include <string> you may even want to try something weird like #include "string.h".

modified on Tuesday, June 30, 2009 8:52 PM

GeneralRe: VC6 MFC : 'string' is not a member of 'std'
kitcad
15:57 30 Jun '09  
yes.. basically, i created new mfc dialog project under VC6(due to project requirement).
include your inifile.cpp and inifile.h into project.

Then on my dialog cpp e.g. TestingIniDlg.cpp, i included

//TestingINIDlg.cpp : implementation file

#include "stdafx.h" //by default it will include for new project
#include "string.h" //this is what i added. even did try with #include <string>

#include "inifile.h"//this is yours .h file

#include "TestingINI.h" //by default for project .h file
#include "TestingINIDlg.h" //by default for project .h file
.....
......
//The rest of the code is newly created generated by VC6


Did try even added .h file put below project .h, the problem still there..Confused
still googling for solution..Confused
GeneralRe: VC6 MFC : 'string' is not a member of 'std'
Ludvik Jerabek
17:07 30 Jun '09  
Add the #include to stdafx.h and see what happens. In your project you can usually right click on the #include and open source which should find the source file. You may also want to search the VC install directory for those libraries to see if they on your system.
GeneralRe: VC6 MFC : 'string' is not a member of 'std'
kitcad
0:53 1 Jul '09  
tried...still got problem.....:(
GeneralRe: VC6 MFC : 'string' is not a member of 'std'
Ludvik Jerabek
4:37 1 Jul '09  
I am trying to find a copy of VS6 I can use to test this. I will let you now how it goes.
GeneralRe: VC6 MFC : 'string' is not a member of 'std' [modified]
Ludvik Jerabek
17:24 1 Jul '09  
I have tested and there are numerous errors which stem from MSVC++ 6 being non ISO C++98 compliant. See http://support.microsoft.com/kb/243451 for a list of non compliance issues with MSVC++ 6.

I have managed to get the standard C++ version to compile after adding some friend's to the classes. This resolves the touching of the privates (lol). The MFC version will have some issues since VC6(MFC) CString doesn't support GetString(). The GetBuffer() call may work instead. You will have to play with that a bit to get it figured out. If you want the MSVC++ 6 version sent to you let me know I will gladly email it.

modified on Thursday, July 2, 2009 12:33 AM


Last Updated 28 Sep 2009 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010