随笔 - 16, 文章 - 0, 评论 - 55, 引用 - 0
数据加载中……

跨平台的INI处理源代码

// IniFile.h

#ifndef INIFILE_H
#define INIFILE_H

#include < stdio.h >
#include < stdlib.h >
#include < string.h >

#ifndef OWP_DONT_DEF_FALSE
#ifndef FALSE
#define FALSE 0
#endif
#endif

#ifndef OWP_DONT_DEF_TRUE
#ifndef TRUE
#define TRUE 1
#endif
#endif

#ifndef OWP_DONT_DEF_BOOL
#ifndef BOOL
#define BOOL unsigned int
#endif
#endif

#ifndef OWP_DONT_DEF_CCHR
#ifndef CCHR
#define CCHR const char
#endif
#endif

#ifndef OWP_DONT_DEF_UCHR
#ifndef UCHR
#define UCHR unsigned char
#endif
#endif

#ifndef OWP_DONT_DEF_UCCHR
#ifndef UCCHR
#define UCCHR const unsigned char
#endif
#endif

#ifndef OWP_DONT_DEF_UINT
#ifndef UINT
#define UINT unsigned int
#endif
#endif

#ifndef OWP_DONT_DEF_WORD
#ifndef WORD
#define WORD unsigned short
#endif
#endif

#ifdef LINUX /* Remove CR, on unix systems. */
#define INI_REMOVE_CR
#define DONT_HAVE_STRUPR
#endif

#define tpNULL 0
#define tpSECTION 1
#define tpKEYVALUE 2
#define tpCOMMENT 3

struct ENTRY
{
char Type;
char *pText;
struct ENTRY *pPrev;
struct ENTRY *pNext;
};

typedef struct
{
struct ENTRY *pSec;
struct ENTRY *pKey;
char KeyText [128];
char ValText [128];
char Comment [255];
} EFIND;

/* Macros */
#define ArePtrValid(Sec,Key,Val) ((Sec!=NULL)&&(Key!=NULL)&&(Val!=NULL))

class CIniFile
{
public:
CIniFile (void)
  {
    m_pEntry = NULL;
    m_pCurEntry = NULL;
    m_result [0] = 0;
    m_pIniFile = NULL;
  }

  ~CIniFile (void)
  {
    FreeAllMem ();
  }

BOOL OpenIniFile (CCHR *pFileName)
  {
    char Str [255];
    char *pStr;
    struct ENTRY *pEntry;
    
    FreeAllMem ();
    
    if (pFileName == NULL) { return FALSE; }
    if ((m_pIniFile = fopen (pFileName, "r")) == NULL) { return FALSE; }
    
    while (fgets (Str, 255, m_pIniFile) != NULL) {
      pStr = strchr (Str, '\n');
      if (pStr != NULL) { *pStr = 0; }
      pEntry = MakeNewEntry ();
      if (pEntry == NULL) { return FALSE; }
      
      #ifdef INI_REMOVE_CR
      Len = strlen(Str);
      if ( Len > 0 ) {
        if ( Str[Len-1] == '\r' ) {
          Str[Len-1] = '\0';
        }
      }
      #endif
      
      pEntry->pText = (char *)malloc (strlen (Str)+1);
      if (pEntry->pText == NULL) {
        FreeAllMem ();
        return FALSE;
      }
      strcpy (pEntry->pText, Str);
      pStr = strchr (Str,';');
      if (pStr != NULL) { *pStr = 0; } /* Cut all comments */
      if ( (strstr (Str, "[") > 0) && (strstr (Str, "]") > 0) ) /* Is Section */ {
        pEntry->Type = tpSECTION;
      } else {
        if (strstr (Str, "=") > 0) {
          pEntry->Type = tpKEYVALUE;
        } else {
          pEntry->Type = tpCOMMENT;
        }
      }
      m_pCurEntry = pEntry;
    }
    fclose (m_pIniFile);
    m_pIniFile = NULL;
    return TRUE;
  }

void CloseIniFile ()
  {
    FreeAllMem ();
    if (m_pIniFile != NULL) {
      fclose (m_pIniFile);
      m_pIniFile = NULL;
    }
  }

bool WriteIniFile (CCHR *pFileName)
  {
    struct ENTRY *pEntry = m_pEntry;
    if (m_pIniFile != NULL) {
      fclose (m_pIniFile);
    }
    if ((m_pIniFile = fopen (pFileName, "wb")) == NULL) {
      FreeAllMem ();
      return FALSE;
    }
    
    while (pEntry != NULL) {
      if (pEntry->Type != tpNULL) {
      #ifdef INI_REMOVE_CR
        fprintf (m_pIniFile, "%s\n", pEntry->pText);
      #else
        fprintf (m_pIniFile, "%s\r\n", pEntry->pText);
      #endif
      }
      pEntry = pEntry->pNext;
    }
    
    fclose (m_pIniFile);
    m_pIniFile = NULL;
    return TRUE;
  }
  
