Depending on program and user *.ini file Reader/Writer.

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
D.J.Peters
Posts: 7852
Joined: May 28, 2005 3:28

Depending on program and user *.ini file Reader/Writer.

Postby D.J.Peters » Dec 24, 2012 3:48

I know there are more ini file reader/writers on this forum but they doesn't support my needs.

I needed a user and application depending solution for windows and linux.

You can't set the name of the inifile. (it depends on the application).
You can't set the path of the ini file. (it depends on the user)
On Windows it use it's own path and file in the the writeable "APPDATA" path.
Onl Lnux it use it's own (hidden) ./path and file in the writeable $HOME path.
Image
Supported data types are:
boolean, integer, single and strings.

Joshy

include file "Ini.bi"

Code: Select all

' File: Ini.bi
#ifndef __INI_BI__
#define __INI_BI__

type Ini
  public:
  declare constructor ()
  declare function AppName as string
  declare function Path as string
  declare function FileName as string
  declare function ReadBoolean(section as string, key as string, DefaultValue as integer) as integer
  declare function ReadInteger(section as string, key as string, DefaultValue as integer) as integer
  declare function ReadSingle (section as string, key as string, DefaultValue as single)  as single
  declare function ReadString (section as string, key as string, DefaultValue as string)  as string
  declare sub      WriteBoolean(section as string, key as string, Value as integer)
  declare sub      WriteInteger(section as string, key as string, Value as integer)
  declare sub      WriteSingle (section as string, key as string, Value as single)
  declare sub      WriteString (section as string, key as string, Value as string)
 
  private:
  declare function Read (section as string, key as string) as string
  declare sub      Write(section as string, key as string,value as string)
  as string m_AppName, m_Path, m_FileName
end type

constructor Ini()
#ifdef __FB_WIN32__
  dim as string PATHSEP = "\"
#else
  dim as string PATHSEP = "/"
#endif
  m_APPName = command(0)
  dim as integer p = InstrRev(m_APPName,"/")
  if p>0 then
    m_AppName = right(m_AppName,len(m_AppName)-p)
  else
    p = InstrRev(m_APPName,PATHSEP)
    if p>0 then m_AppName = right(m_AppName,len(m_AppName)-p)
  end if
  p = InstrRev(m_APPName,".")
  if p>0 then m_AppName = left(m_AppName,p-1)
  m_AppName = lcase(m_AppName)

  m_FileName = m_AppName & ".ini"
 
#ifdef __FB_WIN32__
  m_Path=environ("APPDATA")
  if right(m_Path,1) <> PATHSEP then m_Path &= PATHSEP
  m_Path &= m_AppName & PATHSEP
#else
  m_Path=environ("HOME")
  if right(m_Path,1) <> PATHSEP then m_Path &= PATHSEP
  m_Path &= "." & m_AppName & PATHSEP
