From 12757054905a236f37735b2d299056580770f62a Mon Sep 17 00:00:00 2001 From: Brodie Thiesfield Date: Fri, 25 Apr 2008 05:38:46 +0000 Subject: added new functions GetBoolValue, GetLongValue, SetBoolValue, SetLongValue --- SimpleIni.h | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++--- package.cmd | 2 +- test1-expected.ini | 4 + test1-input.ini | 4 + testsi.cpp | 15 ++++ 5 files changed, 248 insertions(+), 10 deletions(-) diff --git a/SimpleIni.h b/SimpleIni.h index 4e3e524..e88833b 100644 --- a/SimpleIni.h +++ b/SimpleIni.h @@ -5,7 +5,7 @@ File SimpleIni.h Author Brodie Thiesfield [code at jellycan dot com] Source http://code.jellycan.com/simpleini/ - Version 4.6 + Version 4.7 Jump to the @link CSimpleIniTempl CSimpleIni @endlink interface documentation. @@ -170,7 +170,7 @@ The licence text below is the boilerplate "MIT Licence" used from: http://www.opensource.org/licenses/mit-license.php - Copyright (c) 2006, Brodie Thiesfield + Copyright (c) 2006-2008, Brodie Thiesfield Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -193,9 +193,9 @@ #ifndef INCLUDED_SimpleIni_h #define INCLUDED_SimpleIni_h -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif // Disable these warnings in MSVC: // 4127 "conditional expression is constant" as the conversion classes trigger @@ -222,7 +222,7 @@ #endif // SI_SUPPORT_IOSTREAMS #ifdef _DEBUG -# ifndef assert +# ifndef assert # include # endif # define SI_ASSERT(x) assert(x) @@ -836,6 +836,51 @@ public: bool * a_pHasMultiple = NULL ) const; + /** Retrieve a numeric value for a specific key. If multiple keys are enabled + (see SetMultiKey) then only the first value associated with that key + will be returned, see GetAllValues for getting all values with multikey. + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_nDefault Value to return if the key is not found + @param a_pHasMultiple Optionally receive notification of if there are + multiple entries for this key. + + @return a_nDefault Key was not found in the section + @return other Value of the key + */ + long GetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nDefault = 0, + bool * a_pHasMultiple = NULL + ) const; + + /** Retrieve a boolean value for a specific key. If multiple keys are enabled + (see SetMultiKey) then only the first value associated with that key + will be returned, see GetAllValues for getting all values with multikey. + + Strings starting with "t", "y", "on" or "1" are returned as logically true. + Strings starting with "f", "n", "of" or "0" are returned as logically false. + For all other values the default is returned. Character comparisons are + case-insensitive. + + @param a_pSection Section to search + @param a_pKey Key to search for + @param a_bDefault Value to return if the key is not found + @param a_pHasMultiple Optionally receive notification of if there are + multiple entries for this key. + + @return a_nDefault Key was not found in the section + @return other Value of the key + */ + bool GetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bDefault = false, + bool * a_pHasMultiple = NULL + ) const; + /** Add or update a section or value. This will always insert when multiple keys are enabled. @@ -869,6 +914,50 @@ public: return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, true); } + /** Add or update a numeric value. This will always insert + when multiple keys are enabled. + + @param a_pSection Section to add or update + @param a_pKey Key to add or update. + @param a_nValue Value to set. + @param a_pComment Comment to be associated with the key. See the + notes on SetValue() for comments. + @param a_bUseHex By default the value will be written to the file + in decimal format. Set this to true to write it + as hexadecimal. + + @return SI_Error See error definitions + @return SI_UPDATED Value was updated + @return SI_INSERTED Value was inserted + */ + SI_Error SetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nValue, + const SI_CHAR * a_pComment = NULL, + bool a_bUseHex = false + ); + + /** Add or update a boolean value. This will always insert + when multiple keys are enabled. + + @param a_pSection Section to add or update + @param a_pKey Key to add or update. + @param a_bValue Value to set. + @param a_pComment Comment to be associated with the key. See the + notes on SetValue() for comments. + + @return SI_Error See error definitions + @return SI_UPDATED Value was updated + @return SI_INSERTED Value was inserted + */ + SI_Error SetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_nValue, + const SI_CHAR * a_pComment = NULL + ); + /** Delete an entire section, or a key from a section. Note that the data returned by GetSection is invalid and must not be used after anything has been deleted from that section using this method. @@ -1093,7 +1182,7 @@ CSimpleIniTempl::LoadFile( ) { FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE fopen_s(&fp, a_pszFile, "rb"); #else // !__STDC_WANT_SECURE_LIB__ fp = fopen(a_pszFile, "rb"); @@ -1754,6 +1843,132 @@ CSimpleIniTempl::GetValue( return iKeyVal->second; } +template +long +CSimpleIniTempl::GetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nDefault, + bool * a_pHasMultiple + ) const +{ + // return the default if we don't have a value + const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_nDefault; + + // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII + char szValue[64] = { 0 }; + SI_CONVERTER c(m_bStoreIsUtf8); + if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { + return a_nDefault; + } + + // handle the value as hex if prefaced with "0x" + long nValue = a_nDefault; + char * pszSuffix = szValue; + if (szValue[0] == '0' && (szValue[1] == 'x' || szValue[1] == 'X')) { + if (!szValue[2]) return a_nDefault; + nValue = strtol(&szValue[2], &pszSuffix, 16); + } + else { + nValue = strtol(szValue, &pszSuffix, 10); + } + + // any invalid strings will return the default value + if (*pszSuffix) { + return a_nDefault; + } + + return nValue; +} + +template +SI_Error +CSimpleIniTempl::SetLongValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + long a_nValue, + const SI_CHAR * a_pComment, + bool a_bUseHex + ) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_FAIL; + + // convert to an ASCII string + char szInput[64]; + sprintf(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue); + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(szInput, strlen(szInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, true); +} + +template +bool +CSimpleIniTempl::GetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bDefault, + bool * a_pHasMultiple + ) const +{ + // return the default if we don't have a value + const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_bDefault; + + // we only look at the minimum number of characters + switch (pszValue[0]) { + case 't': case 'T': // true + case 'y': case 'Y': // yes + case '1': // 1 (one) + return true; + + case 'f': case 'F': // false + case 'n': case 'N': // no + case '0': // 0 (zero) + return false; + + case 'o': case 'O': + if (pszValue[1] == 'n' || pszValue[1] == 'N') return true; // on + if (pszValue[1] == 'f' || pszValue[1] == 'F') return false; // off + break; + } + + // no recognized value, return the default + return a_bDefault; +} + +template +SI_Error +CSimpleIniTempl::SetBoolValue( + const SI_CHAR * a_pSection, + const SI_CHAR * a_pKey, + bool a_bValue, + const SI_CHAR * a_pComment + ) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_FAIL; + + // convert to an ASCII string + const char * pszInput = a_bValue ? "true" : "false"; + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(pszInput, strlen(pszInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, true); +} + template bool CSimpleIniTempl::GetAllValues( @@ -1886,7 +2101,7 @@ CSimpleIniTempl::SaveFile( ) const { FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE fopen_s(&fp, a_pszFile, "wb"); #else // !__STDC_WANT_SECURE_LIB__ fp = fopen(a_pszFile, "wb"); @@ -2937,7 +3152,7 @@ typedef CSimpleIniTempl #include +#include #define SI_SUPPORT_IOSTREAMS #if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE) @@ -94,6 +95,20 @@ Test( _tprintf(_T("Key: %s\n"), pItem); } + // add a decimal value + ini.SetLongValue(_T("integer"), _T("dec"), 42, NULL, false); + ini.SetLongValue(_T("integer"), _T("hex"), 42, NULL, true); + + // add some bool values + ini.SetBoolValue(_T("bool"), _T("t"), true); + ini.SetBoolValue(_T("bool"), _T("f"), false); + + // get the values back + assert(42 == ini.GetLongValue(_T("integer"), _T("dec"))); + assert(42 == ini.GetLongValue(_T("integer"), _T("hex"))); + assert(true == ini.GetBoolValue(_T("bool"), _T("t"))); + assert(false == ini.GetBoolValue(_T("bool"), _T("f"))); + // delete the section "standard" ini.Delete(_T("standard"), NULL); _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"), -- cgit v1.2.3