Very rough first start, not even everything added

This commit is contained in:
Darren VanBuren 2017-03-07 14:51:44 -08:00
commit af3619d4fa
88 changed files with 24251 additions and 0 deletions

View file

@ -0,0 +1,394 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: FilePrefsSource.cpp
Contains: Implements object defined in FilePrefsSource.h.
Written by: Chris LeCroy
*/
#include "FilePrefsSource.h"
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "MyAssert.h"
#include "OSMemory.h"
#include "ConfParser.h"
const int kMaxLineLen = 2048;
const int kMaxValLen = 1024;
class KeyValuePair
{
public:
char* GetValue() { return fValue; }
private:
friend class FilePrefsSource;
KeyValuePair(const char* inKey, const char* inValue, KeyValuePair* inNext);
~KeyValuePair();
char* fKey;
char* fValue;
KeyValuePair* fNext;
void ResetValue(const char* inValue);
};
KeyValuePair::KeyValuePair(const char* inKey, const char* inValue, KeyValuePair* inNext) :
fKey(NULL),
fValue(NULL),
fNext(NULL)
{
fKey = NEW char[::strlen(inKey)+1];
::strcpy(fKey, inKey);
fValue = NEW char[::strlen(inValue)+1];
::strcpy(fValue, inValue);
fNext = inNext;
}
KeyValuePair::~KeyValuePair()
{
delete [] fKey;
delete [] fValue;
}
void KeyValuePair::ResetValue(const char* inValue)
{
delete [] fValue;
fValue = NEW char[::strlen(inValue)+1];
::strcpy(fValue, inValue);
}
FilePrefsSource::FilePrefsSource( Bool16 allowDuplicates)
: fKeyValueList(NULL),
fNumKeys(0),
fAllowDuplicates(allowDuplicates)
{
}
FilePrefsSource::~FilePrefsSource()
{
while (fKeyValueList != NULL)
{
KeyValuePair* keyValue = fKeyValueList;
fKeyValueList = fKeyValueList->fNext;
delete keyValue;
}
}
int FilePrefsSource::GetValue(const char* inKey, char* ioValue)
{
return (this->FindValue(inKey, ioValue) != NULL);
}
int FilePrefsSource::GetValueByIndex(const char* inKey, UInt32 inIndex, char* ioValue)
{
KeyValuePair* thePair = this->FindValue(inKey, ioValue, inIndex);
if (thePair == NULL)
return false;
return true;
/*
char* valuePtr = thePair->fValue;
//this function makes the assumption that fValue doesn't start with whitespace
Assert(*valuePtr != '\t');
Assert(*valuePtr != ' ');
for (UInt32 count = 0; ((count < inIndex) && (valuePtr != '\0')); count++)
{
//go through all the "words" on this line (delimited by whitespace)
//until we hit the one specified by inIndex
//we aren't at the proper word yet, so skip...
while ((*valuePtr != ' ') && (*valuePtr != '\t') && (*valuePtr != '\0'))
valuePtr++;
//skip over all the whitespace between words
while ((*valuePtr == ' ') || (*valuePtr == '\t'))
valuePtr++;
}
//We've exhausted the data on this line before getting to our pref,
//so return an error.
if (*valuePtr == '\0')
return false;
//if we are here, then valuePtr is pointing to the beginning of the right word
while ((*valuePtr != ' ') && (*valuePtr != '\t') && (*valuePtr != '\0'))
*ioValue++ = *valuePtr++;
*ioValue = '\0';
return true;
*/
}
char* FilePrefsSource::GetValueAtIndex(UInt32 inIndex)
{
// Iterate through the queue until we have the right entry
KeyValuePair* thePair = fKeyValueList;
while ((thePair != NULL) && (inIndex-- > 0))
thePair = thePair->fNext;
if (thePair != NULL)
return thePair->fValue;
return NULL;
}
char* FilePrefsSource::GetKeyAtIndex(UInt32 inIndex)
{
// Iterate through the queue until we have the right entry
KeyValuePair* thePair = fKeyValueList;
while ((thePair != NULL) && (inIndex-- > 0))
thePair = thePair->fNext;
if (thePair != NULL)
return thePair->fKey;
return NULL;
}
void FilePrefsSource::SetValue(const char* inKey, const char* inValue)
{
KeyValuePair* keyValue = NULL;
// If the key/value already exists update the value.
// If duplicate keys are allowed, however, add a new entry regardless
if ((!fAllowDuplicates) && ((keyValue = this->FindValue(inKey, NULL)) != NULL))
{
keyValue->ResetValue(inValue);
}
else
{
fKeyValueList = NEW KeyValuePair(inKey, inValue, fKeyValueList);
fNumKeys++;
}
}
Bool16 FilePrefsSource::FilePrefsConfigSetter( const char* paramName, const char* paramValue[], void* userData )
{
/*
static callback routine for ParseConfigFile
*/
int valueIndex = 0;
FilePrefsSource *theFilePrefs = (FilePrefsSource*)userData;
Assert( theFilePrefs );
Assert( paramName );
// Assert( paramValue[0] );
// multiple values are passed in the paramValue array as distinct strs
while ( paramValue[valueIndex] != NULL )
{
//qtss_printf("Adding config setting <key=\"%s\", value=\"%s\">\n", paramName, paramValue[valueIndex] );
theFilePrefs->SetValue(paramName, paramValue[valueIndex] );
valueIndex++;
}
return false; // always succeeds
}
int FilePrefsSource::InitFromConfigFile(const char* configFilePath)
{
/*
load config from specified file. return non-zero
in the event of significant error(s).
*/
return ::ParseConfigFile( true, configFilePath, FilePrefsConfigSetter, this );
/*
int err = 0;
char bufLine[kMaxLineLen];
char key[kMaxValLen];
char value[kMaxLineLen];
FILE* fileDesc = ::fopen( configFilePath, "r");
if (fileDesc == NULL)
{
// report some problem here...
err = OSThread::GetErrno();
Assert( err );
}
else
{
while (fgets(bufLine, sizeof(bufLine) - 1, fileDesc) != NULL)
{
if (bufLine[0] != '#' && bufLine[0] != '\0')
{
int i = 0;
int n = 0;
while ( bufLine[i] == ' ' || bufLine[i] == '\t')
{ ++i;}
n = 0;
while ( bufLine[i] != ' ' &&
bufLine[i] != '\t' &&
bufLine[i] != '\n' &&
bufLine[i] != '\r' &&
bufLine[i] != '\0' &&
n < (kMaxLineLen - 1) )
{
key[n++] = bufLine[i++];
}
key[n] = '\0';
while (bufLine[i] == ' ' || bufLine[i] == '\t')
{++i;}
n = 0;
while ((bufLine[i] != '\n') && (bufLine[i] != '\0') &&
(bufLine[i] != '\r') && (n < kMaxLineLen - 1))
{
value[n++] = bufLine[i++];
}
value[n] = '\0';
if (key[0] != '#' && key[0] != '\0' && value[0] != '\0')
{
qtss_printf("Adding config setting <key=\"%s\", value=\"%s\">\n", key, value);
this->SetValue(key, value);
}
else
{
//assert(false);
}
}
}
int closeErr = ::fclose(fileDesc);
Assert(closeErr == 0);
}
return err;
*/
}
void FilePrefsSource::DeleteValue(const char* inKey)
{
KeyValuePair* keyValue = fKeyValueList;
KeyValuePair* prevKeyValue = NULL;
while (keyValue != NULL)
{
if (::strcmp(inKey, keyValue->fKey) == 0)
{
if (prevKeyValue != NULL)
{
prevKeyValue->fNext = keyValue->fNext;
delete keyValue;
}
else
{
fKeyValueList = prevKeyValue;
}
return;
}
prevKeyValue = keyValue;
keyValue = keyValue->fNext;
}
}
void FilePrefsSource::WriteToConfigFile(const char* configFilePath)
{
int err = 0;
FILE* fileDesc = ::fopen( configFilePath, "w");
if (fileDesc != NULL)
{
err = ::fseek(fileDesc, 0, SEEK_END);
Assert(err == 0);
KeyValuePair* keyValue = fKeyValueList;
while (keyValue != NULL)
{
(void)qtss_fprintf(fileDesc, "%s %s\n\n", keyValue->fKey, keyValue->fValue);
keyValue = keyValue->fNext;
}
err = ::fclose(fileDesc);
Assert(err == 0);
}
}
KeyValuePair* FilePrefsSource::FindValue(const char* inKey, char* ioValue, UInt32 index )
{
KeyValuePair *keyValue = fKeyValueList;
UInt32 foundIndex = 0;
if ( ioValue != NULL)
ioValue[0] = '\0';
while (keyValue != NULL)
{
if (::strcmp(inKey, keyValue->fKey) == 0)
{
if ( foundIndex == index )
{
if (ioValue != NULL)
::strcpy(ioValue, keyValue->fValue);
return keyValue;
}
foundIndex++;
}
keyValue = keyValue->fNext;
}
return NULL;
}