  bool  DeleteKey (CCHR *pSection, CCHR *pKey)
  {
    EFIND List;
    struct ENTRY *pPrev;
    struct ENTRY *pNext;
    
    if (FindKey (pSection, pKey, &List) == TRUE) {
      pPrev = List.pKey->pPrev;
      pNext = List.pKey->pNext;
      if (pPrev) {
        pPrev->pNext=pNext;
      }
      if (pNext) {
        pNext->pPrev=pPrev;
      }
      FreeMem (List.pKey->pText);
      FreeMem (List.pKey);
      return TRUE;
    }
    return FALSE;
  }

  BOOL ReadBool (CCHR *pSection, CCHR *pKey, BOOL Default)
  {
    char Val [2] = {"0"};
    if (Default != 0) { Val [0] = '1'; }
    return (atoi (ReadString (pSection, pKey, Val))?1:0); /* Only allow 0 or 1 */
  }

int ReadInt (CCHR *pSection, CCHR *pKey, int Default)
  {
    char Val [12];
    sprintf (Val,"%d", Default);
    return (atoi (ReadString (pSection, pKey, Val)));
  }

double ReadDouble (CCHR *pSection, CCHR *pKey, double Default)
  {
    double Val;
    sprintf (m_result, "%1.10lE", Default);
    sscanf (ReadString (pSection, pKey, m_result), "%lE", &Val);
    return Val;
  }

CCHR *ReadString (CCHR *pSection, CCHR *pKey, CCHR *pDefault)
  {
    EFIND List;
    if (ArePtrValid (pSection, pKey, pDefault) == FALSE) { return pDefault; }
    if (FindKey (pSection, pKey, &List) == TRUE) {
      strcpy (m_result, List.ValText);
      return m_result;
    }
    return pDefault;
  }

void WriteBool (CCHR *pSection, CCHR *pKey, bool Value)
  {
    char Val [2] = {'0',0};
    if (Value != 0) { Val [0] = '1'; }
    WriteString (pSection, pKey, Val);
  }
  
void WriteInt (CCHR *pSection, CCHR *pKey, int Value)
  {
    char Val [12]; /* 32bit maximum + sign + \0 */
    sprintf (Val, "%d", Value);
    WriteString (pSection, pKey, Val);
  }

void WriteDouble (CCHR *pSection, CCHR *pKey, double Value)
  {
    char Val [32]; /* DDDDDDDDDDDDDDD+E308\0 */
    sprintf (Val, "%1.10lE", Value);
    WriteString (pSection, pKey, Val);
  }

void WriteString (CCHR *pSection, CCHR *pKey, CCHR *pValue)
  {
    EFIND List;
    char Str [255];
    
    if (ArePtrValid (pSection, pKey, pValue) == FALSE) { return; }
    if (FindKey (pSection, pKey, &List) == TRUE) {
      sprintf (Str, "%s=%s%s", List.KeyText, pValue, List.Comment);
      FreeMem (List.pKey->pText);
      List.pKey->pText = (char *)malloc (strlen (Str)+1);
      strcpy (List.pKey->pText, Str);
    } else {
      if ((List.pSec != NULL) && (List.pKey == NULL)) /* section exist, Key not */ {
        AddKey (List.pSec, pKey, pValue);
      } else {
        AddSectionAndKey (pSection, pKey, pValue);
      }
    }
  }

protected:
  struct ENTRY *m_pEntry;
  struct ENTRY *m_pCurEntry;
  char m_result [255];
  FILE *m_pIniFile;
  
  void AddKey (struct ENTRY *pEntry, CCHR *pKey, CCHR *pValue)
  {
    char Text [255];
    sprintf (Text, "%s=%s", pKey, pValue);
    AddItemAt (pEntry, tpKEYVALUE, Text);
  }
  
