comparison host/tools/Utils/common/Properties.cpp @ 82:6736c52df507 ecos-sw-2000-04-14

Merge from eCos master repository on 2000-04-14-13:35:46-BST
author jlarmour
date Tue, 18 Apr 2000 21:51:55 +0000
parents 435cced73e2f
children e0c0827131d1
comparison
equal deleted inserted replaced
81:89fef2181d7d 82:6736c52df507
24 //####COPYRIGHTEND#### 24 //####COPYRIGHTEND####
25 // Properties.cpp: implementation of the CProperties class. 25 // Properties.cpp: implementation of the CProperties class.
26 // 26 //
27 ////////////////////////////////////////////////////////////////////// 27 //////////////////////////////////////////////////////////////////////
28 #include "Properties.h" 28 #include "Properties.h"
29 #if defined (_AFXDLL) || defined(_AFXEXT) 29 #include "eCosTrace.h"
30 // MFC
31 //#ifdef _DEBUG
32 //#undef THIS_FILE
33 //static char THIS_FILE[]=__FILE__;
34 //#define new DEBUG_NEW
35 //#endif
36 #include <assert.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <direct.h>
40 #endif
41
42 ////////////////////////////////////////////////////////////////////// 30 //////////////////////////////////////////////////////////////////////
43 // Construction/Destruction 31 // Construction/Destruction
44 ////////////////////////////////////////////////////////////////////// 32 //////////////////////////////////////////////////////////////////////
45 33
46 CProperties::CProperties(LPCTSTR pszKey,void *hKey): 34 CProperties::CProperties()
47 m_strName(pszKey),
48 m_hKey(hKey)
49 { 35 {
50 } 36 }
51 37
52 CProperties::~CProperties() 38 CProperties::~CProperties()
53 { 39 {
54 RemoveAll();
55 }
56
57 void CProperties::RemoveAll()
58 {
59 for(int i=ar.size()-1;i>=0;--i){
60 delete (CProperties::CProperty *)ar[i];
61 }
62 ar.clear();
63 } 40 }
64 41
65 #ifdef _WIN32 42 #ifdef _WIN32
66 bool CProperties::LoadFromRegistry(HKEY hTopKey,LPCTSTR szRegKey,LPCTSTR pszPrefix) 43 bool CProperties::LoadFromRegistry(HKEY hTopKey,LPCTSTR szRegKey)
67 { 44 {
68 int nPrefixlen=_tcslen(pszPrefix);
69 HKEY hKey; 45 HKEY hKey;
70 LONG l=RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_QUERY_VALUE, &hKey); 46 LONG l=RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_QUERY_VALUE, &hKey);
71 bool rc=(ERROR_SUCCESS==l); 47 bool rc=(ERROR_SUCCESS==l);
72 if(rc){ 48 if(rc){
73 TCHAR szName[256]; 49 TCHAR szName[256];
76 DWORD dwType; 52 DWORD dwType;
77 if(ERROR_SUCCESS==RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dwMaxDatalen,NULL,NULL)){ 53 if(ERROR_SUCCESS==RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dwMaxDatalen,NULL,NULL)){
78 char *Data=new char[dwMaxDatalen]; 54 char *Data=new char[dwMaxDatalen];
79 DWORD dwDatalen=dwMaxDatalen; 55 DWORD dwDatalen=dwMaxDatalen;
80 for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumValue(hKey, dwIndex, szName, &dwSizeName, NULL, &dwType, (LPBYTE)Data, &dwDatalen);dwIndex++){ 56 for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumValue(hKey, dwIndex, szName, &dwSizeName, NULL, &dwType, (LPBYTE)Data, &dwDatalen);dwIndex++){
81 if(0!=_tcsncmp(pszPrefix,szName,nPrefixlen)){
82 continue;
83 }
84 57
85 CProperties::CProperty *p=Lookup(szName+nPrefixlen); 58 CProperties::CProperty *p=Lookup(szName);
86 if(p){ 59 if(p){
87 switch(p->Type){ 60 switch(p->Type){
88 case CProperty::Integer: 61 case CProperty::Integer:
89 if(REG_DWORD==dwType){ 62 if(REG_DWORD==dwType){
90 p->SetValue(*(int *)Data); 63 p->SetValue(*(int *)Data);
91 } else { 64 } else {
92 //TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType); 65 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
93 rc=false; 66 rc=false;
94 } 67 }
95 break; 68 break;
96 case CProperty::Bool: 69 case CProperty::Bool:
97 if(REG_DWORD==dwType){ 70 if(REG_DWORD==dwType){
98 p->SetValue((bool)0!=*(int *)Data); 71 p->SetValue((bool)0!=*(int *)Data);
99 } else { 72 } else {
100 //TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType); 73 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
101 rc=false; 74 rc=false;
102 } 75 }
103 break; 76 break;
104 case CProperty::Char: 77 case CProperty::Char:
105 if(REG_DWORD==dwType){ 78 if(REG_DWORD==dwType){
106 p->SetValue(*(char *)Data); 79 p->SetValue(*(char *)Data);
107 } else { 80 } else {
108 //TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType); 81 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
109 rc=false; 82 rc=false;
110 } 83 }
111 break; 84 break;
112 case CProperty::Short: 85 case CProperty::Short:
113 if(REG_DWORD==dwType){ 86 if(REG_DWORD==dwType){
114 p->SetValue(*(short *)Data); 87 p->SetValue(*(short *)Data);
115 } else { 88 } else {
116 //TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType); 89 TRACE(_T("Type mismatch - %s: expected REG_DWORD, got %d\n"),(LPCTSTR)p->strName,dwType);
117 rc=false; 90 rc=false;
118 } 91 }
119 break; 92 break;
120 case CProperty::Float: 93 case CProperty::Float:
121 case CProperty::Double: 94 case CProperty::Double:
122 case CProperty::szString: 95 case CProperty::szString:
123 case CProperty::GPString: 96 if(REG_SZ==dwType){
124 if(REG_SZ==dwType){ 97 rc&=p->SetValue((LPCTSTR)Data);
125 rc&=p->SetValue((LPCTSTR)Data); 98 } else {
126 } else { 99 TRACE(_T("Type mismatch - %s: expected REG_SZ, got %d\n"),(LPCTSTR)p->strName,dwType);
127 //TRACE(_T("Type mismatch - %s: expected REG_SZ, got %d\n"),(LPCTSTR)p->strName,dwType); 100 rc=false;
128 rc=false; 101 }
129 } 102 break;
130 break; 103 case CProperty::Void:
131 case CProperty::Void: 104 if(REG_BINARY==dwType){
132 if(REG_BINARY==dwType){ 105 memcpy(p->pData,Data,min(dwDatalen,p->nLength));
133 memcpy(p->pData,Data,min(dwDatalen,p->nLength)); 106 } else {
134 } else { 107 TRACE(_T("Type mismatch - %s: expected REG_BINARY, got %d\n"),(LPCTSTR)p->strName,dwType);
135 //TRACE(_T("Type mismatch - %s: expected REG_BINARY, got %d\n"),(LPCTSTR)p->strName,dwType); 108 rc=false;
136 rc=false; 109 }
137 } 110 break;
138 break;
139 } 111 }
140 } else { 112 } else {
141 //TRACE(_T("CProperties::LoadFromRegistry - unrecognized value %s\\%s\n"),szRegKey,szName); 113 TRACE(_T("CProperties::LoadFromRegistry - unrecognized value %s in key %s\n"),szName,szRegKey);
142 rc=false; 114 rc=false;
143 } 115 }
144 dwSizeName=sizeof szName; 116 dwSizeName=sizeof szName;
145 dwDatalen=dwMaxDatalen; 117 dwDatalen=dwMaxDatalen;
146 } 118 }
147 delete [] Data; 119 delete [] Data;
148 dwSizeName=sizeof szName; 120 dwSizeName=sizeof szName;
149 } 121 }
150 RegCloseKey(hKey); 122 RegCloseKey(hKey);
151 } else { 123 } else {
152 //TRACE(_T("Failed to open %s\n"),szRegKey); 124 TRACE(_T("Failed to open %s\n"),szRegKey);
153 } 125 }
154 126
155 return rc; 127 return rc;
156 } 128 }
157 129
158 bool CProperties::SaveToRegistry(HKEY hTopKey,LPCTSTR szRegKey,LPCTSTR pszPrefix) const 130 bool CProperties::SaveToRegistry(HKEY hTopKey,LPCTSTR szRegKey) const
159 { 131 {
160 HKEY hKey; 132 HKEY hKey;
161 CreateKey(szRegKey); 133 CreateKey(szRegKey);
162 bool rc=(ERROR_SUCCESS==RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_SET_VALUE, &hKey)); 134 bool rc=(ERROR_SUCCESS==RegOpenKeyEx (hTopKey, szRegKey, 0L, KEY_SET_VALUE, &hKey));
163 if(rc){ 135 if(rc){
167 DWORD dwType=REG_DWORD; 139 DWORD dwType=REG_DWORD;
168 BYTE *Data=0; 140 BYTE *Data=0;
169 // strValue and dw *must* be in scope for RegSetValueEx below. 141 // strValue and dw *must* be in scope for RegSetValueEx below.
170 DWORD dw; 142 DWORD dw;
171 String strValue; 143 String strValue;
172 CProperties::CProperty *p=(CProperties::CProperty *)ar[i]; 144 const CProperty &p=ar[i];
173 switch(p->Type){ 145 switch(p.Type){
174 case CProperties::CProperty::Integer: 146 case CProperties::CProperty::Integer:
175 case CProperties::CProperty::Bool: 147 case CProperties::CProperty::Bool:
176 case CProperties::CProperty::Char: 148 case CProperties::CProperty::Char:
177 case CProperties::CProperty::Short: 149 case CProperties::CProperty::Short:
178 dwType=REG_DWORD; 150 dwType=REG_DWORD;
179 dwDatalen=sizeof(DWORD); 151 dwDatalen=sizeof(DWORD);
180 dw=p->GetValue(); 152 dw=p.GetValue();
181 Data=(BYTE *)&dw; 153 Data=(BYTE *)&dw;
182 break; 154 break;
183 case CProperties::CProperty::Float: 155 case CProperties::CProperty::Float:
184 case CProperties::CProperty::Double: 156 case CProperties::CProperty::Double:
185 case CProperties::CProperty::szString: 157 case CProperties::CProperty::szString:
186 case CProperties::CProperty::GPString: 158 strValue=p.GetStringValue();
187 strValue=p->GetStringValue();
188 Data=(BYTE *)(LPCTSTR)strValue; 159 Data=(BYTE *)(LPCTSTR)strValue;
189 dwType=REG_SZ; 160 dwType=REG_SZ;
190 dwDatalen=(1+strValue.GetLength())*sizeof(_TCHAR); 161 dwDatalen=(1+strValue.size())*sizeof(_TCHAR);
191 break; 162 break;
192 case CProperties::CProperty::Void: 163 case CProperties::CProperty::Void:
193 Data=(BYTE *)p->pData; 164 Data=(BYTE *)p.pData;
194 dwType=REG_BINARY; 165 dwType=REG_BINARY;
195 dwDatalen=p->nLength; 166 dwDatalen=p.nLength;
196 break; 167 break;
197 default: 168 default:
198 assert(false); 169 assert(false);
199 break; 170 break;
200 } 171 }
201 String strName(pszPrefix); 172 rc&=(ERROR_SUCCESS==RegSetValueEx(hKey,p.strName,0,dwType,Data,dwDatalen));
202 strName+=p->strName;
203 rc&=(ERROR_SUCCESS==RegSetValueEx(hKey,strName,0,dwType,Data,dwDatalen));
204 } 173 }
205 } 174 }
206 RegCloseKey(hKey); 175 RegCloseKey(hKey);
207 return rc; 176 return rc;
208 } 177 }
209 178
210 // Create all keys down to the one specified 179 // Create all keys down to the one specified
211 bool CProperties::CreateKey(LPCTSTR pszKey,HKEY hKey/*=HKEY_CURRENT_USER*/) 180 bool CProperties::CreateKey(LPCTSTR pszKey,HKEY hKey/*=HKEY_CURRENT_USER*/)
212 { 181 {
213 bool rc=true; 182 bool rc=true;
214 LPCTSTR pcStart=pszKey; 183 LPCTSTR pcStart=pszKey;
215 LPCTSTR pcEnd; 184 LPCTSTR pcEnd;
216 do { 185 do {
217 HKEY hKey2; 186 HKEY hKey2;
218 pcEnd=_tcschr(pcStart,_TCHAR('\\')); 187 pcEnd=_tcschr(pcStart,_TCHAR('\\'));
219 if(NULL==pcEnd){ 188 if(NULL==pcEnd){
220 pcEnd=pcStart+_tcslen(pcStart); 189 pcEnd=pcStart+_tcslen(pcStart);
221 } 190 }
222 String strKey(pcStart,pcEnd-pcStart); 191 String strKey(pcStart,pcEnd-pcStart);
223 if(ERROR_SUCCESS!=RegCreateKeyEx(hKey, // handle to an open key 192 if(ERROR_SUCCESS!=RegCreateKeyEx(hKey, // handle to an open key
224 strKey, // address of subkey name 193 strKey, // address of subkey name
225 0, // reserved 194 0, // reserved
226 0, // address of class string 195 0, // address of class string
227 REG_OPTION_NON_VOLATILE, // special options flag 196 REG_OPTION_NON_VOLATILE, // special options flag
228 KEY_ALL_ACCESS, // desired security access 197 KEY_ALL_ACCESS, // desired security access
229 NULL, 198 NULL,
230 // address of key security structure 199 // address of key security structure
231 &hKey2, // address of buffer for opened handle 200 &hKey2, // address of buffer for opened handle
232 NULL// address of disposition value buffer); 201 NULL// address of disposition value buffer);
233 )){ 202 )){
234 rc=false; 203 rc=false;
235 break; 204 break;
236 } 205 }
237 RegCloseKey(hKey);
238 hKey=hKey2;
239 pcStart=pcEnd+1;
240 } while (_TCHAR('\0')!=*pcEnd);
241 RegCloseKey(hKey); 206 RegCloseKey(hKey);
242 return rc; 207 hKey=hKey2;
208 pcStart=pcEnd+1;
209 } while (_TCHAR('\0')!=*pcEnd);
210 RegCloseKey(hKey);
211 return rc;
243 } 212 }
244 213
245 #endif 214 #endif
246 215
247 bool CProperties::LoadFromCommandString(LPCTSTR psz,LPCTSTR pszPrefix/*=_T("-")*/) 216 bool CProperties::LoadFromCommandString(LPCTSTR psz)
248 { 217 {
249 bool rc=true; 218 bool rc=true;
250 const TCHAR *cNext; 219 const TCHAR *cNext;
251 int nPrefixlen=_tcslen(pszPrefix); 220 for(LPCTSTR c=_tcschr(psz,_TCHAR('-'));c;c=_tcschr(cNext,_TCHAR('-'))){
252 for(LPCTSTR c=_tcsstr(psz,pszPrefix);c;c=_tcsstr(cNext,pszPrefix)){ 221 c++;
253 c+=nPrefixlen;
254 const TCHAR *pEq=_tcschr(c,_TCHAR('=')); 222 const TCHAR *pEq=_tcschr(c,_TCHAR('='));
255 if(NULL==pEq){ 223 if(NULL==pEq){
256 //TRACE(_T("Failed to find '=' after %s\n"),c); 224 TRACE(_T("Failed to find '=' after %s\n"),c);
257 rc=false; 225 rc=false;
258 break; 226 break;
259 } 227 }
260 String strName(c,pEq-c); 228 String strName(c,pEq-c);
261 CProperties::CProperty *p=Lookup(strName); 229 CProperties::CProperty *p=Lookup(strName);
275 str=String(c,cNext-c); 243 str=String(c,cNext-c);
276 } 244 }
277 if(p){ 245 if(p){
278 rc&=p->SetValue(str); 246 rc&=p->SetValue(str);
279 } else { 247 } else {
280 //TRACE(_T("Properties: unrecognized attribute %s in command string\n"),(LPCTSTR)strName); 248 TRACE(_T("Properties: unrecognized attribute %s in command string\n"),(LPCTSTR)strName);
281 rc=false; 249 rc=false;
282 } 250 }
251 c=cNext;
283 } 252 }
284 return rc; 253 return rc;
285 } 254 }
286 255
287 CProperties::CProperty * CProperties::Lookup(LPCTSTR pszName) 256 CProperties::CProperty * CProperties::Lookup(LPCTSTR pszName)
288 { 257 {
289 for(int i=ar.size()-1;i>=0;--i){ 258 for(int i=ar.size()-1;i>=0;--i){
290 CProperties::CProperty *p=(CProperties::CProperty *)ar[i]; 259 CProperties::CProperty &p=ar[i];
291 if(p->strName==pszName){ 260 if(0==_tcsicmp(p.strName,pszName)){
292 return p; 261 return &p;
293 } 262 }
294 } 263 }
295 return NULL; 264 return NULL;
296 } 265 }
297 266
298 String CProperties::MakeCommandString(LPCTSTR pszPrefix/*=_T("-")*/) const 267 String CProperties::MakeCommandString() const
299 { 268 {
300 String strResult; 269 String strResult;
301 bool bFirst=true; 270 bool bFirst=true;
302 for(int i=ar.size()-1;i>=0;--i){ 271 for(int i=ar.size()-1;i>=0;--i){
303 String str; 272 String str;
304 CProperties::CProperty *p=(CProperties::CProperty *)ar[i]; 273 const CProperty &p=ar[i];
305 switch(p->Type){ 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
309 bool 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
337 bool 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
368 bool 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
386 // Check for continuation lines
387 if(_TCHAR('\\')==buf[nLen-1]){
388 buf[--nLen]=_TCHAR('\0');
389 str+=buf;
390 } else {
391 str+=buf;
392 LPCTSTR c=(LPCTSTR)str;
393 const TCHAR *pEq=_tcschr(c,_TCHAR('='));
394 if(pEq){
395 const String strName(c,pEq-c);
396 CProperties::CProperty *p=Lookup(strName);
397 if(p){
398 pEq++;
399 rc&=p->SetValue(pEq);
400 } else {
401 ERROR(_T("Unknown attribute %s found in %s line %d\n"),(LPCTSTR)strName,pszFileName,nLine);
402 rc=false;
403 }
404 }
405 str=_T("");
406 }
407 }
408 }
409 fclose(f);
410 }
411 return rc;
412 }
413
414 CProperties::CProperty::CProperty(LPCTSTR pszName,Typetype type,void *_pData):
415 strName(pszName),
416 Type(type),
417 pData(_pData)
418 {
419 }
420
421 CProperties::CProperty::~CProperty()
422 {
423 }
424
425 void CProperties::Add(LPCTSTR pszName,int &n)
426 {
427 CProperty p(pszName,CProperty::Integer,&n);
428 ar.push_back(p);
429 }
430
431 void CProperties::Add(LPCTSTR pszName,unsigned int &n)
432 {
433 CProperty p(pszName,CProperty::Integer,&n);
434 ar.push_back(p);
435 }
436
437 void CProperties::Add(LPCTSTR pszName,bool &b)
438 {
439 CProperty p(pszName,CProperty::Bool,&b);
440 ar.push_back(p);
441 }
442
443 void CProperties::Add(LPCTSTR pszName,char &c)
444 {
445 CProperty p(pszName,CProperty::Char,&c);
446 ar.push_back(p);
447 }
448
449 void CProperties::Add(LPCTSTR pszName,unsigned char &c)
450 {
451 CProperty p(pszName,CProperty::Char,&c);
452 ar.push_back(p);
453 }
454
455 void CProperties::Add(LPCTSTR pszName,short &s)
456 {
457 CProperty p(pszName,CProperty::Short,&s);
458 ar.push_back(p);
459 }
460
461 void CProperties::Add(LPCTSTR pszName,unsigned short &s)
462 {
463 CProperty p(pszName,CProperty::Short,&s);
464 ar.push_back(p);
465 }
466
467 void CProperties::Add(LPCTSTR pszName,float &f)
468 {
469 CProperty p(pszName,CProperty::Float,&f);
470 ar.push_back(p);
471 }
472
473 void CProperties::Add(LPCTSTR pszName,double &f)
474 {
475 CProperty p(pszName,CProperty::Double,&f);
476 ar.push_back(p);
477 }
478
479 void CProperties::Add(LPCTSTR pszName,void *pv,unsigned int _nLength)
480 {
481 CProperty p(pszName,CProperty::Void,pv);
482 p.nLength=_nLength;
483 ar.push_back(p);
484 }
485
486 void CProperties::Add(LPCTSTR pszName,String &s)
487 {
488 CProperty p(pszName,CProperty::szString,(void *)&s);
489 ar.push_back(p);
490 }
491
492 unsigned long CProperties::CProperty::GetValue() const
493 {
494 unsigned long dw;
495 switch(Type){
496 case Integer:
497 dw=*(int *)pData;
498 break;
499 case Bool:
500 dw=*(bool *)pData;
501 break;
502 case Char:
503 dw=*(char *)pData;
504 break;
505 case Short:
506 dw=*(short *)pData;
507 break;
508 default:
509 dw=0;
510 assert(false);
511 }
512 return dw;
513 }
514
515 const String CProperties::CProperty::GetStringValue() const
516 {
517 String str;
518 switch(Type){
519 case szString:
520 str=*(String *)pData;
521 break;
306 case CProperties::CProperty::Integer: 522 case CProperties::CProperty::Integer:
307 case CProperties::CProperty::Bool: 523 case CProperties::CProperty::Bool:
308 case CProperties::CProperty::Char: 524 case CProperties::CProperty::Char:
309 case CProperties::CProperty::Short: 525 case CProperties::CProperty::Short:
310 str.Format(_T("%s%s=%u"),pszPrefix,(LPCTSTR)p->strName,p->GetValue()); 526 str.Format(_T("%u"),GetValue());
311 break; 527 break;
312 case CProperties::CProperty::szString:
313 case CProperties::CProperty::GPString:
314 case CProperties::CProperty::Float: 528 case CProperties::CProperty::Float:
529 str.Format(_T("%e"),*(float *)(pData));
530 break;
315 case CProperties::CProperty::Double: 531 case CProperties::CProperty::Double:
532 str.Format(_T("%e"),*(double *)(pData));
533 break;
316 case CProperties::CProperty::Void: 534 case CProperties::CProperty::Void:
317 str.Format(_T("%s%s=\"%s\""),pszPrefix,(LPCTSTR)p->strName,(LPCTSTR)p->GetStringValue()); 535 {
318 break; 536 unsigned char *c=(unsigned char *)pData;
319 } 537 for(unsigned int i=0;i<nLength;i++){
320 if(!bFirst){ 538 TCHAR buf[3];
321 strResult+=_TCHAR(' '); 539 _tprintf(buf,_T("%02x"),c[i]);
322 } 540 str+=buf;
323 bFirst=false;
324 strResult+=str;
325 }
326 return strResult;
327 }
328
329 bool CProperties::CreatePathToFile(LPCTSTR pszDir)
330 {
331 // Create intermediate directories
332 #ifdef _WIN32
333 const TCHAR cSep='\\';
334 #else // UNIX
335 const TCHAR cSep='/';
336 #endif
337 for(LPCTSTR c=_tcschr(pszDir,cSep);c;c=_tcschr(c+1,cSep)){
338 #ifdef _WIN32
339 if(c==pszDir+2 && _istalpha(pszDir[0]) && _TCHAR(':')==pszDir[1]){
340 continue; // don't attempt to create "C:"
341 } 541 }
342 #endif 542 }
343 String strDir(pszDir,c-pszDir); 543 break;
344 struct _stat buf; 544 default:
345 if(!(0==_tstat(strDir,&buf) && (S_IFDIR&buf.st_mode))){ 545 break;
346 // Need to create directory 546 }
347 bool b=(0==_tmkdir(strDir)); 547 return str;
348 //TRACE(_T("Create directory %s rc=%d\n"),(LPCTSTR)strDir,b); 548 }
349 if(!b){ 549
350 return false; 550 bool CProperties::CProperty::SetValue(int n)
351 } 551 {
352 } 552 bool rc=true;
353 } 553 switch(Type){
354 return true; 554 case Integer:
355 } 555 *(int *)(pData)=n;
356 556 break;
357 bool CProperties::SaveToFile(LPCTSTR pszFileName,LPCTSTR pszPrefix) const 557 case Bool:
358 { 558 *(bool *)(pData)=(0!=n);
359 CreatePathToFile(pszFileName); 559 break;
360 // If we have a prefix, we assume we're tagging on to an existing file 560 case Char:
361 FILE *f=_tfopen(pszFileName,(_TCHAR('\0')==*pszPrefix)?_T("wt"):_T("at")); 561 *(char *)(pData)=(char)n; //FIXME: range checks
362 if(f){ 562 break;
363 for(int i=ar.size()-1;i>=0;--i){ 563 case Short:
364 CProperties::CProperty *p=(CProperties::CProperty *)ar[i]; 564 *(short *)(pData)=(short)n;//FIXME: range checks
365 String str(pszPrefix); 565 break;
366 str+=p->strName; 566 default:
367 str+=_TCHAR('='); 567 TRACE(_T("Failed to set '%s' to integer value '%d'\n"),(LPCTSTR)strName,n);
368 switch(p->Type){ 568 break;
369 case CProperties::CProperty::Integer:
370 case CProperties::CProperty::Bool:
371 case CProperties::CProperty::Char:
372 case CProperties::CProperty::Short:
373 {
374 String strN;
375 strN.Format(_T("%u"),p->GetValue());
376 str+=strN;
377 }
378 break;
379 case CProperties::CProperty::Float:
380 case CProperties::CProperty::Double:
381 case CProperties::CProperty::szString:
382 case CProperties::CProperty::GPString:
383 case CProperties::CProperty::Void:
384 str+=p->GetStringValue();
385 break;
386 }
387 str+=_TCHAR('\n');
388 _fputts(str,f);
389 }
390 fclose(f);
391 }
392 return (0!=f);
393 }
394
395 bool CProperties::LoadFromFile(LPCTSTR pszFileName,LPCTSTR pszPrefix)
396 {
397 int nPrefixlen=_tcslen(pszPrefix);
398 FILE *f=_tfopen(pszFileName,_T("rt"));
399 bool rc=(0!=f);
400 if(rc){
401 TCHAR c[256];
402 while(_fgetts(c,sizeof(c)-1,f)){
403 if(_TCHAR('\0')!=c[0]){
404 c[_tcslen(c)-1]=_TCHAR('\0'); // remove trailing \n
405 }
406 if((signed)_tcslen(c)>nPrefixlen && 0==_tcsncmp(c,pszPrefix,nPrefixlen)){
407 TCHAR *pEq=_tcschr(c,_TCHAR('='));
408 if(pEq){
409 const String strName(c+nPrefixlen,pEq-c-nPrefixlen);
410 CProperties::CProperty *p=Lookup(strName);
411 if(p){
412 pEq++;
413 rc&=p->SetValue(pEq);
414 } else {
415 //TRACE(_T("Failed to find %s\n"),(LPCTSTR)strName);
416 rc=false;
417 }
418 }
419 }
420 }
421 fclose(f);
422 } 569 }
423 return rc; 570 return rc;
571 }
572
573 bool CProperties::CProperty::SetValue(double n)
574 {
575 bool rc=true;
576 switch(Type){
577 case Double:
578 *(float *)(pData)=(float)n;//FIXME: range checks?
579 break;
580 case Float:
581 *(double *)(pData)=n;
582 break;
583 default:
584 TRACE(_T("Failed to set '%s' to double value '%f'\n"),(LPCTSTR)strName,n);
585 rc=false;
586 break;
587 }
424 588
425 } 589 return rc;
426
427 CProperties::CProperty::CProperty(LPCTSTR pszName,Typetype type,void *_pData):
428 strName(pszName),
429 Type(type),
430 pData(_pData)
431 {
432 }
433
434 CProperties::CProperty::~CProperty()
435 {
436 }
437
438 void CProperties::Add(LPCTSTR pszName,int &n,int _nDefault)
439 {
440 CProperty *p=new CProperty(pszName,CProperty::Integer,&n);
441 p->nDefault=_nDefault;
442 ar.push_back(p);
443 }
444
445 void CProperties::Add(LPCTSTR pszName,unsigned int &n,unsigned int _nDefault)
446 {
447 CProperty *p=new CProperty(pszName,CProperty::Integer,&n);
448 p->nDefault=_nDefault;
449 ar.push_back(p);
450 }
451
452 void CProperties::Add(LPCTSTR pszName,bool &b,bool _bDefault)
453 {
454 CProperty *p=new CProperty(pszName,CProperty::Bool,&b);
455 p->nDefault=_bDefault;
456 ar.push_back(p);
457 }
458
459 void CProperties::Add(LPCTSTR pszName,char &c,char _cDefault)
460 {
461 CProperty *p=new CProperty(pszName,CProperty::Char,&c);
462 p->nDefault=_cDefault;
463 ar.push_back(p);
464 }
465
466 void CProperties::Add(LPCTSTR pszName,unsigned char &c,unsigned char _cDefault)
467 {
468 CProperty *p=new CProperty(pszName,CProperty::Char,&c);
469 p->nDefault=_cDefault;
470 ar.push_back(p);
471 }
472
473 void CProperties::Add(LPCTSTR pszName,short &s,short _sDefault)
474 {
475 CProperty *p=new CProperty(pszName,CProperty::Short,&s);
476 p->nDefault=_sDefault;
477 ar.push_back(p);
478 }
479
480 void CProperties::Add(LPCTSTR pszName,unsigned short &s,unsigned short _sDefault)
481 {
482 CProperty *p=new CProperty(pszName,CProperty::Short,&s);
483 p->nDefault=_sDefault;
484 ar.push_back(p);
485 }
486
487 void CProperties::Add(LPCTSTR pszName,float &f,float _fDefault)
488 {
489 CProperty *p=new CProperty(pszName,CProperty::Float,&f);
490 p->dDefault=_fDefault;
491 ar.push_back(p);
492 }
493
494 void CProperties::Add(LPCTSTR pszName,double &f,double dDefault)
495 {
496 CProperty *p=new CProperty(pszName,CProperty::Double,&f);
497 p->dDefault=dDefault;
498 ar.push_back(p);
499 }
500
501 void CProperties::Add(LPCTSTR pszName,void *pv,unsigned int _nLength,void *pvDefault)
502 {
503 CProperty *p=new CProperty(pszName,CProperty::Void,pv);
504 p->nLength=_nLength;
505 p->pvDefault=pvDefault;
506 ar.push_back(p);
507 }
508
509 void CProperties::Add(LPCTSTR pszName,LPTSTR s,unsigned int _nLength,LPCTSTR _pszDefault)
510 {
511 CProperty *p=new CProperty(pszName,CProperty::szString,s);
512 p->nLength=_nLength;
513 p->strDefault=_pszDefault;
514 ar.push_back(p);
515 }
516
517 void CProperties::Add (LPCTSTR pszName,void *pObj,getFn *getFn,putFn *putFn,LPCTSTR pszDefault)
518 {
519 CProperty *p=new CProperty(pszName,CProperty::GPString,pObj);
520 p->strDefault=pszDefault;
521 p->pgetFn=getFn;
522 p->pputFn=putFn;
523 p->strDefault=pszDefault;
524 ar.push_back(p);
525 }
526
527 unsigned long CProperties::CProperty::GetValue() const
528 {
529 unsigned long dw;
530 switch(Type){
531 case Integer:
532 dw=*(int *)pData;
533 break;
534 case Bool:
535 dw=*(bool *)pData;
536 break;
537 case Char:
538 dw=*(char *)pData;
539 break;
540 case Short:
541 dw=*(short *)pData;
542 break;
543 default:
544 dw=0;
545 assert(false);
546 }
547 return dw;
548 }
549
550 const String CProperties::CProperty::GetStringValue() const
551 {
552 String str;
553 switch(Type){
554 case szString:
555 str=(LPCTSTR)(pData);
556 break;
557 case GPString:
558 str=pgetFn(pData);
559 break;
560 case CProperties::CProperty::Integer:
561 case CProperties::CProperty::Bool:
562 case CProperties::CProperty::Char:
563 case CProperties::CProperty::Short:
564 str.Format(_T("%u"),GetValue());
565 break;
566 case CProperties::CProperty::Float:
567 str.Format(_T("%e"),*(float *)(pData));
568 break;
569 case CProperties::CProperty::Double:
570 str.Format(_T("%e"),*(double *)(pData));
571 break;
572 case CProperties::CProperty::Void:
573 {
574 unsigned char *c=(unsigned char *)pData;
575 for(unsigned int i=0;i<nLength;i++){
576 TCHAR buf[3];
577 _tprintf(buf,_T("%02x"),c[i]);
578 str+=buf;
579 }
580 }
581 break;
582 default:
583 break;
584 }
585 return str;
586 }
587
588 bool CProperties::CProperty::SetValue(int n)
589 {
590 bool rc=true;
591 switch(Type){
592 case Integer:
593 *(int *)(pData)=n;
594 break;
595 case Bool:
596 *(bool *)(pData)=(0!=n);
597 break;
598 case Char:
599 *(char *)(pData)=(char)n; //FIXME: range checks
600 break;
601 case Short:
602 *(short *)(pData)=(short)n;//FIXME: range checks
603 break;
604 default:
605 //TRACE(_T("Failed to set '%s' to integer value '%d'\n"),(LPCTSTR)strName,n);
606 break;
607 }
608 return rc;
609 }
610
611 bool CProperties::CProperty::SetValue(double n)
612 {
613 bool rc=true;
614 switch(Type){
615 case Double:
616 *(float *)(pData)=(float)n;//FIXME: range checks?
617 break;
618 case Float:
619 *(double *)(pData)=n;
620 break;
621 default:
622 //TRACE(_T("Failed to set '%s' to double value '%f'\n"),(LPCTSTR)strName,n);
623 rc=false;
624 break;
625 }
626
627 return rc;
628 } 590 }
629 591
630 bool CProperties::CProperty::SetValue(LPCTSTR psz) 592 bool CProperties::CProperty::SetValue(LPCTSTR psz)
631 { 593 {
632 bool rc=false; 594 bool rc=false;
633 TCHAR *pEnd; 595 TCHAR *pEnd;
634 double d; 596 double d=0.0;
635 long l; 597 long l=0;
636 switch(Type){ 598 switch(Type){
637 case szString: 599 case szString:
638 _tcsncpy((LPTSTR)pData,psz,nLength); 600 *(String *)pData=psz;
639 if(nLength<=_tcslen(psz)){ 601 rc=true;
640 ((LPTSTR)pData)[nLength]=_TCHAR('\0'); 602 break;
641 } 603 case Float:
642 rc=true; 604 d=_tcstod(psz,&pEnd);
643 break; 605 rc=(_TCHAR('\0')==*pEnd);
644 case GPString: 606 if(rc){
645 pputFn(pData,psz); 607 SetValue((float)d);
646 rc=true; 608 }
647 break; 609 break;
648 case Float: 610 case Double:
649 d=_tcstod(psz,&pEnd); 611 d=_tcstod(psz,&pEnd);
650 rc=(_TCHAR('\0')==*pEnd); 612 rc=(_TCHAR('\0')==*pEnd);
651 if(rc){ 613 if(rc){
652 SetValue((float)d); 614 SetValue(d);
653 } 615 }
654 break; 616 break;
655 case Double: 617 case Integer:
656 d=_tcstod(psz,&pEnd); 618 case Bool:
657 rc=(_TCHAR('\0')==*pEnd); 619 case Char:
658 if(rc){ 620 case Short:
659 SetValue(d); 621 l=_tcstol(psz,&pEnd,10);
660 } 622 rc=(_TCHAR('\0')==*pEnd);
661 break; 623 if(rc){
662 case Integer: 624 SetValue((int)l);
663 case Bool: 625 }
664 case Char: 626 break;
665 case Short: 627 default:
666 l=_tcstol(psz,&pEnd,10); 628 TRACE(_T("Failed to set '%s' to string value '%s'\n"),(LPCTSTR)strName,psz);
667 rc=(_TCHAR('\0')==*pEnd); 629 break;
668 if(rc){ 630 }
669 SetValue((int)l); 631 return rc;
670 } 632 }
671 break; 633
672 default:
673 //TRACE(_T("Failed to set '%s' to string value '%s'\n"),(LPCTSTR)strName,psz);
674 break;
675 }
676 return rc;
677 }
678
679 void CProperties::CProperty::SetDefault()
680 {
681 switch(Type){
682 case Bool:
683 case Integer:
684 case Char:
685 case Short:
686 SetValue(nDefault);
687 break;
688 case Float:
689 case Double:
690 SetValue(dDefault);
691 break;
692 case szString:
693 case GPString:
694 SetValue(strDefault);
695 break;
696 case Void:
697 if(pvDefault){
698 memcpy(pData,pvDefault,nLength);
699 }
700 break;
701 default:
702 assert(false);
703 }
704
705 }
706
707 void CProperties::SetDefaults()
708 {
709 for(int i=ar.size()-1;i>=0;--i){
710 ((CProperty*)ar[i])->SetDefault();
711 }
712 }
713
714 bool CProperties::Load(LPCTSTR pszPrefix)
715 {
716 #ifdef _WIN32
717 return m_hKey?LoadFromRegistry((HKEY)m_hKey,m_strName,pszPrefix):LoadFromFile(m_strName,pszPrefix);
718 #else // UNIX
719 return LoadFromFile(m_strName,pszPrefix);
720 #endif
721 }
722
723 bool CProperties::Save(LPCTSTR pszPrefix)
724 {
725 #ifdef _WIN32
726 return m_hKey?SaveToRegistry((HKEY)m_hKey,m_strName,pszPrefix):SaveToFile(m_strName,pszPrefix);
727 #else // UNIX
728 return SaveToFile(m_strName,pszPrefix);
729 #endif
730 }
731 /*
732 bool CProperties::Remove(LPCTSTR pszName)
733 {
734 for(int i=ar.size()-1;i>=0;--i){
735 CProperties::CProperty *p=(CProperties::CProperty *)ar[i];
736 if(p->strName==pszName){
737 delete p;
738 ar.RemoveAt(i);
739 return true;
740 }
741 }
742 return false;
743 }
744 */