diff -r 000000000000 -r f58d6ec98e88 cdlcompilertoolkit/src/CdlTkUtil.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdlcompilertoolkit/src/CdlTkUtil.cpp Thu Dec 17 09:14:18 2009 +0200 @@ -0,0 +1,561 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ +#include "CdlTkPriv.h" + +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +namespace CdlCompilerToolkit { + +// +// CdlCompilerToolkitErr +// + +CdlCompilerToolkitErr::~CdlCompilerToolkitErr() + { + } + + +// +// CCdlTkFileCleanup +// + +CCdlTkFileCleanup::CCdlTkFileCleanup() +: iName("") + { + } + +CCdlTkFileCleanup::CCdlTkFileCleanup(const std::string& aName) +: iName(aName) + { + } + +CCdlTkFileCleanup::~CCdlTkFileCleanup() + { + Cleanup(); + } + +void CCdlTkFileCleanup::Set(const string& aName) + { + iName = aName; + } + +void CCdlTkFileCleanup::Cleanup() + { + if (!iName.empty()) + CdlTkUtil::DeleteFile(iName); + Release(); + } + +string CCdlTkFileCleanup::Name() const + { + return iName; + } + +void CCdlTkFileCleanup::Release() + { + iName.erase(); + } + + +// +// CdlTkAssert +// + +CdlTkAssert::CdlTkAssert(const string& aText) +: iText(aText) + { + } + +void CdlTkAssert::Show(ostream& stream) const + { + stream << "Cdl Compiler Toolkit assertion failed : " << iText << endl; + } + + +// +// CdlTkFileOpenErr +// + +CdlTkFileOpenErr::CdlTkFileOpenErr(const string& aFileName) : iFileName(aFileName) + { + } + +void CdlTkFileOpenErr::Show(ostream& stream) const + { + stream << endl; + stream << iFileName << " failed to open" << endl; + } + + +// +// CdlTkUtil +// + +string CdlTkUtil::CurrentDrive() + { + static string drive = "?:"; + if (drive == "?:") + drive[0] = 'A' + _getdrive() - 1; + return drive; + } + +string CdlTkUtil::CurrentDir() + { + static string dir = ""; + if (dir == "") + { + char buf[256]; + dir = _getcwd(buf, 255) + 2; // +2 removes drive + dir += "\\"; + } + return dir; + } + +static string gOutputPath = ""; + +string CdlTkUtil::OutputPath() + { + if (gOutputPath == "") + gOutputPath = CurrentDir(); + return gOutputPath; + } + +void CdlTkUtil::SetOutputPath(const string& aPath) + { + gOutputPath = aPath; + if (gOutputPath.size() == 0) + gOutputPath += ".\\"; + else if (gOutputPath[gOutputPath.size()-1] != '\\') + gOutputPath += "\\"; // CDL Tk convention is that paths always end in \ + } + +string CdlTkUtil::ToLower(const string& aString) + { + string r; + r.resize(aString.size()); + transform(aString.begin(), aString.end(), r.begin(), tolower); + return r; + } + +string CdlTkUtil::ToUpper(const string& aString) + { + string r; + r.resize(aString.size()); + transform(aString.begin(), aString.end(), r.begin(), toupper); + return r; + } + +string CdlTkUtil::ToCpp(const string& aString) + { + string r = aString; + for (string::iterator pC = r.begin(); pC != r.end(); ++pC) + { + if (!CdlTkUtil::IsCpp(*pC)) + *pC = '_'; + } + if (r.empty() || CdlTkUtil::IsNumeric(r[0])) + r = string("_") + r; + return r; + } + +string CdlTkUtil::StripPath(const string& aPath) + { + return aPath.substr(aPath.rfind('\\')+1); + } + +string CdlTkUtil::ResolvePath(const string& aPath, const string& aFileName) + { + int size = aFileName.size(); + // if aFileName is absolute, return it + if (size > 0 && aFileName[0] == '\\' || size > 1 && aFileName[1] == ':') + return aFileName; + + string path = aPath; + string file = aFileName; + + // while file starts with a '.', chop file head directory and path tail directory if necessary + while (file.size() > 0 && file[0]=='.') + { + // if file starts with a "..", chop the tail directory off the path + if (file.size() > 1 && file[1]=='.' && !path.empty()) + { + path.resize(path.size()-1); // remove the last slash + path.resize(path.rfind('\\')+1); // remove everything after the next last slash + } + + // chop the head directory off the file - it has to have a '\' if it has a '.' + int fileSlashPos = file.find('\\'); + if (fileSlashPos == string::npos) + throw CdlTkAssert("Illegal filename"); + file = file.substr(fileSlashPos + 1); + } + + // join remaining path and file + return path + file; + } + +string CdlTkUtil::CapitalizeFilename(const string& aString) + { + // convert the whole thing to lower case + string res = ToLower(aString); + // find the first character after the last \ - will be 0 if no \ is present. + int filenamePos = res.find_last_of('\\') + 1; + if (filenamePos >= res.size()) + throw CdlTkAssert(aString + " has no filename"); + // uppercase the first character + res[filenamePos] = toupper(res[filenamePos]); + cerr << "Warning, filename capitalized: " << res << endl; + return res; + } + +string CdlTkUtil::CorrectFilenameCase(const string& aString) + { + // The current standard is to set the filename and path to lower case. + return ToLower(aString); + } + +string CdlTkUtil::Replace(const string& aTarget, const string& aWith, const string& aIn) + { + string ret; + int pos=0; + int lastMatch = 0; + int targetMatch = 0; + int targetSize = aTarget.size(); + int inSize = aIn.size(); + while (pos < inSize) + { + if (aTarget[targetMatch] == aIn[pos++]) + { + ++targetMatch; + if (targetMatch == targetSize) + { + AppendString(ret, aIn.substr(lastMatch, pos - targetMatch - lastMatch)); + AppendString(ret, aWith); + lastMatch = pos; + targetMatch = 0; + } + } + else + { + targetMatch = 0; + } + } + AppendString(ret, aIn.substr(lastMatch)); + return ret; + } + +void CdlTkUtil::ExportFile(CCdlTkFileCleanup& aSourceFile, const string& aExport, ios_base::openmode aOpenMode) + { + if (!FilesAreIdentical(aSourceFile.Name(), aExport, aOpenMode)) + { + CopyFile(aSourceFile.Name(), aExport, aOpenMode); + } + aSourceFile.Cleanup(); + } + +void CdlTkUtil::ExportFileIfWritable(CCdlTkFileCleanup& aSourceFile, const string& aExport, ios_base::openmode aOpenMode) + { + if (!FilesAreIdentical(aSourceFile.Name(), aExport, aOpenMode)) + { + try + { + CopyFile(aSourceFile.Name(), aExport, aOpenMode); + } + catch (const CdlTkFileOpenErr& /*e*/) + { + cerr << "Could not write to " << aExport << endl; + } + } + aSourceFile.Cleanup(); + } + +void CdlTkUtil::DeleteFile(const std::string& aFileName) + { + remove(aFileName.c_str()); + } + +void CdlTkUtil::CopyFile(const std::string& aSourceFileName, const std::string& aDestinationFileName, ios_base::openmode aOpenMode) + { + ifstream from; + OpenInput(from, aSourceFileName, aOpenMode); + ofstream to; + OpenOutput(to, aDestinationFileName, aOpenMode); + + const int KSize = 1024; + char buf[KSize+1]; + while (!from.eof()) + { + from.read(buf,KSize); + to.write(buf, from.gcount()); + } + + from.close(); + to.close(); + } + +bool CdlTkUtil::FilesAreIdentical(const std::string& aLeftFileName, const std::string& aRightFileName, ios_base::openmode aOpenMode) + { + bool different = false; + ifstream leftFile(aLeftFileName.c_str(), aOpenMode); + ifstream rightFile(aRightFileName.c_str(), aOpenMode); + + const int KSize = 1024; + char left[KSize+1]; + char right[KSize+1]; + + while (!leftFile.eof() && !rightFile.eof()) + { + int gotLeft = leftFile.read(left,KSize).gcount(); + int gotRight = rightFile.read(right,KSize).gcount(); + + if (gotLeft != gotRight || memcmp(left, right, gotLeft) != 0) + { + different = true; + break; + } + } + + if (leftFile.eof() != rightFile.eof()) + different = true; + + leftFile.close(); + rightFile.close(); + + return !different; + } + +void CdlTkUtil::OpenTempOutput(ofstream& aStream, CCdlTkFileCleanup& aFile, ios_base::openmode aOpenMode) + { + char tmpName[256]; + if (!tmpnam(tmpName)) + { + throw CdlTkAssert("Can't create temporary file name"); + } + + OpenOutput(aStream, tmpName, aOpenMode); + aFile.Set(tmpName); + } + +void CdlTkUtil::OpenOutput(ofstream& aStream, const string& aFileName, ios_base::openmode aOpenMode) + { + aStream.open(aFileName.c_str(), aOpenMode); + if (!aStream.is_open()) + { + throw CdlTkFileOpenErr(aFileName); + } + } + +void CdlTkUtil::OpenInput(ifstream& aStream, const string& aFileName, ios_base::openmode aOpenMode) + { + aStream.open(aFileName.c_str(), aOpenMode); + if (!aStream.is_open()) + throw CdlTkFileOpenErr(aFileName); + } + +int CdlTkUtil::ParseInt(const string& aInt) + { + int base = 10; + if (aInt.size() > 1 && aInt[0] == '0') + { + base = 8; + if (aInt[1] == 'x') + base = 16; + } + + int val = 0; + stringstream s(aInt); + s >> setbase(base) >> val; + return val; + } + +string CdlTkUtil::IntToString(int aInt) + { + stringstream s; + s << aInt; + return s.str(); + } + +string CdlTkUtil::IntToHexString(int aInt) + { + stringstream s; + s << "0x" << setw(8) << setfill('0') << hex << aInt; + return s.str(); + } + +char* gHexDigits = "0123456789abcdef"; +string CdlTkUtil::ShortToHexString(short aInt) + { + char s[7] = "0x0000"; + s[2]=gHexDigits[(aInt>>12)&0xf]; + s[3]=gHexDigits[(aInt>>8)&0xf]; + s[4]=gHexDigits[(aInt>>4)&0xf]; + s[5]=gHexDigits[aInt&0xf]; + return s; + } + +string CdlTkUtil::CharToHexString(char aInt) + { + char s[5] = "0x00"; + s[2]=gHexDigits[(aInt>>4)&0xf]; + s[3]=gHexDigits[aInt&0xf]; + return s; + } + +void CdlTkUtil::StripLeadingAndTrailingWhitespace(string& aStr) + { + int pos = aStr.find_first_not_of(KWhiteSpace); + if (pos == string::npos) + { + aStr = KEmptyString; + } + else + { + aStr = aStr.substr(pos, aStr.find_last_not_of(KWhiteSpace) + 1 - pos); + } + } + +bool CdlTkUtil::IsAlpha(char aChar) + { + return ('A' <= aChar && aChar <= 'Z') || ('a' <= aChar && aChar <= 'z'); + } + +bool CdlTkUtil::IsNumeric(char aChar) + { + return '0' <= aChar && aChar <= '9'; + } + +bool CdlTkUtil::IsCpp(char aChar) + { + return IsAlpha(aChar) || IsNumeric(aChar) || aChar == '_'; + } + +void ZeroInts(int* aInts, int aCount) + { + for (int ii=0; ii