View file

@ -0,0 +1,76 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: FilePrefsSource.h
Contains: Implements the PrefsSource interface, getting the prefs from a file.
Written by: Chris LeCroy
*/
#ifndef __FILEPREFSSOURCE_H__
#define __FILEPREFSSOURCE_H__
#include "PrefsSource.h"
#include "OSHeaders.h"
class KeyValuePair; //only used in the implementation
class FilePrefsSource : public PrefsSource
{
public:
FilePrefsSource( Bool16 allowDuplicates = false );
virtual ~FilePrefsSource();
virtual int GetValue(const char* inKey, char* ioValue);
virtual int GetValueByIndex(const char* inKey, UInt32 inIndex, char* ioValue);
// Allows caller to iterate over all the values in the file.
char* GetValueAtIndex(UInt32 inIndex);
char* GetKeyAtIndex(UInt32 inIndex);
UInt32 GetNumKeys() { return fNumKeys; }
int InitFromConfigFile(const char* configFilePath);
void WriteToConfigFile(const char* configFilePath);
void SetValue(const char* inKey, const char* inValue);
void DeleteValue(const char* inKey);
private:
static Bool16 FilePrefsConfigSetter( const char* paramName, const char* paramValue[], void* userData );
KeyValuePair* FindValue(const char* inKey, char* ioValue, UInt32 index = 0);
KeyValuePair* fKeyValueList;
UInt32 fNumKeys;
Bool16 fAllowDuplicates;
};
#endif //__FILEPREFSSOURCE_H__

View file

@ -0,0 +1,54 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: PrefsSource.h
Contains: Defines an abstract common interface for extracting prefs
from some data source. Very general, low level
Written by: Denis Serenyi
Change History (most recent first):
*/
#ifndef __PREFSSOURCE_H__
#define __PREFSSOURCE_H__
#include "OSHeaders.h"
class PrefsSource
{
public:
virtual int GetValue(const char* inKey, char* ioValue) = 0;
virtual int GetValueByIndex(const char* inKey, UInt32 inIndex, char* ioValue) = 0;
virtual ~PrefsSource(){};
};
#endif

View file