#endif 

  ' create the path if needed
  dim as string oldpath = CurDir()
  if ChDir(m_PATH) then mkdir(m_PATH)
  chdir(oldpath)

  ' create the file if needed
  dim as integer hFile = FreeFile
  if open(m_Path & m_FileName,for binary,access read,as #hFile) then
    hFile = FreeFile()
    open m_Path & m_FileName for output as #hFile
    print #hFile,"[" & ucase(m_AppName) & "]"
    close #hFile
  else
    close #hFile
  end if

end constructor

function Ini.Read(section as string,key as string) as string

  section = ucase(trim(section))
  if len(section)<1 then section = ucase(m_AppName)
  section= "[" & section & "]"
  dim as integer hFile=FreeFile()
  if open(m_Path & m_FileName,for input,as #hFile) then
    return ""
  end if
 
  dim as string aLine
  dim as integer Found
  while (Found=0) and (eof(hFile)=0)
    line input #hFile,aLine
    aLine=ucase(trim(aLine))
    if len(aLine) then
      if aLine=section then found=1
    end if 
  wend
  if found=0 then
    close #hFile
    return ""
  end if
 
  key = ucase(trim(key))
  if len(key)=0 then
    close #hFile
    return ""
  end if
 
  dim as integer sectionerror
  found=0
  while (Found=0) and (eof(hFile)=0) and (sectionerror=0)
    line input #hFile,aLine
    aLine=ucase(trim(aLine))
    if len(aLine) then
      if left(aLine,1)="[" and right(aLine,1)="]" then
        sectionerror=1
      else   
        if left(aLine,len(key))=key then found=1
      end if 
    end if
  wend
  close #hFile
  if found=0 then return ""
 
  dim as integer p = instrrev(aLine,"=")
  if p=0 then return ""
 
  dim as string value = right(aLine,len(aLine)-p)
 
  return trim(value)
end function

sub Ini.Write(section as string,key as string,value as string)
  section = trim(section)
  if len(section) then
    section = ucase(section)
  else
    section = ucase(m_AppName)
  end if
  section = "[" & section & "]"
 
  key = trim(key)
  if len(key)<1 then return
  key=ucase(key)
 
  value = trim(value)

  dim as integer hFile=FreeFile()
  if open(m_Path & m_FileName,for input,as #hFile) then
    return
  end if
 
  dim as integer nLines,sectionerror,foundsection=-1,foundkey=-1
  dim as string Lines(),aLine
  while (eof(hFile)=0)
    line input #hFile,aLine 
    aLine=trim(aLine)
    if len(aLine)>0 then
      redim preserve Lines(nLines)
      Lines(nLines)=aLine
      if (foundsection=-1) then
        if left(aLine,1)="[" andalso right(aLine,1)="]" then
          aLine=ucase(aLine)
          if aLine=section then foundsection=nLines
        end if
      elseif (foundkey=-1) andalso (sectionerror=0) then
        if left(aLine,1)="[" andalso right(aLine,1)="]" then
          sectionerror=1
        else
          aLine=ucase(aLine) 
          if left(aLine,len(key))=key then foundkey=nLines
        end if 
      end if
      nLines+=1
    end if
  wend
  close #hFile

  if (foundsection=-1) then
    ' append a new section and key
    redim preserve Lines(nLines)
    Lines(nLines)=section
    foundsection=nLines
    nLines+=1
    redim preserve Lines(nLines)
    Lines(nLines)=key & "=" & value
    foundkey=nLines
    nLines+=1
  elseif (foundkey<>-1) then
    ' set key with value
    Lines(foundkey) = key & "=" & value
  else
    dim as string tmp(nLines)
    dim as integer cLine=0
    for i as integer=0 to nLines-1
      tmp(cLine)=Lines(i)
      cLine+=1
      if (i=foundsection) then
        ' add new key in section
        tmp(cLine) = key & "=" & value
        cLine+=1
      end if
    next
    nLines=cLine
    redim Lines(nLines-1)
    for i as integer=0 to nLines-1
      Lines(i)=tmp(i)
    next
  end if
  ' write ini file
  hFile=FreeFile()
  if open(m_Path & m_FileName,for output,as #hFile) then
    return
  end if
  for i as integer = 0 to nLines-1
    print #hFile,Lines(i)
  next
  close #hFile
end sub

function Ini.ReadBoolean(section as string,key as string,defaultvalue as integer) as integer
  dim as string value = this.read(section,key)
  if value="" then return defaultvalue
  if lcase(value)="true" then return -1
  return 0
end function
function Ini.ReadInteger(section as string,key as string,defaultvalue as integer) as integer
  dim as string value = this.read(section,key)
  if value="" then return defaultvalue
  return int(val(value))
end function
function Ini.ReadSingle(section as string,key as string,defaultvalue as single) as single
  dim as string value = this.read(section,key)
  if value="" then return defaultvalue
  return val(value)
end function
function Ini.ReadString(section as string,key as string,defaultvalue as string) as string
  dim as string value = this.read(section,key)
  if value="" then return defaultvalue
  return value
end function

sub Ini.WriteBoolean(section as string,key as string,value as integer)
  if value<>0 then
    this.write(section,key,"true")
  else
    this.write(section,key,"false")
  end if
end sub
sub Ini.WriteInteger(section as string,key as string,value as integer)
  this.write(section,key,str(value))
end sub
sub Ini.WriteSingle(section as string,key as string,value as single)
  this.write(section,key,str(value))
end sub
sub Ini.WriteString(section as string,key as string,value as string)
  this.write(section,key,value)
end sub
 
function Ini.AppName as string
  return m_AppName
end function
function Ini.Path as string
  return m_Path
end function
function Ini.FileName as string
  return m_FileName
end function

#endif ' __INI_BI__

A short test "initest01.bas"

Code: Select all

' File: IniTest01.bas
#include once "fbgfx.bi"
#include once "Ini.bi"

const as string section = "screen"

dim as Ini IniFile

' key's are insensitive
dim as integer w = IniFile.ReadInteger(section,"WIDTH",640)
dim as integer h = IniFile.ReadInteger(section,"height",480)
dim as integer b = IniFile.ReadInteger(section,"BPP",24)
dim as integer flags
if IniFile.ReadBoolean(section,"FULLscreen",1) then
  flags = FB.GFX_FULLSCREEN
end if


screenres w,h,,b,flags
? "application : " & Inifile.AppName
? "init path   : " & Inifile.Path
? "init file   : " & Inifile.FileName
? w & " x " & h & " x " & b & " fullscreen: "; 
if flags then ? "true" else ? "false"
? "press any key"
sleep

IniFile.WriteInteger(section,"width",w)
IniFile.WriteInteger(section,"height",h)
IniFile.WriteInteger(section,"bpp",b)
IniFile.WriteBoolean(section,"fullscreen",flags)
TJF
Posts: 3486
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Depending on program and user *.ini file Reader/Writer.

Postby TJF » Dec 24, 2012 7:05

D.J.Peters wrote:Onl Lnux it use it's own (hidden) ./path and file in the writeable $HOME path.

Today, it's more common to use ./config/path

BTW: Your solution is similar to the GLib Key-value file parser.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest