--- /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 <string>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+#include <direct.h>
+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<aCount; ii++)
+ aInts[ii] = 0;
+ }
+
+string CdlTkUtil::MultiReplace(const CReplaceSet& aSet, const string& aIn)
+ {
+ string ret;
+ int setCount = aSet.size();
+ int* match = new int[setCount];
+ if (!match)
+ throw bad_alloc();
+ ZeroInts(match, setCount);
+
+ int inSize = aIn.size();
+ int pos = 0;
+ int lastMatch = 0;
+ while (pos < inSize)
+ {
+ char ch = aIn[pos++];
+ for (int ii=0; ii<setCount; ii++)
+ {
+ const string& target = aSet[ii].first;
+ int& targetMatch = match[ii];
+ if (target[targetMatch] == ch)
+ {
+ ++targetMatch;
+ if (targetMatch == target.size())
+ {
+ AppendString(ret, aIn.substr(lastMatch, pos - targetMatch - lastMatch));
+ AppendString(ret, aSet[ii].second);
+ lastMatch = pos;
+ ZeroInts(match, setCount);
+ }
+ }
+ else
+ {
+ match[ii] = 0;
+ }
+ }
+ }
+ AppendString(ret, aIn.substr(lastMatch));
+
+ delete[] match;
+ return ret;
+ }
+
+void CdlTkUtil::AppendString(string& aTarget, const string& aAppend)
+ {
+ int resSize = aTarget.size() + aAppend.size();
+ if (aTarget.capacity() < resSize)
+ aTarget.reserve(resSize*2);
+ aTarget.append(aAppend);
+ }
+
+static string gCommandLine = "";
+
+string CdlTkUtil::CommandLine()
+ {
+ return gCommandLine;
+ }
+
+void CdlTkUtil::SetCommandLine(int argc, char* argv[])
+ {
+ string tool(argv[0]);
+ tool = tool.substr(tool.find_last_of('\\') + 1);
+ gCommandLine = tool.substr(0, tool.find_last_of('.'));
+ for (int ii=1; ii<argc; ii++)
+ {
+ AppendString(gCommandLine, " ");
+ AppendString(gCommandLine, argv[ii]);
+ }
+ }
+
+//
+// CdlTkUtil::CReplaceSet
+//
+
+void CdlTkUtil::CReplaceSet::Add(const string& aTarget, const string& aWith)
+ {
+ push_back(make_pair(aTarget, aWith));
+ }
+
+void CdlTkUtil::ReadFile(std::string& aContent, const std::string& aFileName)
+ {
+ ifstream in;
+ OpenInput(in, aFileName);
+ aContent.erase();
+ const int KChars = 1024 + 1;
+ char buf[KChars];
+ while (!in.eof())
+ {
+ in.get(buf,KChars,0);
+ AppendString(aContent, buf);
+ }
+ in.close();
+ }
+
+void CdlTkUtil::WriteFile(const std::string& aContent, const std::string& aFileName)
+ {
+ ofstream out;
+ OpenOutput(out, aFileName);
+ out << aContent;
+ out.close();
+ }
+
+} // end of namespace CdlCompilerToolkit