@ -0,0 +1,692 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef __Win32__
#include <unistd.h>
#endif
#include "XMLParser.h"
#include "OSMemory.h"
XMLParser::XMLParser( char* inPath, DTDVerifier* verifier)
: fRootTag(NULL), fFilePath(NULL)
{
StrPtrLen thePath(inPath);
fFilePath = thePath.GetAsCString();
fFile.Set(inPath);
fVerifier = verifier;
}
XMLParser::~XMLParser()
{
if (fRootTag)
delete fRootTag;
delete [] fFilePath;
}
Bool16 XMLParser::ParseFile(char* errorBuffer, int errorBufferSize)
{
if (fRootTag != NULL)
{
delete fRootTag; // flush old data
fRootTag = NULL;
}
fFile.Set(fFilePath);
if (errorBufferSize < 500) errorBuffer = NULL; // Just a hack to avoid checking everywhere
if ((fFile.GetLength() == 0) || fFile.IsDir())
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "Couldn't read xml file");
return false; // we don't have a valid file;
}
char* fileData = NEW char[ (SInt32) (fFile.GetLength() + 1)];
UInt32 theLengthRead = 0;
fFile.Read(0, fileData, (UInt32) fFile.GetLength(), &theLengthRead);
StrPtrLen theDataPtr(fileData, theLengthRead);
StringParser theParser(&theDataPtr);
fRootTag = NEW XMLTag();
Bool16 result = fRootTag->ParseTag(&theParser, fVerifier, errorBuffer, errorBufferSize);
if (!result)
{
// got error parsing file
delete fRootTag;
fRootTag = NULL;
}
delete fileData;
fFile.Close();
return result;
}
Bool16 XMLParser::DoesFileExist()
{
Bool16 itExists = false;
fFile.Set(fFilePath);
if ((fFile.GetLength() > 0) && (!fFile.IsDir()))
itExists = true;
fFile.Close();
return itExists;
}
Bool16 XMLParser::DoesFileExistAsDirectory()
{
Bool16 itExists = false;
fFile.Set(fFilePath);
if (fFile.IsDir())
itExists = true;
fFile.Close();
return itExists;
}
Bool16 XMLParser::CanWriteFile()
{
//
// First check if it exists for reading
FILE* theFile = ::fopen(fFilePath, "r");
if (theFile == NULL)
return true;
::fclose(theFile);
//
// File exists for reading, check if we can write it
theFile = ::fopen(fFilePath, "a");
if (theFile == NULL)
return false;
//
// We can read and write
::fclose(theFile);
return true;
}
void XMLParser::SetRootTag(XMLTag* tag)
{
if (fRootTag != NULL)
delete fRootTag;
fRootTag = tag;
}
void XMLParser::WriteToFile(char** fileHeader)
{
char theBuffer[8192];
ResizeableStringFormatter formatter(theBuffer, 8192);
//
// Write the file header
for (UInt32 a = 0; fileHeader[a] != NULL; a++)
{
formatter.Put(fileHeader[a]);
formatter.Put(kEOLString);
}
if (fRootTag)
fRootTag->FormatData(&formatter, 0);
//
// New libC code. This seems to work better on Win32
formatter.PutTerminator();
FILE* theFile = ::fopen(fFilePath, "w");
if (theFile == NULL)
return;
qtss_fprintf(theFile, "%s", formatter.GetBufPtr());
::fclose(theFile);
#if __MacOSX__
(void) ::chown(fFilePath,76,80);//owner qtss, group admin
#endif
#ifndef __Win32__
::chmod(fFilePath, S_IRUSR | S_IWUSR | S_IRGRP );
#endif
}
UInt8 XMLTag::sNonNameMask[] =
{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //0-9
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //10-19
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //20-29
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //30-39
1, 1, 1, 1, 1, 0, 0, 1, 0, 0, //40-49 '.' and '-' are name chars
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //50-59 ':' is a name char
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, //60-69 //stop on every character except a letter or number
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89
0, 1, 1, 1, 1, 0, 1, 0, 0, 0, //90-99 '_' is a name char
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, //120-129
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //130-139
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //140-149
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //150-159
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //160-169
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //170-179
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //180-189
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //190-199
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //200-209
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //210-219
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //220-229
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //230-239
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //240-249
1, 1, 1, 1, 1, 1 //250-255
};
XMLTag::XMLTag() :
fTag(NULL),
fValue(NULL),
fElem(NULL)
{ fElem = this;
}
XMLTag::XMLTag(char* tagName) :
fTag(NULL),
fValue(NULL),
fElem(NULL)
{ fElem = this;
StrPtrLen temp(tagName);
fTag = temp.GetAsCString();
}
XMLTag::~XMLTag()
{
if (fTag)
delete fTag;
if (fValue)
delete fValue;
OSQueueElem* elem;
while ((elem = fAttributes.DeQueue()) != NULL)
{
XMLAttribute* attr = (XMLAttribute*)elem->GetEnclosingObject();
delete attr;
}
while ((elem = fEmbeddedTags.DeQueue()) != NULL)
{
XMLTag* tag = (XMLTag*)elem->GetEnclosingObject();
delete tag;
}
if (fElem.IsMemberOfAnyQueue())
fElem.InQueue()->Remove(&fElem); // remove from parent tag
}
void XMLTag::ConsumeIfComment(StringParser* parser)
{
if ((parser->GetDataRemaining() > 2) && ((*parser)[1] == '-') && ((*parser)[2] == '-'))
{
// this is a comment, so skip to end of comment
parser->ConsumeLength(NULL, 2); // skip '--'
// look for -->
while((parser->GetDataRemaining() > 2) && ((parser->PeekFast() != '-') ||
((*parser)[1] != '-') || ((*parser)[2] != '>')))
{
if (parser->PeekFast() == '-') parser->ConsumeLength(NULL, 1);
parser->ConsumeUntil(NULL, '-');
}
if (parser->GetDataRemaining() > 2) parser->ConsumeLength(NULL, 3); // consume -->
}
}
bool XMLTag::ParseTag(StringParser* parser, DTDVerifier* verifier, char* errorBuffer, int errorBufferSize)
{
while (true)
{
if (!parser->GetThru(NULL, '<'))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "Couldn't find a valid tag");
return false; // couldn't find beginning of tag
}
char c = parser->PeekFast();
if (c == '/')
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "End tag with no begin tag on line %d", parser->GetCurrentLineNumber());
return false; // we shouldn't be seeing a close tag here
}
if ((c != '!') && (c != '?'))
break; // this should be the beginning of a regular tag
ConsumeIfComment(parser);
// otherwise this is a processing instruction or a c-data, so look for the next tag
}
int tagStartLine = parser->GetCurrentLineNumber();
StrPtrLen temp;
parser->ConsumeUntil(&temp, sNonNameMask);
if (temp.Len == 0)
{
if (errorBuffer != NULL)
{
if (parser->GetDataRemaining() == 0)
qtss_snprintf(errorBuffer, errorBufferSize, "Unexpected end of file on line %d", parser->GetCurrentLineNumber());
else
qtss_snprintf(errorBuffer, errorBufferSize,"Unexpected character (%c) on line %d", parser->PeekFast(), parser->GetCurrentLineNumber());
}
return false; // bad file
}
fTag = temp.GetAsCString();
parser->ConsumeWhitespace();
while ((parser->PeekFast() != '>') && (parser->PeekFast() != '/'))
{
// we must have an attribute value for this tag
XMLAttribute* attr = new XMLAttribute;
fAttributes.EnQueue(&attr->fElem);
parser->ConsumeUntil(&temp, sNonNameMask);
if (temp.Len == 0)
{
if (errorBuffer != NULL)
{
if (parser->GetDataRemaining() == 0)
qtss_snprintf(errorBuffer, errorBufferSize, "Unexpected end of file on line %d", parser->GetCurrentLineNumber());
else
qtss_snprintf(errorBuffer, errorBufferSize,"Unexpected character (%c) on line %d", parser->PeekFast(), parser->GetCurrentLineNumber());
}
return false; // bad file
}
attr->fAttrName = temp.GetAsCString();
if (!parser->Expect('='))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"Missing '=' after attribute %s on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
if (!parser->Expect('"'))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"Attribute %s value not in quotes on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
parser->ConsumeUntil(&temp, '"');
attr->fAttrValue = temp.GetAsCString();
if (!parser->Expect('"'))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "Attribute %s value not in quotes on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
if (verifier && !verifier->IsValidAttributeName(fTag, attr->fAttrName))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "Attribute %s not allowed in tag %s on line %d", attr->fAttrName, fTag, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
if (verifier && !verifier->IsValidAttributeValue(fTag, attr->fAttrName, attr->fAttrValue))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"Bad value for attribute %s on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
parser->ConsumeWhitespace();
}
if (parser->PeekFast() == '/')
{
// this is an empty element tag, i.e. no contents or end tag (e.g <TAG attr="value" />
parser->Expect('/');
if (!parser->Expect('>'))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"'>' must follow '/' on line %d", parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
return true; // we're done with this tag
}
if (!parser->Expect('>'))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"Bad format for tag <%s> on line %d", fTag, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
while(true)
{
parser->ConsumeUntil(&temp, '<'); // this is either value or whitespace
if (parser->GetDataRemaining() < 4)
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "Reached end of file without end for tag <%s> declared on line %d", fTag, tagStartLine);
return false;
}
if ((*parser)[1] == '/')
{
// we'll only assign a value if there were no embedded tags
if (fEmbeddedTags.GetLength() == 0 && (!verifier || verifier->CanHaveValue(fTag)))
fValue = temp.GetAsCString();
else
{
// otherwise this needs to have been just whitespace
StringParser tempParser(&temp);
tempParser.ConsumeWhitespace();
if (tempParser.GetDataRemaining() > 0)
{
if (errorBuffer)
{
if (fEmbeddedTags.GetLength() > 0)
qtss_snprintf(errorBuffer, errorBufferSize,"Unexpected text outside of tag on line %d", tagStartLine);
else
qtss_snprintf(errorBuffer, errorBufferSize, "Tag <%s> on line %d not allowed to have data", fTag, tagStartLine);
}
}
}
break; // we're all done with this tag
}
if (((*parser)[1] != '!') && ((*parser)[1] != '?'))
{
// this must be the beginning of an embedded tag
XMLTag* tag = NEW XMLTag();
fEmbeddedTags.EnQueue(&tag->fElem);
if (!tag->ParseTag(parser, verifier, errorBuffer, errorBufferSize))
return false;
if (verifier && !verifier->IsValidSubtag(fTag, tag->GetTagName()))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize, "Tag %s not allowed in tag %s on line %d", tag->GetTagName(), fTag, parser->GetCurrentLineNumber());
return false; // bad attribute specification
}
}
else
{
parser->ConsumeLength(NULL, 1); // skip '<'
ConsumeIfComment(parser);
}
}
parser->ConsumeLength(NULL, 2); // skip '</'
parser->ConsumeUntil(&temp, sNonNameMask);
if (!temp.Equal(fTag))
{
char* newTag = temp.GetAsCString();
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"End tag </%s> on line %d doesn't match tag <%s> declared on line %d", newTag, parser->GetCurrentLineNumber(),fTag, tagStartLine);
delete newTag;
return false; // bad attribute specification
}
if (!parser->GetThru(NULL, '>'))
{
if (errorBuffer != NULL)
qtss_snprintf(errorBuffer, errorBufferSize,"Couldn't find end of tag <%s> declared on line %d", fTag, tagStartLine);
return false; // bad attribute specification
}
return true;
}
char* XMLTag::GetAttributeValue(const char* attrName)
{
for (OSQueueIter iter(&fAttributes); !iter.IsDone(); iter.Next())
{
XMLAttribute* attr = (XMLAttribute*)iter.GetCurrent()->GetEnclosingObject();
if (!strcmp(attr->fAttrName, attrName))
return attr->fAttrValue;
}
return NULL;
}
XMLTag* XMLTag::GetEmbeddedTag(const UInt32 index)
{
if (fEmbeddedTags.GetLength() <= index)
return NULL;
OSQueueIter iter(&fEmbeddedTags);
for (UInt32 i = 0; i < index; i++)
{
iter.Next();
}
OSQueueElem* result = iter.GetCurrent();
return (XMLTag*)result->GetEnclosingObject();
}
XMLTag* XMLTag::GetEmbeddedTagByName(const char* tagName, const UInt32 index)
{
if (fEmbeddedTags.GetLength() <= index)
return NULL;
XMLTag* result = NULL;
UInt32 curIndex = 0;
for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
{
XMLTag* temp = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
if (!strcmp(temp->GetTagName(), tagName))
{
if (curIndex == index)
{
result = temp;
break;
}
curIndex++;
}
}
return result;
}
XMLTag* XMLTag::GetEmbeddedTagByAttr(const char* attrName, const char* attrValue, const UInt32 index)
{
if (fEmbeddedTags.GetLength() <= index)
return NULL;
XMLTag* result = NULL;
UInt32 curIndex = 0;
for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
{
XMLTag* temp = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
if ((temp->GetAttributeValue(attrName) != NULL) && (!strcmp(temp->GetAttributeValue(attrName), attrValue)))
{
if (curIndex == index)
{
result = temp;
break;
}
curIndex++;
}
}
return result;
}
XMLTag* XMLTag::GetEmbeddedTagByNameAndAttr(const char* tagName, const char* attrName, const char* attrValue, const UInt32 index)
{
if (fEmbeddedTags.GetLength() <= index)
return NULL;
XMLTag* result = NULL;
UInt32 curIndex = 0;
for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
{
XMLTag* temp = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
if (!strcmp(temp->GetTagName(), tagName) && (temp->GetAttributeValue(attrName) != NULL) &&
(!strcmp(temp->GetAttributeValue(attrName), attrValue)))
{
if (curIndex == index)
{
result = temp;
break;
}
curIndex++;
}
}
return result;
}
void XMLTag::AddAttribute( char* attrName, char* attrValue)
{
XMLAttribute* attr = NEW XMLAttribute;
StrPtrLen temp(attrName);
attr->fAttrName = temp.GetAsCString();
temp.Set(attrValue);
attr->fAttrValue = temp.GetAsCString();
fAttributes.EnQueue(&attr->fElem);
}
void XMLTag::RemoveAttribute(char* attrName)
{
for (OSQueueIter iter(&fAttributes); !iter.IsDone(); iter.Next())
{
XMLAttribute* attr = (XMLAttribute*)iter.GetCurrent()->GetEnclosingObject();
if (!strcmp(attr->fAttrName, attrName))
{
fAttributes.Remove(&attr->fElem);
delete attr;
return;
}
}
}
void XMLTag::AddEmbeddedTag(XMLTag* tag)
{
fEmbeddedTags.EnQueue(&tag->fElem);
}
void XMLTag::RemoveEmbeddedTag(XMLTag* tag)
{
fEmbeddedTags.Remove(&tag->fElem);
}
void XMLTag::SetTagName( char* name)
{
Assert (name != NULL); // can't have a tag without a name!
if (fTag != NULL)
delete fTag;
StrPtrLen temp(name);
fTag = temp.GetAsCString();
}
void XMLTag::SetValue( char* value)
{
if (fEmbeddedTags.GetLength() > 0)
return; // can't have a value with embedded tags
if (fValue != NULL)
delete fValue;
if (value == NULL)
fValue = NULL;
else
{
StrPtrLen temp(value);
fValue = temp.GetAsCString();
}
}
void XMLTag::FormatData(ResizeableStringFormatter* formatter, UInt32 indent)
{
for (UInt32 i=0; i<indent; i++) formatter->PutChar('\t');
formatter->PutChar('<');
formatter->Put(fTag);
if (fAttributes.GetLength() > 0)
{
formatter->PutChar(' ');
for (OSQueueIter iter(&fAttributes); !iter.IsDone(); iter.Next())
{
XMLAttribute* attr = (XMLAttribute*)iter.GetCurrent()->GetEnclosingObject();
formatter->Put(attr->fAttrName);
formatter->Put("=\"");
formatter->Put(attr->fAttrValue);
formatter->Put("\" ");
}
}
formatter->PutChar('>');
if (fEmbeddedTags.GetLength() == 0)
{
if (fValue > 0)
formatter->Put(fValue);
}
else
{
formatter->Put(kEOLString);
for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
{
XMLTag* current = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
current->FormatData(formatter, indent + 1);
}
for (UInt32 i=0; i<indent; i++) formatter->PutChar('\t');
}
formatter->Put("</");
formatter->Put(fTag);
formatter->PutChar('>');
formatter->Put(kEOLString);
}
XMLAttribute::XMLAttribute()
: fAttrName(NULL),
fAttrValue(NULL)
{ fElem = this;
}
XMLAttribute::~XMLAttribute()
{
if (fAttrName)
delete fAttrName;
if (fAttrValue)
delete fAttrValue;
}

