source: SVN/cambria/redboot/host/tools/Utils/common/Properties.cpp @ 1

Last change on this file since 1 was 1, checked in by Tim Harvey, 2 years ago

restored latest version of files from server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 16.5 KB
Line 
1//####COPYRIGHTBEGIN####
2//                                                                         
3// ----------------------------------------------------------------------------
4// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5//
6// This program is part of the eCos host tools.
7//
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)
11// any later version.
12//
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
16// more details.
17//
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.
21//
22// ----------------------------------------------------------------------------
23//                                                                         
24//####COPYRIGHTEND####
25// Properties.cpp: implementation of the CProperties class.
26//
27//////////////////////////////////////////////////////////////////////
28#include "Properties.h"
29#include "eCosTrace.h"
30//////////////////////////////////////////////////////////////////////
31// Construction/Destruction
32//////////////////////////////////////////////////////////////////////
33
34CProperties::CProperties()
35{
36}
37
38CProperties::~CProperties()
39{
40}
41
42#ifdef _WIN32
43bool CProperties::LoadFromRegistry(HKEY hTopKey,LPCTSTR szRegKey)
44{
45  HKEY hKey;
46  LONG l=RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_QUERY_VALUE, &hKey);
47  bool rc=(ERROR_SUCCESS==l);
48  if(rc){
49    TCHAR szName[256];
50    DWORD dwSizeName=sizeof szName;
51    DWORD dwMaxDatalen;
52    DWORD dwType;
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++){ 
57       
58        CProperties::CProperty *p=Lookup(szName);
59        if(p){
60          switch(p->Type){
61            case CProperty::Integer:
62              if(REG_DWORD==dwType){
63                p->SetValue(*(int *)Data);
64              } else {
65                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
66                rc=false;
67              }
68              break;
69            case CProperty::Bool:
70              if(REG_DWORD==dwType){
71                p->SetValue((bool)0!=*(int *)Data);
72              } else {
73                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
74                rc=false;
75              }
76              break;
77            case CProperty::Char:
78              if(REG_DWORD==dwType){
79                p->SetValue(*(char *)Data);
80              } else {
81                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
82                rc=false;
83              }
84              break;
85            case CProperty::Short:
86              if(REG_DWORD==dwType){
87                p->SetValue(*(short *)Data);
88              } else {
89                TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
90                rc=false;
91              }
92              break;
93            case CProperty::Float:
94            case CProperty::Double:
95            case CProperty::szString: 
96              if(REG_SZ==dwType){
97                rc&=p->SetValue((LPCTSTR)Data);
98              } else {
99                TRACE(_T("Type mismatch - %s: expected REG_SZ, got %d\n"),(LPCTSTR)p->strName,dwType);
100                rc=false;
101              }
102              break;
103            case CProperty::Void:
104              if(REG_BINARY==dwType){
105                memcpy(p->pData,Data,MIN(dwDatalen,p->nLength));
106              } else {
107                TRACE(_T("Type mismatch - %s: expected REG_BINARY, got %d\n"),(LPCTSTR)p->strName,dwType);
108                rc=false;
109              }
110              break;
111          }
112        } else {
113          TRACE(_T("CProperties::LoadFromRegistry - unrecognized value %s in key %s\n"),szName,szRegKey);
114          rc=false;
115        }
116        dwSizeName=sizeof szName;
117        dwDatalen=dwMaxDatalen;
118      }
119      delete [] Data;
120      dwSizeName=sizeof szName;
121    }
122    RegCloseKey(hKey);
123  } else {
124    TRACE(_T("Failed to open %s\n"),szRegKey);
125  }
126 
127  return rc;
128}
129
130bool CProperties::SaveToRegistry(HKEY hTopKey,LPCTSTR szRegKey) const
131{
132  HKEY hKey;
133  CreateKey(szRegKey);
134  bool rc=(ERROR_SUCCESS==RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_SET_VALUE, &hKey));
135  if(rc){
136    for(int i=ar.size()-1;i>=0;--i){
137      // Initializations are simply to avoid compiler warnings.
138      DWORD dwDatalen=0; 
139      DWORD dwType=REG_DWORD;
140      BYTE *Data=0;
141      // strValue and dw *must* be in scope for RegSetValueEx below.
142      DWORD dw;
143      String strValue;
144      const CProperty &p=ar[i];
145      switch(p.Type){
146        case CProperties::CProperty::Integer:
147        case CProperties::CProperty::Bool:
148        case CProperties::CProperty::Char:
149        case CProperties::CProperty::Short:
150          dwType=REG_DWORD;
151          dwDatalen=sizeof(DWORD);
152          dw=p.GetValue();
153          Data=(BYTE *)&dw;
154          break;
155        case CProperties::CProperty::Float:
156        case CProperties::CProperty::Double:
157        case CProperties::CProperty::szString:
158          strValue=p.GetStringValue();
159          Data=(BYTE *)(LPCTSTR)strValue;
160          dwType=REG_SZ;
161          dwDatalen=(1+strValue.size())*sizeof(_TCHAR);
162          break;
163        case CProperties::CProperty::Void:
164          Data=(BYTE *)p.pData;
165          dwType=REG_BINARY;
166          dwDatalen=p.nLength;
167          break;
168        default:
169          assert(false);
170          break;
171      }
172      rc&=(ERROR_SUCCESS==RegSetValueEx(hKey,p.strName,0,dwType,Data,dwDatalen));
173    }
174  }   
175  RegCloseKey(hKey);
176  return rc;   
177}
178
179// Create all keys down to the one specified
180bool CProperties::CreateKey(LPCTSTR pszKey,HKEY hKey/*=HKEY_CURRENT_USER*/)
181{
182  bool rc=true;
183  LPCTSTR pcStart=pszKey;
184  LPCTSTR pcEnd;
185  do {
186    HKEY hKey2;
187    pcEnd=_tcschr(pcStart,_TCHAR('\\'));
188    if(NULL==pcEnd){
189      pcEnd=pcStart+_tcslen(pcStart);
190    }
191    String strKey(pcStart,pcEnd-pcStart);
192    if(ERROR_SUCCESS!=RegCreateKeyEx(hKey,                // handle to an open key
193      strKey,         // address of subkey name
194      0,           // reserved
195      0,           // address of class string
196      REG_OPTION_NON_VOLATILE,          // special options flag
197      KEY_ALL_ACCESS,        // desired security access
198      NULL,
199      // address of key security structure
200      &hKey2,          // address of buffer for opened handle
201      NULL// address of disposition value buffer);
202      )){
203      rc=false;
204      break;
205    }
206    RegCloseKey(hKey);
207    hKey=hKey2;
208    pcStart=pcEnd+1;
209  } while (_TCHAR('\0')!=*pcEnd);
210  RegCloseKey(hKey);
211  return rc;
212}
213
214#endif
215
216bool CProperties::LoadFromCommandString(LPCTSTR psz)
217{
218  bool rc=true;
219  const TCHAR *cNext;
220  for(LPCTSTR c=_tcschr(psz,_TCHAR('-'));c;c=_tcschr(cNext,_TCHAR('-'))){
221    c++;
222    const TCHAR *pEq=_tcschr(c,_TCHAR('='));
223    if(NULL==pEq){
224      TRACE(_T("Failed to find '=' after %s\n"),c);
225      rc=false;
226      break;
227    }
228    String strName(c,pEq-c);
229    CProperties::CProperty *p=Lookup(strName);
230    c=pEq+1;
231    String str;
232    if(_TCHAR('"')==*c){
233      // Value is a quoted string
234      for(cNext=c+1;_TCHAR('"')!=*cNext;cNext++){
235        if(_TCHAR('\\')==*cNext){
236          cNext++;
237        }
238        str+=*cNext;
239      }
240    } else {
241      // Value is simply terminated by whitespace
242      for(cNext=c;_TCHAR('\0')!=*cNext && !_istspace(*cNext);cNext++);
243      str=String(c,cNext-c);
244    }
245    if(p){
246      rc&=p->SetValue(str);
247    } else {
248      TRACE(_T("Properties: unrecognized attribute %s in command string\n"),(LPCTSTR)strName);
249      rc=false;
250    }
251    c=cNext;
252  }
253  return rc;
254}
255
256CProperties::CProperty * CProperties::Lookup(LPCTSTR pszName)
257{
258  for(int i=ar.size()-1;i>=0;--i){
259    CProperties::CProperty &p=ar[i];
260    if(0==_tcsicmp(p.strName,pszName)){
261      return &p;
262    }
263  }
264  return NULL;
265}
266
267String CProperties::MakeCommandString() const
268{
269  String strResult;
270  bool bFirst=true;
271  for(int i=ar.size()-1;i>=0;--i){
272    String str;   
273    const CProperty &p=ar[i];
274    switch(p.Type){
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());
280        break;
281      case CProperties::CProperty::szString:
282        {
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++){
286            if(_TCHAR('"')==*c){
287              str+=_TCHAR('\\');
288            }
289            str+=*c;
290          }
291          str+=_TCHAR('"');
292        }
293        break;
294      case CProperties::CProperty::Float:
295      case CProperties::CProperty::Double:
296      case CProperties::CProperty::Void:
297        str.Format(_T("-%s=%s"),(LPCTSTR)p.GetStringValue());
298        break;
299    }
300    if(!bFirst){
301      strResult+=_TCHAR(' ');
302    }
303    bFirst=false;
304    strResult+=str;
305  }
306  return strResult;
307}       
308
309bool CProperties::CreatePathToFile(LPCTSTR pszDir) 
310{
311  // Create intermediate directories
312#ifdef _WIN32
313  const TCHAR cSep='\\';
314#else // UNIX
315  const TCHAR cSep='/';
316#endif
317  for(LPCTSTR c=_tcschr(pszDir,cSep);c;c=_tcschr(c+1,cSep)){
318#ifdef _WIN32
319    if(c==pszDir+2 && _istalpha(pszDir[0]) && _TCHAR(':')==pszDir[1]){
320      continue; // don't attempt to create "C:"
321    }
322#endif
323    String strDir(pszDir,c-pszDir);
324    struct _stat buf;
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);
329      if(!b){
330        return false;
331      }
332    }
333  }
334  return true;
335}
336
337bool CProperties::SaveToFile(LPCTSTR pszFileName) const
338{
339  CreatePathToFile(pszFileName);
340  FILE *f=_tfopen(pszFileName,_T("w") MODE_TEXT);
341  if(f){
342    for(int i=ar.size()-1;i>=0;--i){
343      const CProperty &p=ar[i];
344      String str(p.strName);
345      str+=_TCHAR('=');
346      switch(p.Type){
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());
352          break;
353        case CProperties::CProperty::Float:
354        case CProperties::CProperty::Double:
355        case CProperties::CProperty::szString:
356        case CProperties::CProperty::Void:
357          str+=p.GetStringValue();
358          break;
359      }
360      str+=_TCHAR('\n');
361      _fputts(str,f);
362    }
363    fclose(f);
364  }
365  return (0!=f);
366}
367
368bool CProperties::LoadFromFile(LPCTSTR pszFileName)
369{
370  FILE *f=_tfopen(pszFileName,_T("r") MODE_TEXT);
371  bool rc=(0!=f);
372  if(rc){
373    TCHAR buf[4096];
374    int nLine=0;
375    String str;
376    while(_fgetts(buf,sizeof(buf)-1,f)){
377     
378      nLine++;
379      int nLen=_tcslen(buf);
380      if(nLen>0){
381        // Remove trailing '\n'
382        if(_TCHAR('\n')==buf[nLen-1]){
383          buf[--nLen]=_TCHAR('\0');
384        }
385        // Remove trailing '\r'
386        if(_TCHAR('\r')==buf[nLen-1]){
387          buf[--nLen]=_TCHAR('\0');
388        }
389       
390        // Check for continuation lines
391        if(_TCHAR('\\')==buf[nLen-1]){
392          buf[--nLen]=_TCHAR('\0');
393          str+=buf;
394        } else {
395          str+=buf;
396          LPCTSTR c=(LPCTSTR)str;
397          const TCHAR *pEq=_tcschr(c,_TCHAR('='));
398          if(pEq){
399            const String strName(c,pEq-c);
400            CProperties::CProperty *p=Lookup(strName);
401            if(p){
402              pEq++;
403              rc&=p->SetValue(pEq);
404            } else {
405              ERROR(_T("Unknown attribute %s found in %s line %d\n"),(LPCTSTR)strName,pszFileName,nLine);
406              rc=false;
407            }
408          }
409          str=_T("");
410        }
411      }
412    }
413    fclose(f);
414  }
415  return rc;
416}
417
418CProperties::CProperty::CProperty(LPCTSTR pszName,Typetype type,void *_pData):
419  strName(pszName),
420  Type(type),
421  pData(_pData)
422{
423}
424
425CProperties::CProperty::~CProperty()
426{
427}
428
429void CProperties::Add(LPCTSTR pszName,int &n) 
430{
431  CProperty p(pszName,CProperty::Integer,&n);
432  ar.push_back(p);
433}
434
435void CProperties::Add(LPCTSTR pszName,unsigned int &n)
436{
437  CProperty p(pszName,CProperty::Integer,&n);
438  ar.push_back(p);
439}
440
441void CProperties::Add(LPCTSTR pszName,bool &b)
442{
443  CProperty p(pszName,CProperty::Bool,&b);
444  ar.push_back(p);
445}
446
447void CProperties::Add(LPCTSTR pszName,char &c)
448{
449  CProperty p(pszName,CProperty::Char,&c);
450  ar.push_back(p);
451}
452
453void CProperties::Add(LPCTSTR pszName,unsigned char &c)
454{
455  CProperty p(pszName,CProperty::Char,&c);
456  ar.push_back(p);
457}
458
459void CProperties::Add(LPCTSTR pszName,short &s)
460{
461  CProperty p(pszName,CProperty::Short,&s);
462  ar.push_back(p);
463}
464
465void CProperties::Add(LPCTSTR pszName,unsigned short &s)
466{
467  CProperty p(pszName,CProperty::Short,&s);
468  ar.push_back(p);
469}
470
471void CProperties::Add(LPCTSTR pszName,float &f)
472{
473  CProperty p(pszName,CProperty::Float,&f);
474  ar.push_back(p);
475}
476
477void CProperties::Add(LPCTSTR pszName,double &f) 
478{
479  CProperty p(pszName,CProperty::Double,&f);
480  ar.push_back(p);
481}
482
483void CProperties::Add(LPCTSTR pszName,void *pv,unsigned int _nLength)
484{
485  CProperty p(pszName,CProperty::Void,pv);
486  p.nLength=_nLength;
487  ar.push_back(p);
488}
489
490void CProperties::Add(LPCTSTR pszName,String &s)
491{
492  CProperty p(pszName,CProperty::szString,(void *)&s);
493  ar.push_back(p);
494}
495
496unsigned long CProperties::CProperty::GetValue() const
497{
498  unsigned long dw;
499  switch(Type){
500    case Integer:
501      dw=*(int *)pData;
502      break;
503    case Bool:
504      dw=*(bool *)pData;
505      break;
506    case Char:
507      dw=*(char *)pData;
508      break;
509    case Short:
510      dw=*(short *)pData;
511      break;
512    default:
513      dw=0;
514      assert(false);
515  }
516  return dw;
517}
518
519const String CProperties::CProperty::GetStringValue() const 
520{
521  String str;
522  switch(Type){
523    case szString:
524      str=*(String *)pData; 
525      break;
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());
531      break;
532    case CProperties::CProperty::Float:
533      str.Format(_T("%e"),*(float *)(pData));
534      break;
535    case CProperties::CProperty::Double:
536      str.Format(_T("%e"),*(double *)(pData));
537      break;
538    case CProperties::CProperty::Void:
539      {
540        unsigned char *c=(unsigned char *)pData;
541        for(unsigned int i=0;i<nLength;i++){
542          TCHAR buf[3];
543          _tprintf(buf,_T("%02x"),c[i]);
544          str+=buf;
545        }
546      }
547      break;
548    default:
549      break;
550  }
551  return str;
552}
553
554bool CProperties::CProperty::SetValue(int n)
555{
556  bool rc=true;
557  switch(Type){
558    case Integer:
559      *(int *)(pData)=n;
560      break;
561    case Bool:
562      *(bool *)(pData)=(0!=n);
563      break;
564    case Char:
565      *(char *)(pData)=(char)n; //FIXME: range checks
566      break;
567    case Short:
568      *(short *)(pData)=(short)n;//FIXME: range checks
569      break;
570    default:
571      TRACE(_T("Failed to set '%s' to integer value '%d'\n"),(LPCTSTR)strName,n);
572      break;
573  }
574  return rc;
575}
576
577bool CProperties::CProperty::SetValue(double n)
578{
579  bool rc=true;
580  switch(Type){
581    case Double:
582      *(float *)(pData)=(float)n;//FIXME: range checks?
583      break;
584    case Float:
585      *(double *)(pData)=n;
586      break;
587    default:
588      TRACE(_T("Failed to set '%s' to double value '%f'\n"),(LPCTSTR)strName,n);
589      rc=false;
590      break;
591  }
592 
593  return rc;
594}
595
596bool CProperties::CProperty::SetValue(LPCTSTR psz)
597{
598  bool rc=false;
599  TCHAR *pEnd;
600  double d=0.0;
601  long l=0;
602  switch(Type){
603    case szString:
604      *(String *)pData=psz;
605      rc=true;
606      break;
607    case Float:
608      d=_tcstod(psz,&pEnd);
609      rc=(_TCHAR('\0')==*pEnd);
610      if(rc){
611        SetValue((float)d);
612      }
613      break;
614    case Double:
615      d=_tcstod(psz,&pEnd);
616      rc=(_TCHAR('\0')==*pEnd);
617      if(rc){
618        SetValue(d);
619      }
620      break;
621    case Integer:
622    case Bool:
623    case Char:
624    case Short:
625      l=_tcstol(psz,&pEnd,10);
626      rc=(_TCHAR('\0')==*pEnd);
627      if(rc){
628        SetValue((int)l);
629      }
630      break;
631    default:
632      TRACE(_T("Failed to set '%s' to string value '%s'\n"),(LPCTSTR)strName,psz);
633      break;
634  }
635  return rc;
636}
637
Note: See TracBrowser for help on using the repository browser.