1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
25 // Properties.cpp: implementation of the CProperties class.
27 //////////////////////////////////////////////////////////////////////
28 #include "Properties.h"
29 #include "eCosTrace.h"
30 //////////////////////////////////////////////////////////////////////
31 // Construction/Destruction
32 //////////////////////////////////////////////////////////////////////
34 CProperties::CProperties()
38 CProperties::~CProperties()
43 bool CProperties::LoadFromRegistry(HKEY hTopKey,LPCTSTR szRegKey)
46 LONG l=RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_QUERY_VALUE, &hKey);
47 bool rc=(ERROR_SUCCESS==l);
50 DWORD dwSizeName=sizeof szName;
53 if(ERROR_SUCCESS==RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dwMaxDatalen,NULL,NULL)){
54 char *Data=new char[dwMaxDatalen];
55 DWORD dwDatalen=dwMaxDatalen;
56 for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumValue(hKey, dwIndex, szName, &dwSizeName, NULL, &dwType, (LPBYTE)Data, &dwDatalen);dwIndex++){
58 CProperties::CProperty *p=Lookup(szName);
61 case CProperty::Integer:
62 if(REG_DWORD==dwType){
63 p->SetValue(*(int *)Data);
65 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
70 if(REG_DWORD==dwType){
71 p->SetValue((bool)0!=*(int *)Data);
73 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
78 if(REG_DWORD==dwType){
79 p->SetValue(*(char *)Data);
81 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
85 case CProperty::Short:
86 if(REG_DWORD==dwType){
87 p->SetValue(*(short *)Data);
89 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
93 case CProperty::Float:
94 case CProperty::Double:
95 case CProperty::szString:
97 rc&=p->SetValue((LPCTSTR)Data);
99 TRACE(_T("Type mismatch - %s: expected REG_SZ, got %d\n"),(LPCTSTR)p->strName,dwType);
103 case CProperty::Void:
104 if(REG_BINARY==dwType){
105 memcpy(p->pData,Data,MIN(dwDatalen,p->nLength));
107 TRACE(_T("Type mismatch - %s: expected REG_BINARY, got %d\n"),(LPCTSTR)p->strName,dwType);
113 TRACE(_T("CProperties::LoadFromRegistry - unrecognized value %s in key %s\n"),szName,szRegKey);
116 dwSizeName=sizeof szName;
117 dwDatalen=dwMaxDatalen;
120 dwSizeName=sizeof szName;
124 TRACE(_T("Failed to open %s\n"),szRegKey);
130 bool CProperties::SaveToRegistry(HKEY hTopKey,LPCTSTR szRegKey) const
134 bool rc=(ERROR_SUCCESS==RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_SET_VALUE, &hKey));
136 for(int i=ar.size()-1;i>=0;--i){
137 // Initializations are simply to avoid compiler warnings.
139 DWORD dwType=REG_DWORD;
141 // strValue and dw *must* be in scope for RegSetValueEx below.
144 const CProperty &p=ar[i];
146 case CProperties::CProperty::Integer:
147 case CProperties::CProperty::Bool:
148 case CProperties::CProperty::Char:
149 case CProperties::CProperty::Short:
151 dwDatalen=sizeof(DWORD);
155 case CProperties::CProperty::Float:
156 case CProperties::CProperty::Double:
157 case CProperties::CProperty::szString:
158 strValue=p.GetStringValue();
159 Data=(BYTE *)(LPCTSTR)strValue;
161 dwDatalen=(1+strValue.size())*sizeof(_TCHAR);
163 case CProperties::CProperty::Void:
164 Data=(BYTE *)p.pData;
172 rc&=(ERROR_SUCCESS==RegSetValueEx(hKey,p.strName,0,dwType,Data,dwDatalen));
179 // Create all keys down to the one specified
180 bool CProperties::CreateKey(LPCTSTR pszKey,HKEY hKey/*=HKEY_CURRENT_USER*/)
183 LPCTSTR pcStart=pszKey;
187 pcEnd=_tcschr(pcStart,_TCHAR('\\'));
189 pcEnd=pcStart+_tcslen(pcStart);
191 String strKey(pcStart,pcEnd-pcStart);
192 if(ERROR_SUCCESS!=RegCreateKeyEx(hKey, // handle to an open key
193 strKey, // address of subkey name
195 0, // address of class string
196 REG_OPTION_NON_VOLATILE, // special options flag
197 KEY_ALL_ACCESS, // desired security access
199 // address of key security structure
200 &hKey2, // address of buffer for opened handle
201 NULL// address of disposition value buffer);
209 } while (_TCHAR('\0')!=*pcEnd);
216 bool CProperties::LoadFromCommandString(LPCTSTR psz)
220 for(LPCTSTR c=_tcschr(psz,_TCHAR('-'));c;c=_tcschr(cNext,_TCHAR('-'))){
222 const TCHAR *pEq=_tcschr(c,_TCHAR('='));
224 TRACE(_T("Failed to find '=' after %s\n"),c);
228 String strName(c,pEq-c);
229 CProperties::CProperty *p=Lookup(strName);
233 // Value is a quoted string
234 for(cNext=c+1;_TCHAR('"')!=*cNext;cNext++){
235 if(_TCHAR('\\')==*cNext){
241 // Value is simply terminated by whitespace
242 for(cNext=c;_TCHAR('\0')!=*cNext && !_istspace(*cNext);cNext++);
243 str=String(c,cNext-c);
246 rc&=p->SetValue(str);
248 TRACE(_T("Properties: unrecognized attribute %s in command string\n"),(LPCTSTR)strName);
256 CProperties::CProperty * CProperties::Lookup(LPCTSTR pszName)
258 for(int i=ar.size()-1;i>=0;--i){
259 CProperties::CProperty &p=ar[i];
260 if(0==_tcsicmp(p.strName,pszName)){
267 String CProperties::MakeCommandString() const
271 for(int i=ar.size()-1;i>=0;--i){
273 const CProperty &p=ar[i];
275 case CProperties::CProperty::Integer:
276 case CProperties::CProperty::Bool:
277 case CProperties::CProperty::Char:
278 case CProperties::CProperty::Short:
279 str.Format(_T("-%s=%u"),(LPCTSTR)p.strName,p.GetValue());
281 case CProperties::CProperty::szString:
283 // Quote the string, escaping existing quotes as necessary
284 str.Format(_T("-%s=\""),(LPCTSTR)p.strName);
285 for(LPCTSTR c=p.GetStringValue();*c;c++){
294 case CProperties::CProperty::Float:
295 case CProperties::CProperty::Double:
296 case CProperties::CProperty::Void:
297 str.Format(_T("-%s=%s"),(LPCTSTR)p.GetStringValue());
301 strResult+=_TCHAR(' ');
309 bool CProperties::CreatePathToFile(LPCTSTR pszDir)
311 // Create intermediate directories
313 const TCHAR cSep='\\';
315 const TCHAR cSep='/';
317 for(LPCTSTR c=_tcschr(pszDir,cSep);c;c=_tcschr(c+1,cSep)){
319 if(c==pszDir+2 && _istalpha(pszDir[0]) && _TCHAR(':')==pszDir[1]){
320 continue; // don't attempt to create "C:"
323 String strDir(pszDir,c-pszDir);
325 if(!(0==_tstat(strDir,&buf) && (S_IFDIR&buf.st_mode))){
326 // Need to create directory
327 bool b=(0==_tmkdir(strDir));
328 TRACE(_T("Create directory %s rc=%d\n"),(LPCTSTR)strDir,b);
337 bool CProperties::SaveToFile(LPCTSTR pszFileName) const
339 CreatePathToFile(pszFileName);
340 FILE *f=_tfopen(pszFileName,_T("w") MODE_TEXT);
342 for(int i=ar.size()-1;i>=0;--i){
343 const CProperty &p=ar[i];
344 String str(p.strName);
347 case CProperties::CProperty::Integer:
348 case CProperties::CProperty::Bool:
349 case CProperties::CProperty::Char:
350 case CProperties::CProperty::Short:
351 str+=String::SFormat(_T("%u"),p.GetValue());
353 case CProperties::CProperty::Float:
354 case CProperties::CProperty::Double:
355 case CProperties::CProperty::szString:
356 case CProperties::CProperty::Void:
357 str+=p.GetStringValue();
368 bool CProperties::LoadFromFile(LPCTSTR pszFileName)
370 FILE *f=_tfopen(pszFileName,_T("r") MODE_TEXT);
376 while(_fgetts(buf,sizeof(buf)-1,f)){
379 int nLen=_tcslen(buf);
381 // Remove trailing '\n'
382 if(_TCHAR('\n')==buf[nLen-1]){
383 buf[--nLen]=_TCHAR('\0');
385 // Remove trailing '\r'
386 if(_TCHAR('\r')==buf[nLen-1]){
387 buf[--nLen]=_TCHAR('\0');
390 // Check for continuation lines
391 if(_TCHAR('\\')==buf[nLen-1]){
392 buf[--nLen]=_TCHAR('\0');
396 LPCTSTR c=(LPCTSTR)str;
397 const TCHAR *pEq=_tcschr(c,_TCHAR('='));
399 const String strName(c,pEq-c);
400 CProperties::CProperty *p=Lookup(strName);
403 rc&=p->SetValue(pEq);
405 ERROR(_T("Unknown attribute %s found in %s line %d\n"),(LPCTSTR)strName,pszFileName,nLine);
418 CProperties::CProperty::CProperty(LPCTSTR pszName,Typetype type,void *_pData):
425 CProperties::CProperty::~CProperty()
429 void CProperties::Add(LPCTSTR pszName,int &n)
431 CProperty p(pszName,CProperty::Integer,&n);
435 void CProperties::Add(LPCTSTR pszName,unsigned int &n)
437 CProperty p(pszName,CProperty::Integer,&n);
441 void CProperties::Add(LPCTSTR pszName,bool &b)
443 CProperty p(pszName,CProperty::Bool,&b);
447 void CProperties::Add(LPCTSTR pszName,char &c)
449 CProperty p(pszName,CProperty::Char,&c);
453 void CProperties::Add(LPCTSTR pszName,unsigned char &c)
455 CProperty p(pszName,CProperty::Char,&c);
459 void CProperties::Add(LPCTSTR pszName,short &s)
461 CProperty p(pszName,CProperty::Short,&s);
465 void CProperties::Add(LPCTSTR pszName,unsigned short &s)
467 CProperty p(pszName,CProperty::Short,&s);
471 void CProperties::Add(LPCTSTR pszName,float &f)
473 CProperty p(pszName,CProperty::Float,&f);
477 void CProperties::Add(LPCTSTR pszName,double &f)
479 CProperty p(pszName,CProperty::Double,&f);
483 void CProperties::Add(LPCTSTR pszName,void *pv,unsigned int _nLength)
485 CProperty p(pszName,CProperty::Void,pv);
490 void CProperties::Add(LPCTSTR pszName,String &s)
492 CProperty p(pszName,CProperty::szString,(void *)&s);
496 unsigned long CProperties::CProperty::GetValue() const
519 const String CProperties::CProperty::GetStringValue() const
524 str=*(String *)pData;
526 case CProperties::CProperty::Integer:
527 case CProperties::CProperty::Bool:
528 case CProperties::CProperty::Char:
529 case CProperties::CProperty::Short:
530 str.Format(_T("%u"),GetValue());
532 case CProperties::CProperty::Float:
533 str.Format(_T("%e"),*(float *)(pData));
535 case CProperties::CProperty::Double:
536 str.Format(_T("%e"),*(double *)(pData));
538 case CProperties::CProperty::Void:
540 unsigned char *c=(unsigned char *)pData;
541 for(unsigned int i=0;i<nLength;i++){
543 _tprintf(buf,_T("%02x"),c[i]);
554 bool CProperties::CProperty::SetValue(int n)
562 *(bool *)(pData)=(0!=n);
565 *(char *)(pData)=(char)n; //FIXME: range checks
568 *(short *)(pData)=(short)n;//FIXME: range checks
571 TRACE(_T("Failed to set '%s' to integer value '%d'\n"),(LPCTSTR)strName,n);
577 bool CProperties::CProperty::SetValue(double n)
582 *(float *)(pData)=(float)n;//FIXME: range checks?
585 *(double *)(pData)=n;
588 TRACE(_T("Failed to set '%s' to double value '%f'\n"),(LPCTSTR)strName,n);
596 bool CProperties::CProperty::SetValue(LPCTSTR psz)
604 *(String *)pData=psz;
608 d=_tcstod(psz,&pEnd);
609 rc=(_TCHAR('\0')==*pEnd);
615 d=_tcstod(psz,&pEnd);
616 rc=(_TCHAR('\0')==*pEnd);
625 l=_tcstol(psz,&pEnd,10);
626 rc=(_TCHAR('\0')==*pEnd);
632 TRACE(_T("Failed to set '%s' to string value '%s'\n"),(LPCTSTR)strName,psz);