126
PrefsSourceLib/XMLParser.h Normal file
View file

@ -0,0 +1,126 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
#ifndef __XMLParser_h__
#define __XMLParser_h__
#include "StringParser.h"
#include "OSQueue.h"
#include "OSFileSource.h"
#include "ResizeableStringFormatter.h"
class DTDVerifier
{
public:
virtual bool IsValidSubtag(char* tagName, char* subTagName) = 0;
virtual bool IsValidAttributeName(char* tagName, char* attrName) = 0;
virtual bool IsValidAttributeValue(char* tagName, char* attrName, char* attrValue) = 0;
virtual char* GetRequiredAttribute(char* tagName, int index) = 0;
virtual bool CanHaveValue(char* tagName) = 0;
virtual ~DTDVerifier(){};
};
class XMLTag
{
public:
XMLTag();
XMLTag(char* tagName);
~XMLTag();
bool ParseTag(StringParser* parser, DTDVerifier* verifier, char* errorBuffer = NULL, int errorBufferSize = 0);
char* GetAttributeValue(const char* attrName);
char* GetValue() { return fValue; }
char* GetTagName() { return fTag; }
UInt32 GetNumEmbeddedTags() { return fEmbeddedTags.GetLength(); }
XMLTag* GetEmbeddedTag(const UInt32 index = 0);
XMLTag* GetEmbeddedTagByName(const char* tagName, const UInt32 index = 0);
XMLTag* GetEmbeddedTagByAttr(const char* attrName, const char* attrValue, const UInt32 index = 0);
XMLTag* GetEmbeddedTagByNameAndAttr(const char* tagName, const char* attrName, const char* attrValue, const UInt32 index = 0);
void AddAttribute(char* attrName, char* attrValue);
void RemoveAttribute(char* attrName);
void AddEmbeddedTag(XMLTag* tag);
void RemoveEmbeddedTag(XMLTag* tag);
void SetTagName( char* name);
void SetValue( char* value);
void FormatData(ResizeableStringFormatter* formatter, UInt32 indent);
private:
void ConsumeIfComment(StringParser* parser);
char* fTag;
char* fValue;
OSQueue fAttributes;
OSQueue fEmbeddedTags;
OSQueueElem fElem;
static UInt8 sNonNameMask[]; // stop when you hit a word
};
class XMLAttribute
{
public:
XMLAttribute();
~XMLAttribute();
char* fAttrName;
char* fAttrValue;
OSQueueElem fElem;
};
class XMLParser
{
public:
XMLParser( char* inPath, DTDVerifier* verifier = NULL);
~XMLParser();
// Check for existence, man.
Bool16 DoesFileExist();
Bool16 DoesFileExistAsDirectory();
Bool16 CanWriteFile();
Bool16 ParseFile(char* errorBuffer = NULL, int errorBufferSize = 0);
XMLTag* GetRootTag() { return fRootTag; }
void SetRootTag(XMLTag* tag);
void WriteToFile(char** fileHeader);
private:
XMLTag* fRootTag;
OSFileSource fFile;
char* fFilePath;
DTDVerifier* fVerifier;
};
#endif