  BOOL AddItem (char Type, CCHR *pText)
  {
    struct ENTRY *pEntry = MakeNewEntry ();
    if (pEntry == NULL) { return FALSE; }
    pEntry->Type = Type;
    pEntry->pText = (char*)malloc (strlen (pText) +1);
    if (pEntry->pText == NULL) {
      free (pEntry);
      return FALSE;
    }
    strcpy (pEntry->pText, pText);
    pEntry->pNext = NULL;
    if (m_pCurEntry != NULL) { m_pCurEntry->pNext = pEntry; }
    m_pCurEntry = pEntry;
    return TRUE;
  }
  
  bool AddItemAt (struct ENTRY *pEntryAt, char Mode, CCHR *pText)
  {
    struct ENTRY *pNewEntry;
    if (pEntryAt == NULL) { return FALSE; }
    pNewEntry = (struct ENTRY*) malloc (sizeof (ENTRY));
    if (pNewEntry == NULL) { return FALSE; }
    pNewEntry->pText = (char *) malloc (strlen (pText)+1);
    if (pNewEntry->pText == NULL) {
      free (pNewEntry);
      return FALSE;
    }
    strcpy (pNewEntry->pText, pText);
    if (pEntryAt->pNext == NULL) /* No following nodes. */ {
      pEntryAt->pNext = pNewEntry;
      pNewEntry->pNext = NULL;
    } else {
      pNewEntry->pNext = pEntryAt->pNext;
      pEntryAt->pNext = pNewEntry;
    }
    pNewEntry->pPrev = pEntryAt;
    pNewEntry->Type = Mode;
    return TRUE;
  }
  
  void FreeMem (void *pPtr)
  {
    if (pPtr != NULL) { free (pPtr); }
  }
  
  void FreeAllMem (void)
  {
    struct ENTRY *pEntry;
    struct ENTRY *pNextEntry;
    pEntry = m_pEntry;
    while (1) {
      if (pEntry == NULL) { break; }
      pNextEntry = pEntry->pNext;
      FreeMem (pEntry->pText); /* Frees the pointer if not NULL */
      FreeMem (pEntry);
      pEntry = pNextEntry;
    }
    m_pEntry = NULL;
    m_pCurEntry = NULL;
  }
  
  bool FindKey (CCHR *pSection, CCHR *pKey, EFIND *pList)
  {
    char Search [130];
    char Found [130];
    char Text [255];
    char *pText;
    struct ENTRY *pEntry;
    pList->pSec = NULL;
    pList->pKey = NULL;
    pEntry = FindSection (pSection);
    if (pEntry == NULL) { return FALSE; }
    pList->pSec = pEntry;
    pList->KeyText[0] = 0;
    pList->ValText[0] = 0;
    pList->Comment[0] = 0;
    pEntry = pEntry->pNext;
    if (pEntry == NULL) { return FALSE; }
    sprintf (Search, "%s",pKey);
    strupr (Search);
    while (pEntry != NULL) {
      if ((pEntry->Type == tpSECTION) || /* Stop after next section or EOF */
        (pEntry->Type == tpNULL )) {
        return FALSE;
      }
      if (pEntry->Type == tpKEYVALUE) {
        strcpy (Text, pEntry->pText);
        pText = strchr (Text, ';');
        if (pText != NULL) {
          strcpy (pList->Comment, pText);
          *pText = 0;
        }
        pText = strchr (Text, '=');
        if (pText != NULL) {
          *pText = 0;
          strcpy (pList->KeyText, Text);
          strcpy (Found, Text);
          *pText = '=';
          strupr (Found);
          /* printf ("%s,%s\n", Search, Found); */
          if (strcmp (Found,Search) == 0) {
            strcpy (pList->ValText, pText+1);
            pList->pKey = pEntry;
            return TRUE;
          }
        }
      }
      pEntry = pEntry->pNext;
    }
    return NULL;
  }

  bool AddSectionAndKey (CCHR *pSection, CCHR *pKey, CCHR *pValue)
  {
    char Text [255];
    sprintf (Text, "[%s]", pSection);
    if (AddItem (tpSECTION, Text) == FALSE) { return FALSE; }
    sprintf (Text, "%s=%s", pKey, pValue);
    return AddItem (tpKEYVALUE, Text)? 1 : 0;
  }
  
