]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - tools/src/tools/Utils/common/Properties.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / Utils / common / Properties.cpp
diff --git a/tools/src/tools/Utils/common/Properties.cpp b/tools/src/tools/Utils/common/Properties.cpp
new file mode 100644 (file)
index 0000000..1fe99b7
--- /dev/null
@@ -0,0 +1,637 @@
+//####COPYRIGHTBEGIN####
+//                                                                          
+// ----------------------------------------------------------------------------
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
+//
+// This program is part of the eCos host tools.
+//
+// This program is free software; you can redistribute it and/or modify it 
+// under the terms of the GNU General Public License as published by the Free 
+// Software Foundation; either version 2 of the License, or (at your option) 
+// any later version.
+// 
+// This program is distributed in the hope that it will be useful, but WITHOUT 
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+// more details.
+// 
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//
+// ----------------------------------------------------------------------------
+//                                                                          
+//####COPYRIGHTEND####
+// Properties.cpp: implementation of the CProperties class.
+//
+//////////////////////////////////////////////////////////////////////
+#include "Properties.h"
+#include "eCosTrace.h"
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CProperties::CProperties()
+{
+}
+
+CProperties::~CProperties()
+{
+}
+
+#ifdef _WIN32
+bool CProperties::LoadFromRegistry(HKEY hTopKey,LPCTSTR szRegKey)
+{
+  HKEY hKey;
+  LONG l=RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_QUERY_VALUE, &hKey);
+  bool rc=(ERROR_SUCCESS==l);
+  if(rc){
+    TCHAR szName[256];
+    DWORD dwSizeName=sizeof szName;
+    DWORD dwMaxDatalen;
+    DWORD dwType;
+    if(ERROR_SUCCESS==RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dwMaxDatalen,NULL,NULL)){
+      char *Data=new char[dwMaxDatalen];
+      DWORD dwDatalen=dwMaxDatalen;
+      for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumValue(hKey, dwIndex, szName, &dwSizeName, NULL, &dwType, (LPBYTE)Data, &dwDatalen);dwIndex++){ 
+        
+        CProperties::CProperty *p=Lookup(szName);
+        if(p){
+          switch(p->Type){
+            case CProperty::Integer:
+              if(REG_DWORD==dwType){
+                p->SetValue(*(int *)Data);
+              } else {
+                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
+                rc=false;
+              }
+              break;
+            case CProperty::Bool:
+              if(REG_DWORD==dwType){
+                p->SetValue((bool)0!=*(int *)Data);
+              } else {
+                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
+                rc=false;
+              }
+              break;
+            case CProperty::Char:
+              if(REG_DWORD==dwType){
+                p->SetValue(*(char *)Data);
+              } else {
+                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
+                rc=false;
+              }
+              break;
+            case CProperty::Short:
+              if(REG_DWORD==dwType){
+                p->SetValue(*(short *)Data);
+              } else {
+                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
+                rc=false;
+              }
+              break;
+            case CProperty::Float:
+            case CProperty::Double:
+            case CProperty::szString: 
+              if(REG_SZ==dwType){
+                rc&=p->SetValue((LPCTSTR)Data);
+              } else {
+                TRACE(_T("Type mismatch - %s: expected REG_SZ, got %d\n"),(LPCTSTR)p->strName,dwType);
+                rc=false;
+              }
+              break;
+            case CProperty::Void:
+              if(REG_BINARY==dwType){
+                memcpy(p->pData,Data,MIN(dwDatalen,p->nLength));
+              } else {
+                TRACE(_T("Type mismatch - %s: expected REG_BINARY, got %d\n"),(LPCTSTR)p->strName,dwType);
+                rc=false;
+              }
+              break;
+          }
+        } else {
+          TRACE(_T("CProperties::LoadFromRegistry - unrecognized value %s in key %s\n"),szName,szRegKey);
+          rc=false;
+        }
+        dwSizeName=sizeof szName;
+        dwDatalen=dwMaxDatalen;
+      }
+      delete [] Data;
+      dwSizeName=sizeof szName;
+    }
+    RegCloseKey(hKey);
+  } else {
+    TRACE(_T("Failed to open %s\n"),szRegKey);
+  }
+  
+  return rc;
+}
+
+bool CProperties::SaveToRegistry(HKEY hTopKey,LPCTSTR szRegKey) const
+{
+  HKEY hKey;
+  CreateKey(szRegKey);
+  bool rc=(ERROR_SUCCESS==RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_SET_VALUE, &hKey));
+  if(rc){
+    for(int i=ar.size()-1;i>=0;--i){
+      // Initializations are simply to avoid compiler warnings.
+      DWORD dwDatalen=0; 
+      DWORD dwType=REG_DWORD;
+      BYTE *Data=0;
+      // strValue and dw *must* be in scope for RegSetValueEx below.
+      DWORD dw;
+      String strValue;
+      const CProperty &p=ar[i];
+      switch(p.Type){
+        case CProperties::CProperty::Integer:
+        case CProperties::CProperty::Bool:
+        case CProperties::CProperty::Char:
+        case CProperties::CProperty::Short:
+          dwType=REG_DWORD;
+          dwDatalen=sizeof(DWORD);
+          dw=p.GetValue();
+          Data=(BYTE *)&dw;
+          break;
+        case CProperties::CProperty::Float:
+        case CProperties::CProperty::Double:
+        case CProperties::CProperty::szString:
+          strValue=p.GetStringValue();
+          Data=(BYTE *)(LPCTSTR)strValue;
+          dwType=REG_SZ;
+          dwDatalen=(1+strValue.size())*sizeof(_TCHAR);
+          break;
+        case CProperties::CProperty::Void:
+          Data=(BYTE *)p.pData;
+          dwType=REG_BINARY;
+          dwDatalen=p.nLength;
+          break;
+        default:
+          assert(false);
+          break;
+      }
+      rc&=(ERROR_SUCCESS==RegSetValueEx(hKey,p.strName,0,dwType,Data,dwDatalen));
+    }
+  }   
+  RegCloseKey(hKey);
+  return rc;    
+}
+
+// Create all keys down to the one specified
+bool CProperties::CreateKey(LPCTSTR pszKey,HKEY hKey/*=HKEY_CURRENT_USER*/)
+{
+  bool rc=true;
+  LPCTSTR pcStart=pszKey;
+  LPCTSTR pcEnd;
+  do {
+    HKEY hKey2;
+    pcEnd=_tcschr(pcStart,_TCHAR('\\'));
+    if(NULL==pcEnd){
+      pcEnd=pcStart+_tcslen(pcStart);
+    }
+    String strKey(pcStart,pcEnd-pcStart);
+    if(ERROR_SUCCESS!=RegCreateKeyEx(hKey,                // handle to an open key
+      strKey,         // address of subkey name
+      0,           // reserved
+      0,           // address of class string
+      REG_OPTION_NON_VOLATILE,          // special options flag
+      KEY_ALL_ACCESS,        // desired security access
+      NULL,
+      // address of key security structure
+      &hKey2,          // address of buffer for opened handle
+      NULL// address of disposition value buffer);
+      )){
+      rc=false;
+      break;
+    }
+    RegCloseKey(hKey);
+    hKey=hKey2;
+    pcStart=pcEnd+1;
+  } while (_TCHAR('\0')!=*pcEnd);
+  RegCloseKey(hKey);
+  return rc;
+}
+
+#endif
+
+bool CProperties::LoadFromCommandString(LPCTSTR psz)
+{
+  bool rc=true;
+  const TCHAR *cNext;
+  for(LPCTSTR c=_tcschr(psz,_TCHAR('-'));c;c=_tcschr(cNext,_TCHAR('-'))){
+    c++;
+    const TCHAR *pEq=_tcschr(c,_TCHAR('='));
+    if(NULL==pEq){
+      TRACE(_T("Failed to find '=' after %s\n"),c);
+      rc=false;
+      break;
+    }
+    String strName(c,pEq-c);
+    CProperties::CProperty *p=Lookup(strName);
+    c=pEq+1;
+    String str;
+    if(_TCHAR('"')==*c){
+      // Value is a quoted string
+      for(cNext=c+1;_TCHAR('"')!=*cNext;cNext++){
+        if(_TCHAR('\\')==*cNext){
+          cNext++;
+        }
+        str+=*cNext;
+      }
+    } else {
+      // Value is simply terminated by whitespace
+      for(cNext=c;_TCHAR('\0')!=*cNext && !_istspace(*cNext);cNext++);
+      str=String(c,cNext-c);
+    }
+    if(p){
+      rc&=p->SetValue(str);
+    } else {
+      TRACE(_T("Properties: unrecognized attribute %s in command string\n"),(LPCTSTR)strName);
+      rc=false;
+    }
+    c=cNext;
+  }
+  return rc;
+}
+
+CProperties::CProperty * CProperties::Lookup(LPCTSTR pszName)
+{
+  for(int i=ar.size()-1;i>=0;--i){
+    CProperties::CProperty &p=ar[i];
+    if(0==_tcsicmp(p.strName,pszName)){
+      return &p;
+    }
+  }
+  return NULL;
+}
+
+String CProperties::MakeCommandString() const
+{
+  String strResult;
+  bool bFirst=true;
+  for(int i=ar.size()-1;i>=0;--i){
+    String str;    
+    const CProperty &p=ar[i];
+    switch(p.Type){
+      case CProperties::CProperty::Integer:
+      case CProperties::CProperty::Bool:
+      case CProperties::CProperty::Char:
+      case CProperties::CProperty::Short:
+        str.Format(_T("-%s=%u"),(LPCTSTR)p.strName,p.GetValue());
+        break;
+      case CProperties::CProperty::szString:
+        {
+          // Quote the string, escaping existing quotes as necessary
+          str.Format(_T("-%s=\""),(LPCTSTR)p.strName);
+          for(LPCTSTR c=p.GetStringValue();*c;c++){
+            if(_TCHAR('"')==*c){
+              str+=_TCHAR('\\');
+            }
+            str+=*c;
+          }
+          str+=_TCHAR('"');
+        }
+        break;
+      case CProperties::CProperty::Float:
+      case CProperties::CProperty::Double:
+      case CProperties::CProperty::Void:
+        str.Format(_T("-%s=%s"),(LPCTSTR)p.GetStringValue());
+        break;
+    }
+    if(!bFirst){
+      strResult+=_TCHAR(' ');
+    }
+    bFirst=false;
+    strResult+=str;
+  }
+  return strResult;
+}       
+
+bool CProperties::CreatePathToFile(LPCTSTR pszDir) 
+{
+  // Create intermediate directories
+#ifdef _WIN32
+  const TCHAR cSep='\\';
+#else // UNIX
+  const TCHAR cSep='/';
+#endif
+  for(LPCTSTR c=_tcschr(pszDir,cSep);c;c=_tcschr(c+1,cSep)){
+#ifdef _WIN32
+    if(c==pszDir+2 && _istalpha(pszDir[0]) && _TCHAR(':')==pszDir[1]){
+      continue; // don't attempt to create "C:"
+    }
+#endif
+    String strDir(pszDir,c-pszDir);
+    struct _stat buf;
+    if(!(0==_tstat(strDir,&buf) && (S_IFDIR&buf.st_mode))){
+      // Need to create directory
+      bool b=(0==_tmkdir(strDir));
+      TRACE(_T("Create directory %s rc=%d\n"),(LPCTSTR)strDir,b);
+      if(!b){
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool CProperties::SaveToFile(LPCTSTR pszFileName) const
+{
+  CreatePathToFile(pszFileName);
+  FILE *f=_tfopen(pszFileName,_T("w") MODE_TEXT);
+  if(f){
+    for(int i=ar.size()-1;i>=0;--i){
+      const CProperty &p=ar[i];
+      String str(p.strName);
+      str+=_TCHAR('=');
+      switch(p.Type){
+        case CProperties::CProperty::Integer:
+        case CProperties::CProperty::Bool:
+        case CProperties::CProperty::Char:
+        case CProperties::CProperty::Short:
+          str+=String::SFormat(_T("%u"),p.GetValue());
+          break;
+        case CProperties::CProperty::Float:
+        case CProperties::CProperty::Double:
+        case CProperties::CProperty::szString:
+        case CProperties::CProperty::Void:
+          str+=p.GetStringValue();
+          break;
+      }
+      str+=_TCHAR('\n');
+      _fputts(str,f);
+    }
+    fclose(f);
+  }
+  return (0!=f);
+}
+
+bool CProperties::LoadFromFile(LPCTSTR pszFileName)
+{
+  FILE *f=_tfopen(pszFileName,_T("r") MODE_TEXT);
+  bool rc=(0!=f);
+  if(rc){
+    TCHAR buf[4096];
+    int nLine=0;
+    String str;
+    while(_fgetts(buf,sizeof(buf)-1,f)){
+      
+      nLine++;
+      int nLen=_tcslen(buf);
+      if(nLen>0){
+        // Remove trailing '\n'
+        if(_TCHAR('\n')==buf[nLen-1]){
+          buf[--nLen]=_TCHAR('\0');
+        }
+        // Remove trailing '\r'
+        if(_TCHAR('\r')==buf[nLen-1]){
+          buf[--nLen]=_TCHAR('\0');
+        }
+        
+        // Check for continuation lines
+        if(_TCHAR('\\')==buf[nLen-1]){
+          buf[--nLen]=_TCHAR('\0');
+          str+=buf;
+        } else {
+          str+=buf;
+          LPCTSTR c=(LPCTSTR)str;
+          const TCHAR *pEq=_tcschr(c,_TCHAR('='));
+          if(pEq){
+            const String strName(c,pEq-c);
+            CProperties::CProperty *p=Lookup(strName);
+            if(p){
+              pEq++;
+              rc&=p->SetValue(pEq);
+            } else {
+              ERROR(_T("Unknown attribute %s found in %s line %d\n"),(LPCTSTR)strName,pszFileName,nLine);
+              rc=false;
+            }
+          }
+          str=_T("");
+        }
+      }
+    }
+    fclose(f);
+  }
+  return rc;
+}
+
+CProperties::CProperty::CProperty(LPCTSTR pszName,Typetype type,void *_pData):
+  strName(pszName),
+  Type(type),
+  pData(_pData)
+{
+}
+
+CProperties::CProperty::~CProperty()
+{
+}
+
+void CProperties::Add(LPCTSTR pszName,int &n) 
+{
+  CProperty p(pszName,CProperty::Integer,&n);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,unsigned int &n)
+{
+  CProperty p(pszName,CProperty::Integer,&n);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,bool &b)
+{
+  CProperty p(pszName,CProperty::Bool,&b);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,char &c)
+{
+  CProperty p(pszName,CProperty::Char,&c);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,unsigned char &c)
+{
+  CProperty p(pszName,CProperty::Char,&c);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,short &s)
+{
+  CProperty p(pszName,CProperty::Short,&s);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,unsigned short &s)
+{
+  CProperty p(pszName,CProperty::Short,&s);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,float &f)
+{
+  CProperty p(pszName,CProperty::Float,&f);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,double &f) 
+{
+  CProperty p(pszName,CProperty::Double,&f);
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,void *pv,unsigned int _nLength)
+{
+  CProperty p(pszName,CProperty::Void,pv);
+  p.nLength=_nLength;
+  ar.push_back(p);
+}
+
+void CProperties::Add(LPCTSTR pszName,String &s)
+{
+  CProperty p(pszName,CProperty::szString,(void *)&s);
+  ar.push_back(p);
+}
+
+unsigned long CProperties::CProperty::GetValue() const
+{
+  unsigned long dw;
+  switch(Type){
+    case Integer:
+      dw=*(int *)pData;
+      break;
+    case Bool:
+      dw=*(bool *)pData;
+      break;
+    case Char:
+      dw=*(char *)pData;
+      break;
+    case Short:
+      dw=*(short *)pData;
+      break;
+    default:
+      dw=0;
+      assert(false);
+  }
+  return dw;
+}
+
+const String CProperties::CProperty::GetStringValue() const 
+{
+  String str;
+  switch(Type){
+    case szString:
+      str=*(String *)pData; 
+      break;
+    case CProperties::CProperty::Integer:
+    case CProperties::CProperty::Bool:
+    case CProperties::CProperty::Char:
+    case CProperties::CProperty::Short:
+      str.Format(_T("%u"),GetValue());
+      break;
+    case CProperties::CProperty::Float:
+      str.Format(_T("%e"),*(float *)(pData));
+      break;
+    case CProperties::CProperty::Double:
+      str.Format(_T("%e"),*(double *)(pData));
+      break;
+    case CProperties::CProperty::Void:
+      {
+        unsigned char *c=(unsigned char *)pData;
+        for(unsigned int i=0;i<nLength;i++){
+          TCHAR buf[3];
+          _tprintf(buf,_T("%02x"),c[i]);
+          str+=buf;
+        }
+      }
+      break;
+    default:
+      break;
+  }
+  return str;
+}
+
+bool CProperties::CProperty::SetValue(int n)
+{
+  bool rc=true;
+  switch(Type){
+    case Integer:
+      *(int *)(pData)=n;
+      break;
+    case Bool:
+      *(bool *)(pData)=(0!=n);
+      break;
+    case Char:
+      *(char *)(pData)=(char)n; //FIXME: range checks
+      break;
+    case Short:
+      *(short *)(pData)=(short)n;//FIXME: range checks
+      break;
+    default:
+      TRACE(_T("Failed to set '%s' to integer value '%d'\n"),(LPCTSTR)strName,n);
+      break;
+  }
+  return rc;
+}
+
+bool CProperties::CProperty::SetValue(double n)
+{
+  bool rc=true;
+  switch(Type){
+    case Double:
+      *(float *)(pData)=(float)n;//FIXME: range checks?
+      break;
+    case Float:
+      *(double *)(pData)=n;
+      break;
+    default:
+      TRACE(_T("Failed to set '%s' to double value '%f'\n"),(LPCTSTR)strName,n);
+      rc=false;
+      break;
+  }
+  
+  return rc;
+}
+
+bool CProperties::CProperty::SetValue(LPCTSTR psz)
+{
+  bool rc=false;
+  TCHAR *pEnd;
+  double d=0.0;
+  long l=0;
+  switch(Type){
+    case szString:
+      *(String *)pData=psz;
+      rc=true;
+      break;
+    case Float:
+      d=_tcstod(psz,&pEnd);
+      rc=(_TCHAR('\0')==*pEnd);
+      if(rc){
+        SetValue((float)d);
+      }
+      break;
+    case Double:
+      d=_tcstod(psz,&pEnd);
+      rc=(_TCHAR('\0')==*pEnd);
+      if(rc){
+        SetValue(d);
+      }
+      break;
+    case Integer:
+    case Bool:
+    case Char:
+    case Short:
+      l=_tcstol(psz,&pEnd,10);
+      rc=(_TCHAR('\0')==*pEnd);
+      if(rc){
+        SetValue((int)l);
+      }
+      break;
+    default:
+      TRACE(_T("Failed to set '%s' to string value '%s'\n"),(LPCTSTR)strName,psz);
+      break;
+  }
+  return rc;
+}
+