View file

@ -0,0 +1,410 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: XMLPrefsParser.cpp
Contains: Prototype implementation of XMLPrefsParser object.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef __Win32__
#include <unistd.h>
#endif
#include "XMLPrefsParser.h"
#include "OSMemory.h"
#include "OSHeaders.h"
static const UInt32 kPrefArrayMinSize = 20;
static char* kMainTag = "CONFIGURATION";
static char* kServer = "SERVER";
static char* kModule = "MODULE";
static char* kPref = "PREF";
static char* kListPref = "LIST-PREF";
static char* kEmptyObject = "EMPTY-OBJECT";
static char* kObject = "OBJECT";
static char* kObjectList = "LIST-OBJECT";
static char* kValue = "VALUE";
static char* kNameAttr = "NAME";
static char* kTypeAttr = "TYPE";
static char* kFileHeader[] =
{
"<?xml version =\"1.0\"?>",
"<!-- The Document Type Definition (DTD) for the file -->",
"<!DOCTYPE CONFIGURATION [",
"<!ELEMENT CONFIGURATION (SERVER, MODULE*)>",
"<!ELEMENT SERVER (PREF|LIST-PREF|OBJECT|LIST-OBJECT)*>",
"<!ELEMENT MODULE (PREF|LIST-PREF|OBJECT|LIST-OBJECT)*>",
"<!ATTLIST MODULE",
"\tNAME CDATA #REQUIRED>",
"<!ELEMENT PREF (#PCDATA)>",
"<!ATTLIST PREF",
"\tNAME CDATA #REQUIRED",
"\tTYPE (UInt8|SInt8|UInt16|SInt16|UInt32|SInt32|UInt64|SInt64|Float32|Float64|Bool16|Bool8|char) \"char\">",
"<!ELEMENT LIST-PREF (VALUE*)>",
"<!ELEMENT VALUE (#PCDATA)>",
"<!ATTLIST LIST-PREF",
"\tNAME CDATA #REQUIRED",
"\tTYPE (UInt8|SInt8|UInt16|SInt16|UInt32|SInt32|UInt64|SInt64|Float32|Float64|Bool16|Bool8|char) \"char\">",
"<!ELEMENT OBJECT (PREF|LIST-PREF|OBJECT|LIST-OBJECT)*>",
"<!ATTLIST OBJECT",
"\tNAME CDATA #REQUIRED>",
"<!ELEMENT LIST-OBJECT (OBJECT-VALUE*)>",
"<!ELEMENT OBJECT-VALUE (PREF|LIST-PREF|OBJECT|LIST-OBJECT)*>",
"<!ATTLIST LIST-OBJECT",
"\tNAME CDATA #REQUIRED>",
"]>",
NULL
};
XMLPrefsParser::XMLPrefsParser(char* inPath)
: XMLParser(inPath)
{}
XMLPrefsParser::~XMLPrefsParser()
{}
ContainerRef XMLPrefsParser::GetConfigurationTag()
{
ContainerRef result = GetRootTag();
if (result == NULL)
{
result = new XMLTag(kMainTag);
SetRootTag(result);
}
return result;
}
ContainerRef XMLPrefsParser::GetRefForModule(char* inModuleName, Bool16 create)
{
if (inModuleName == NULL)
return GetRefForServer();
ContainerRef result = GetConfigurationTag()->GetEmbeddedTagByNameAndAttr(kModule, kNameAttr, inModuleName);
if (result == NULL)
{
result = new XMLTag(kModule);
result->AddAttribute( kNameAttr, (char*)inModuleName);
GetRootTag()->AddEmbeddedTag(result);
}
return result;
}
ContainerRef XMLPrefsParser::GetRefForServer()
{
ContainerRef result = GetConfigurationTag()->GetEmbeddedTagByName(kServer);
if (result == NULL)
{
result = new XMLTag(kServer);
GetRootTag()->AddEmbeddedTag(result);
}
return result;
}
UInt32 XMLPrefsParser::GetNumPrefValues(ContainerRef pref)
{
if (!strcmp(pref->GetTagName(), kPref))
{
if (pref->GetValue() == NULL)
return 0;
else
return 1;
}
else if (!strcmp(pref->GetTagName(), kObject))
return 1;
else if (!strcmp(pref->GetTagName(), kEmptyObject))
return 0;
return pref->GetNumEmbeddedTags(); // it must be a list
}
UInt32 XMLPrefsParser::GetNumPrefsByContainer(ContainerRef container)
{
return container->GetNumEmbeddedTags();
}
char* XMLPrefsParser::GetPrefValueByIndex(ContainerRef container, const UInt32 inPrefsIndex, const UInt32 inValueIndex,
char** outPrefName, char** outDataType)
{
if (outPrefName != NULL)
*outPrefName = NULL;
if (outPrefName != NULL)
*outDataType = NULL;
XMLTag* pref = container->GetEmbeddedTag(inPrefsIndex);
if (pref == NULL)
return NULL;
return GetPrefValueByRef(pref, inValueIndex, outPrefName, outDataType);
}
char* XMLPrefsParser::GetPrefValueByRef(ContainerRef pref, const UInt32 inValueIndex,
char** outPrefName, char** outDataType)
{
if (outPrefName != NULL)
*outPrefName = pref->GetAttributeValue(kNameAttr);
if (outDataType != NULL)
{
*outDataType = pref->GetAttributeValue(kTypeAttr);
if (*outDataType == NULL)
*outDataType = "CharArray";
}
if (!strcmp(pref->GetTagName(), kPref))
{
if (inValueIndex > 0)
return NULL;
else
return pref->GetValue();
}
if (!strcmp(pref->GetTagName(), kListPref))
{
XMLTag* value = pref->GetEmbeddedTag(inValueIndex);
if (value != NULL)
return value->GetValue();
}
if (!strcmp(pref->GetTagName(), kObject) || !strcmp(pref->GetTagName(), kObjectList))
*outDataType = "QTSS_Object";
return NULL;
}
ContainerRef XMLPrefsParser::GetObjectValue(ContainerRef pref, const UInt32 inValueIndex)
{
if (!strcmp(pref->GetTagName(), kObject) && (inValueIndex == 0))
return pref;
if (!strcmp(pref->GetTagName(), kObjectList))
return pref->GetEmbeddedTag(inValueIndex);
return NULL;
}
ContainerRef XMLPrefsParser::GetPrefRefByName( ContainerRef container,
const char* inPrefName)
{
return container->GetEmbeddedTagByAttr(kNameAttr, inPrefName);
}
ContainerRef XMLPrefsParser::GetPrefRefByIndex( ContainerRef container,
const UInt32 inPrefsIndex)
{
return container->GetEmbeddedTag(inPrefsIndex);
}
ContainerRef XMLPrefsParser::AddPref( ContainerRef container, char* inPrefName,
char* inPrefDataType )
{
XMLTag* pref = container->GetEmbeddedTagByAttr(kNameAttr, inPrefName);
if (pref != NULL)
return pref; // it already exists
pref = NEW XMLTag(kPref); // start it out as a pref
pref->AddAttribute(kNameAttr, inPrefName);
if (!strcmp(inPrefDataType, "QTSS_Object"))
pref->SetTagName(kEmptyObject);
else if (strcmp(inPrefDataType, "CharArray"))
pref->AddAttribute(kTypeAttr, (char*)inPrefDataType);
container->AddEmbeddedTag(pref);
return pref;
}
void XMLPrefsParser::AddPrefValue( ContainerRef pref, char* inNewValue)
{
if (!strcmp(pref->GetTagName(), kPref)) // is this a PREF tag
{
if (pref->GetValue() == NULL)
{
// easy case, no existing value, so just add a vlue
pref->SetValue(inNewValue);
return;
}
else
{
// it already has a value, so change the pref to be a list pref and go to code below
char* firstValue = pref->GetValue();
XMLTag* value = NEW XMLTag(kValue);
value->SetValue(firstValue);
pref->SetTagName(kListPref);
pref->SetValue(NULL);
pref->AddEmbeddedTag(value);
}
}
// we want to fall through from second case above, so this isn't an else
if (!strcmp(pref->GetTagName(), kListPref))
{
XMLTag* value = NEW XMLTag(kValue);
value->SetValue(inNewValue);
pref->AddEmbeddedTag(value);
}
}
void XMLPrefsParser::AddNewObject( ContainerRef pref )
{
if (!strcmp(pref->GetTagName(), kEmptyObject))
{
// just flag that this is now a real object instead of a placeholder
pref->SetTagName(kObject);
return;
}
if (!strcmp(pref->GetTagName(), kObject))
{
// change the object to be an object list and go to code below
XMLTag* subObject = NEW XMLTag(kObject);
XMLTag* objectPref;
// copy all this objects tags into the new listed object
while((objectPref = pref->GetEmbeddedTag()) != NULL)
{
pref->RemoveEmbeddedTag(objectPref);
subObject->AddEmbeddedTag(objectPref);
}
pref->SetTagName(kObjectList);
pref->AddEmbeddedTag(subObject);
}
// we want to fall through from second case above, so this isn't an else
if (!strcmp(pref->GetTagName(), kObjectList))
{
XMLTag* subObject = NEW XMLTag(kObject);
pref->AddEmbeddedTag(subObject);
}
}
void XMLPrefsParser::ChangePrefType( ContainerRef pref, char* inNewPrefDataType)
{
pref->RemoveAttribute(kTypeAttr); // remove it if it exists
if (strcmp(inNewPrefDataType, "CharArray"))
pref->AddAttribute(kTypeAttr, inNewPrefDataType);
}
void XMLPrefsParser::SetPrefValue( ContainerRef pref, const UInt32 inValueIndex,
char* inNewValue)
{
UInt32 numValues = GetNumPrefValues(pref);
if (((numValues == 0) || (numValues == 1)) && (inValueIndex == 0))
{
pref->SetValue(inNewValue);
}
else if (inValueIndex == numValues) // this is an additional value
AddPrefValue(pref, inNewValue);
else
{
XMLTag* value = pref->GetEmbeddedTag(inValueIndex);
if (value != NULL)
value->SetValue(inNewValue);
}
}
void XMLPrefsParser::RemovePrefValue( ContainerRef pref, const UInt32 inValueIndex)
{
UInt32 numValues = GetNumPrefValues(pref);
if (inValueIndex >= numValues)
return;
if (numValues == 1)
{
delete pref; // just remove the whole pref
}
else if (numValues == 2)
{
XMLTag* value = pref->GetEmbeddedTag(inValueIndex); // get the one we're removing
delete value; // delete it
value = pref->GetEmbeddedTag(0); // get the remaining tag index always 0 for 2 vals
pref->RemoveEmbeddedTag(value); // pull it out of the parent
if (!strcmp(pref->GetTagName(), kObjectList))
{
pref->SetTagName(kObject); // set it back to a simple pref
// move all this objects tags into the parent
XMLTag* objectPref;
while((objectPref = value->GetEmbeddedTag()) != NULL)
{
value->RemoveEmbeddedTag(objectPref);
pref->AddEmbeddedTag(objectPref);
}
}
else
{
char* temp = value->GetValue();
pref->SetTagName(kPref); // set it back to a simple pref
pref->SetValue(temp);
}
delete value; // get rid of the other one
}
else
{
XMLTag* value = pref->GetEmbeddedTag(inValueIndex);
if (value)
delete value;
}
}
void XMLPrefsParser::RemovePref( ContainerRef pref )
{
delete pref;
}
int XMLPrefsParser::Parse()
{
char error[500];
if (!ParseFile(error, sizeof(error)))
{
qtss_printf("%s\n", error);
return -1;
}
// the above routine checks that it's a valid XML file, we should check that
// all the tags conform to our prefs format
return 0;
}
int XMLPrefsParser::WritePrefsFile()
{
GetConfigurationTag(); // force it to be created if it doesn't exist
WriteToFile(kFileHeader);
return 0;
}