  struct ENTRY *MakeNewEntry (void)
  {
    struct ENTRY *pEntry;
    pEntry = (struct ENTRY *)malloc (sizeof (ENTRY));
    if (pEntry == NULL) {
      FreeAllMem ();
      return NULL;
    }
    if (m_pEntry == NULL) {
      m_pEntry = pEntry;
    }
    pEntry->Type = tpNULL;
    pEntry->pPrev = m_pCurEntry;
    pEntry->pNext = NULL;
    pEntry->pText = NULL;
    if (m_pCurEntry != NULL) {
      m_pCurEntry->pNext = pEntry;
    }
    return pEntry;
  }
  
  struct ENTRY *FindSection (CCHR *pSection)
  {
    char Sec [130];
    char iSec [130];
    struct ENTRY *pEntry;
    sprintf (Sec, "[%s]", pSection);
    strupr (Sec);
    pEntry = m_pEntry; /* Get a pointer to the first Entry */
    while (pEntry != NULL) {
      if (pEntry->Type == tpSECTION) {
        strcpy (iSec, pEntry->pText);
        strupr (iSec);
        if (strcmp (Sec, iSec) == 0) {
          return pEntry;
        }
      }
      pEntry = pEntry->pNext;
    }
    return NULL;
  }

  #ifdef DONT_HAVE_STRUPR
  /* DONT_HAVE_STRUPR is set when INI_REMOVE_CR is defined */
  void strupr( char *str )
  {
    // We dont check the ptr because the original also dont do it.
    while (*str != 0) {
      if ( islower( *str ) ) {
        *str = toupper( *str );
      }
      str++;
    }
  }
  #endif
  
private:
};

#endif

#ifdef INIFILE_TEST_THIS_FILE
int main (void)
{
  CIniFile iFile;
  printf ("Hello World\n");
  iFile.OpenIniFile ("Test.Ini");
  iFile.WriteString ("Test", "Name", "Value");
  iFile.WriteString ("Test", "Name", "OverWrittenValue");
  iFile.WriteString ("Test", "Port", "COM1");
  iFile.WriteString ("Test", "User", "James Brown jr.");
  iFile.WriteString ("Configuration", "eDriver", "MBM2.VXD");
  iFile.WriteString ("Configuration", "Wrap", "LPT.VXD");
  iFile.WriteInt ("IO-Port", "Com", 2);
  iFile.WriteBool ("IO-Port", "IsValid", 0);
  iFile.WriteDouble ("TheMoney", "TheMoney", 67892.00241);
  iFile.WriteInt ("Test" , "ToDelete", 1234);
  iFile.WriteIniFile ("Test.Ini");
  printf ("Key ToDelete created. Check ini file. Any key to continue");
  while (!kbhit());
  iFile.OpenIniFile ("Test.Ini");
  iFile.DeleteKey ("Test"   , "ToDelete");
  iFile.WriteIniFile ("Test.Ini");
  printf ("[Test] Name = %s\n", iFile.ReadString ("Test", "Name", "NotFound"));
  printf ("[Test] Port = %s\n", iFile.ReadString ("Test", "Port", "NotFound"));
  printf ("[Test] User = %s\n", iFile.ReadString ("Test", "User", "NotFound"));
  printf ("[Configuration] eDriver = %s\n", iFile.ReadString ("Configuration", "eDriver", "NotFound"));
  printf ("[Configuration] Wrap = %s\n", iFile.ReadString ("Configuration", "Wrap", "NotFound"));
  printf ("[IO-Port] Com = %d\n", iFile.ReadInt ("IO-Port", "Com", 0));
  printf ("[IO-Port] IsValid = %d\n", iFile.ReadBool ("IO-Port", "IsValid", 0));
  printf ("[TheMoney] TheMoney = %1.10lf\n", iFile.ReadDouble ("TheMoney", "TheMoney", 111));
  iFile.CloseIniFile ();
  return 0;
}
#endif

posted on 2006-05-31 13:20 cyantree 阅读(856) 评论(1)  编辑 收藏 引用

评论

# re: 跨平台的INI处理源代码  回复  更多评论   

混合类型的编码,又C又类的。
2006-05-31 13:31 | LOGOS

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理