View file

@ -0,0 +1,122 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: XMLPrefsParser.h
Contains: A generic interface for pulling prefs.
*/
#ifndef __XML_PREFS_PARSER__
#define __XML_PREFS_PARSER__
#include "OSFileSource.h"
#include "OSQueue.h"
#include "StringParser.h"
#include "XMLParser.h"
typedef XMLTag* ContainerRef;
class XMLPrefsParser : public XMLParser
{
public:
XMLPrefsParser(char* inPath);
~XMLPrefsParser();
//
// Check for existence, man.
//
// PARSE & WRITE THE FILE. Returns true if there was an error
int Parse();
// Completely replaces old prefs file. Returns true if there was an error
int WritePrefsFile();
//
// ACCESSORS
ContainerRef GetRefForModule( char* inModuleName, Bool16 create = true);
ContainerRef GetRefForServer();
//
// Returns the number of pref values for the pref at this index
UInt32 GetNumPrefValues(ContainerRef pref);
//
// Returns the number of prefs associated with this given module
UInt32 GetNumPrefsByContainer(ContainerRef container);
//
// Returns the pref value at the specfied location
char* GetPrefValueByIndex(ContainerRef container, const UInt32 inPrefsIndex, const UInt32 inValueIndex,
char** outPrefName, char** outDataType);
char* GetPrefValueByRef(ContainerRef pref, const UInt32 inValueIndex,
char** outPrefName, char** outDataType);
ContainerRef GetObjectValue(ContainerRef pref, const UInt32 inValueIndex);
ContainerRef GetPrefRefByName( ContainerRef container,
const char* inPrefName);
ContainerRef GetPrefRefByIndex( ContainerRef container,
const UInt32 inPrefsIndex);
//
// MODIFIERS
//
// Creates a new pref. Returns the index of that pref. If pref already
// exists, returns existing index.
ContainerRef AddPref( ContainerRef container, char* inPrefName, char* inPrefDataType );
void ChangePrefType( ContainerRef pref, char* inNewPrefDataType);
void AddNewObject( ContainerRef pref );
void AddPrefValue( ContainerRef pref, char* inNewValue);
//
// If this value index does not exist yet, and it is one higher than
// the highest one, this function implictly adds the new value.
void SetPrefValue( ContainerRef pref, const UInt32 inValueIndex,
char* inNewValue);
//
// Removes the pref entirely if # of values drops to 0
void RemovePrefValue( ContainerRef pref, const UInt32 inValueIndex);
void RemovePref( ContainerRef pref );
private:
XMLTag* GetConfigurationTag();
};
#endif //__XML_PREFS_PARSER__