cdlcompilertoolkit/src/CdlTkUtil.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
equal deleted inserted replaced
-1:000000000000 0:f58d6ec98e88
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 #include "CdlTkPriv.h"
       
    18 
       
    19 #include <string>
       
    20 #include <vector>
       
    21 #include <algorithm>
       
    22 #include <iostream>
       
    23 #include <fstream>
       
    24 #include <sstream>
       
    25 #include <iomanip>
       
    26 #include <direct.h>
       
    27 using namespace std;
       
    28 
       
    29 namespace CdlCompilerToolkit {
       
    30 
       
    31 //
       
    32 // CdlCompilerToolkitErr
       
    33 //
       
    34 
       
    35 CdlCompilerToolkitErr::~CdlCompilerToolkitErr()
       
    36 	{
       
    37 	}
       
    38 
       
    39 
       
    40 //
       
    41 // CCdlTkFileCleanup
       
    42 //
       
    43 
       
    44 CCdlTkFileCleanup::CCdlTkFileCleanup()
       
    45 : iName("")
       
    46 	{
       
    47 	}
       
    48 
       
    49 CCdlTkFileCleanup::CCdlTkFileCleanup(const std::string& aName)
       
    50 : iName(aName)
       
    51 	{
       
    52 	}
       
    53 
       
    54 CCdlTkFileCleanup::~CCdlTkFileCleanup()
       
    55 	{
       
    56 	Cleanup();
       
    57 	}
       
    58 
       
    59 void CCdlTkFileCleanup::Set(const string& aName)
       
    60 	{
       
    61 	iName = aName;
       
    62 	}
       
    63 
       
    64 void CCdlTkFileCleanup::Cleanup()
       
    65 	{
       
    66 	if (!iName.empty())
       
    67 		CdlTkUtil::DeleteFile(iName);
       
    68 	Release();
       
    69 	}
       
    70 
       
    71 string CCdlTkFileCleanup::Name() const
       
    72 	{
       
    73 	return iName;
       
    74 	}
       
    75 
       
    76 void CCdlTkFileCleanup::Release()
       
    77 	{
       
    78 	iName.erase();
       
    79 	}
       
    80 
       
    81 
       
    82 //
       
    83 // CdlTkAssert
       
    84 //
       
    85 
       
    86 CdlTkAssert::CdlTkAssert(const string& aText)
       
    87 : iText(aText)
       
    88 	{
       
    89 	}
       
    90 
       
    91 void CdlTkAssert::Show(ostream& stream) const
       
    92 	{
       
    93 	stream << "Cdl Compiler Toolkit assertion failed : " << iText << endl;
       
    94 	}
       
    95 
       
    96 
       
    97 //
       
    98 // CdlTkFileOpenErr
       
    99 //
       
   100 
       
   101 CdlTkFileOpenErr::CdlTkFileOpenErr(const string& aFileName) : iFileName(aFileName)
       
   102 	{
       
   103 	}
       
   104 
       
   105 void CdlTkFileOpenErr::Show(ostream& stream) const
       
   106 	{
       
   107 	stream << endl;
       
   108 	stream << iFileName << " failed to open" << endl;
       
   109 	}
       
   110 
       
   111 
       
   112 //
       
   113 // CdlTkUtil
       
   114 //
       
   115 
       
   116 string CdlTkUtil::CurrentDrive()
       
   117 	{
       
   118 	static string drive = "?:";
       
   119 	if (drive == "?:")
       
   120 		drive[0] = 'A' + _getdrive() - 1;
       
   121 	return drive;
       
   122 	}
       
   123 
       
   124 string CdlTkUtil::CurrentDir()
       
   125 	{
       
   126 	static string dir = "";
       
   127 	if (dir == "")
       
   128 		{
       
   129 		char buf[256];
       
   130 		dir = _getcwd(buf, 255) + 2;	// +2 removes drive
       
   131 		dir += "\\";
       
   132 		}
       
   133 	return dir;
       
   134 	}
       
   135 
       
   136 static string gOutputPath = "";
       
   137 
       
   138 string CdlTkUtil::OutputPath()
       
   139 	{
       
   140 	if (gOutputPath == "")
       
   141 		gOutputPath = CurrentDir();
       
   142 	return gOutputPath;
       
   143 	}
       
   144 
       
   145 void CdlTkUtil::SetOutputPath(const string& aPath)
       
   146 	{
       
   147 	gOutputPath = aPath;
       
   148 	if (gOutputPath.size() == 0)
       
   149 		gOutputPath += ".\\";
       
   150 	else if (gOutputPath[gOutputPath.size()-1] != '\\')
       
   151 		gOutputPath += "\\";	// CDL Tk convention is that paths always end in \ 
       
   152 	}
       
   153 
       
   154 string CdlTkUtil::ToLower(const string& aString)
       
   155 	{
       
   156 	string r;
       
   157 	r.resize(aString.size());
       
   158 	transform(aString.begin(), aString.end(), r.begin(), tolower);
       
   159 	return r;
       
   160 	}
       
   161 
       
   162 string CdlTkUtil::ToUpper(const string& aString)
       
   163 	{
       
   164 	string r;
       
   165 	r.resize(aString.size());
       
   166 	transform(aString.begin(), aString.end(), r.begin(), toupper);
       
   167 	return r;
       
   168 	}
       
   169 
       
   170 string CdlTkUtil::ToCpp(const string& aString)
       
   171 	{
       
   172 	string r = aString;
       
   173 	for (string::iterator pC = r.begin(); pC != r.end(); ++pC)
       
   174 		{
       
   175 		if (!CdlTkUtil::IsCpp(*pC))
       
   176 			*pC = '_';
       
   177 		}
       
   178 	if (r.empty() || CdlTkUtil::IsNumeric(r[0]))
       
   179 		r = string("_") + r;
       
   180 	return r;
       
   181 	}
       
   182 
       
   183 string CdlTkUtil::StripPath(const string& aPath)
       
   184 	{
       
   185 	return aPath.substr(aPath.rfind('\\')+1);
       
   186 	}
       
   187 
       
   188 string CdlTkUtil::ResolvePath(const string& aPath, const string& aFileName)
       
   189 	{
       
   190 	int size = aFileName.size();
       
   191 	// if aFileName is absolute, return it
       
   192 	if (size > 0 && aFileName[0] == '\\' || size > 1 && aFileName[1] == ':')
       
   193 		return aFileName;
       
   194 
       
   195 	string path = aPath;
       
   196 	string file = aFileName;
       
   197 
       
   198 	// while file starts with a '.', chop file head directory and path tail directory if necessary
       
   199 	while (file.size() > 0 && file[0]=='.')
       
   200 		{
       
   201 		// if file starts with a "..", chop the tail directory off the path
       
   202 		if (file.size() > 1 && file[1]=='.' && !path.empty())
       
   203 			{
       
   204 			path.resize(path.size()-1);			// remove the last slash
       
   205 			path.resize(path.rfind('\\')+1);	// remove everything after the next last slash
       
   206 			}
       
   207 
       
   208 		// chop the head directory off the file - it has to have a '\' if it has a '.'
       
   209 		int fileSlashPos = file.find('\\');
       
   210 		if (fileSlashPos == string::npos)
       
   211 			throw CdlTkAssert("Illegal filename");
       
   212 		file = file.substr(fileSlashPos + 1);
       
   213 		}
       
   214 
       
   215 	// join remaining path and file
       
   216 	return path + file;
       
   217 	}
       
   218 
       
   219 string CdlTkUtil::CapitalizeFilename(const string& aString)
       
   220 	{
       
   221 	// convert the whole thing to lower case
       
   222 	string res = ToLower(aString);
       
   223 	// find the first character after the last \ - will be 0 if no \ is present.
       
   224 	int filenamePos = res.find_last_of('\\') + 1;
       
   225 	if (filenamePos >= res.size())
       
   226 		throw CdlTkAssert(aString + " has no filename");
       
   227 	// uppercase the first character
       
   228 	res[filenamePos] = toupper(res[filenamePos]);
       
   229 	cerr << "Warning, filename capitalized: " << res << endl;
       
   230 	return res;
       
   231 	}
       
   232 
       
   233 string CdlTkUtil::CorrectFilenameCase(const string& aString)
       
   234 	{
       
   235 	// The current standard is to set the filename and path to lower case.
       
   236 	return ToLower(aString);
       
   237 	}
       
   238 
       
   239 string CdlTkUtil::Replace(const string& aTarget, const string& aWith, const string& aIn)
       
   240 	{
       
   241 	string ret;
       
   242 	int pos=0;
       
   243 	int lastMatch = 0;
       
   244 	int targetMatch = 0;
       
   245 	int targetSize = aTarget.size();
       
   246 	int inSize = aIn.size();
       
   247 	while (pos < inSize)
       
   248 		{
       
   249 		if (aTarget[targetMatch] == aIn[pos++])
       
   250 			{
       
   251 			++targetMatch;
       
   252 			if (targetMatch == targetSize)
       
   253 				{
       
   254 				AppendString(ret, aIn.substr(lastMatch, pos - targetMatch - lastMatch));
       
   255 				AppendString(ret, aWith);
       
   256 				lastMatch = pos;
       
   257 				targetMatch = 0;
       
   258 				}
       
   259 			}
       
   260 		else
       
   261 			{
       
   262 			targetMatch = 0;
       
   263 			}
       
   264 		}
       
   265 	AppendString(ret, aIn.substr(lastMatch));
       
   266 	return ret;
       
   267 	}
       
   268 
       
   269 void CdlTkUtil::ExportFile(CCdlTkFileCleanup& aSourceFile, const string& aExport, ios_base::openmode aOpenMode)
       
   270 	{
       
   271 	if (!FilesAreIdentical(aSourceFile.Name(), aExport, aOpenMode))
       
   272 		{
       
   273 		CopyFile(aSourceFile.Name(), aExport, aOpenMode);
       
   274 		}
       
   275 	aSourceFile.Cleanup();
       
   276 	}
       
   277 
       
   278 void CdlTkUtil::ExportFileIfWritable(CCdlTkFileCleanup& aSourceFile, const string& aExport, ios_base::openmode aOpenMode)
       
   279 	{
       
   280 	if (!FilesAreIdentical(aSourceFile.Name(), aExport, aOpenMode))
       
   281 		{
       
   282 		try
       
   283 			{
       
   284 			CopyFile(aSourceFile.Name(), aExport, aOpenMode);
       
   285 			}
       
   286 		catch (const CdlTkFileOpenErr& /*e*/)
       
   287 			{
       
   288 			cerr << "Could not write to " << aExport << endl;
       
   289 			}
       
   290 		}
       
   291 	aSourceFile.Cleanup();
       
   292 	}
       
   293 
       
   294 void CdlTkUtil::DeleteFile(const std::string& aFileName)
       
   295 	{
       
   296 	remove(aFileName.c_str());
       
   297 	}
       
   298 
       
   299 void CdlTkUtil::CopyFile(const std::string& aSourceFileName, const std::string& aDestinationFileName, ios_base::openmode aOpenMode)
       
   300 	{
       
   301 	ifstream from;
       
   302 	OpenInput(from, aSourceFileName, aOpenMode);
       
   303 	ofstream to;
       
   304 	OpenOutput(to, aDestinationFileName, aOpenMode);
       
   305 
       
   306 	const int KSize = 1024;
       
   307 	char buf[KSize+1];
       
   308 	while (!from.eof())
       
   309 		{
       
   310 		from.read(buf,KSize);
       
   311 		to.write(buf, from.gcount());
       
   312 		}
       
   313 
       
   314 	from.close();
       
   315 	to.close();
       
   316 	}
       
   317 
       
   318 bool CdlTkUtil::FilesAreIdentical(const std::string& aLeftFileName, const std::string& aRightFileName, ios_base::openmode aOpenMode)
       
   319 	{
       
   320 	bool different = false;
       
   321 	ifstream leftFile(aLeftFileName.c_str(), aOpenMode);
       
   322 	ifstream rightFile(aRightFileName.c_str(), aOpenMode);
       
   323 
       
   324 	const int KSize = 1024;
       
   325 	char left[KSize+1];
       
   326 	char right[KSize+1];
       
   327 
       
   328 	while (!leftFile.eof() && !rightFile.eof())
       
   329 		{
       
   330 		int gotLeft = leftFile.read(left,KSize).gcount();
       
   331 		int gotRight = rightFile.read(right,KSize).gcount();
       
   332 
       
   333 		if (gotLeft != gotRight || memcmp(left, right, gotLeft) != 0)
       
   334 			{
       
   335 			different = true;
       
   336 			break;
       
   337 			}
       
   338 		}
       
   339 
       
   340 	if (leftFile.eof() != rightFile.eof())
       
   341 		different = true;
       
   342 
       
   343 	leftFile.close();
       
   344 	rightFile.close();
       
   345 
       
   346 	return !different;
       
   347 	}
       
   348 
       
   349 void CdlTkUtil::OpenTempOutput(ofstream& aStream, CCdlTkFileCleanup& aFile, ios_base::openmode aOpenMode)
       
   350 	{
       
   351 	char tmpName[256];
       
   352 	if (!tmpnam(tmpName))
       
   353 		{
       
   354 		throw CdlTkAssert("Can't create temporary file name");
       
   355 		}
       
   356 
       
   357 	OpenOutput(aStream, tmpName, aOpenMode);
       
   358 	aFile.Set(tmpName);
       
   359 	}
       
   360 
       
   361 void CdlTkUtil::OpenOutput(ofstream& aStream, const string& aFileName, ios_base::openmode aOpenMode)
       
   362 	{
       
   363 	aStream.open(aFileName.c_str(), aOpenMode);
       
   364 	if (!aStream.is_open())
       
   365 		{
       
   366 		throw CdlTkFileOpenErr(aFileName);
       
   367 		}
       
   368 	}
       
   369 
       
   370 void CdlTkUtil::OpenInput(ifstream& aStream, const string& aFileName, ios_base::openmode aOpenMode)
       
   371 	{
       
   372 	aStream.open(aFileName.c_str(), aOpenMode);
       
   373 	if (!aStream.is_open())
       
   374 		throw CdlTkFileOpenErr(aFileName);
       
   375 	}
       
   376 
       
   377 int CdlTkUtil::ParseInt(const string& aInt)
       
   378 	{
       
   379 	int base = 10;
       
   380 	if (aInt.size() > 1 && aInt[0] == '0')
       
   381 		{
       
   382 		base = 8;
       
   383 		if (aInt[1] == 'x')
       
   384 			base = 16;
       
   385 		}
       
   386 
       
   387 	int val = 0;
       
   388 	stringstream s(aInt);
       
   389 	s >> setbase(base) >> val;
       
   390 	return val;
       
   391 	}
       
   392 
       
   393 string CdlTkUtil::IntToString(int aInt)
       
   394 	{
       
   395 	stringstream s;
       
   396 	s << aInt;
       
   397 	return s.str();
       
   398 	}
       
   399 
       
   400 string CdlTkUtil::IntToHexString(int aInt)
       
   401 	{
       
   402 	stringstream s;
       
   403 	s << "0x" << setw(8) << setfill('0') << hex << aInt;
       
   404 	return s.str();
       
   405 	}
       
   406 
       
   407 char* gHexDigits = "0123456789abcdef";
       
   408 string CdlTkUtil::ShortToHexString(short aInt)
       
   409 	{
       
   410 	char s[7] = "0x0000";
       
   411 	s[2]=gHexDigits[(aInt>>12)&0xf];
       
   412 	s[3]=gHexDigits[(aInt>>8)&0xf];
       
   413 	s[4]=gHexDigits[(aInt>>4)&0xf];
       
   414 	s[5]=gHexDigits[aInt&0xf];
       
   415 	return s;
       
   416 	}
       
   417 
       
   418 string CdlTkUtil::CharToHexString(char aInt)
       
   419 	{
       
   420 	char s[5] = "0x00";
       
   421 	s[2]=gHexDigits[(aInt>>4)&0xf];
       
   422 	s[3]=gHexDigits[aInt&0xf];
       
   423 	return s;
       
   424 	}
       
   425 
       
   426 void CdlTkUtil::StripLeadingAndTrailingWhitespace(string& aStr)
       
   427 	{
       
   428 	int pos = aStr.find_first_not_of(KWhiteSpace);
       
   429 	if (pos == string::npos)
       
   430 		{
       
   431 		aStr = KEmptyString;
       
   432 		}
       
   433 	else
       
   434 		{
       
   435 		aStr = aStr.substr(pos, aStr.find_last_not_of(KWhiteSpace) + 1 - pos);
       
   436 		}
       
   437 	}
       
   438 
       
   439 bool CdlTkUtil::IsAlpha(char aChar)
       
   440 	{
       
   441 	return ('A' <= aChar && aChar <= 'Z') || ('a' <= aChar && aChar <= 'z');
       
   442 	}
       
   443 
       
   444 bool CdlTkUtil::IsNumeric(char aChar)
       
   445 	{
       
   446 	return '0' <= aChar && aChar <= '9';
       
   447 	}
       
   448 
       
   449 bool CdlTkUtil::IsCpp(char aChar)
       
   450 	{
       
   451 	return IsAlpha(aChar) || IsNumeric(aChar) || aChar == '_';
       
   452 	}
       
   453 
       
   454 void ZeroInts(int* aInts, int aCount)
       
   455 	{
       
   456 	for (int ii=0; ii<aCount; ii++)
       
   457 		aInts[ii] = 0;
       
   458 	}
       
   459 
       
   460 string CdlTkUtil::MultiReplace(const CReplaceSet& aSet, const string& aIn)
       
   461 	{
       
   462 	string ret;
       
   463 	int setCount = aSet.size();
       
   464 	int* match = new int[setCount];
       
   465 	if (!match)
       
   466 		throw bad_alloc();
       
   467 	ZeroInts(match, setCount);
       
   468 
       
   469 	int inSize = aIn.size();
       
   470 	int pos = 0;
       
   471 	int lastMatch = 0;
       
   472 	while (pos < inSize)
       
   473 		{
       
   474 		char ch = aIn[pos++];
       
   475 		for (int ii=0; ii<setCount; ii++)
       
   476 			{
       
   477 			const string& target = aSet[ii].first;
       
   478 			int& targetMatch = match[ii];
       
   479 			if (target[targetMatch] == ch)
       
   480 				{
       
   481 				++targetMatch;
       
   482 				if (targetMatch == target.size())
       
   483 					{
       
   484 					AppendString(ret, aIn.substr(lastMatch, pos - targetMatch - lastMatch));
       
   485 					AppendString(ret, aSet[ii].second);
       
   486 					lastMatch = pos;
       
   487 					ZeroInts(match, setCount);
       
   488 					}
       
   489 				}
       
   490 			else
       
   491 				{
       
   492 				match[ii] = 0;
       
   493 				}
       
   494 			}
       
   495 		}
       
   496 	AppendString(ret, aIn.substr(lastMatch));
       
   497 
       
   498 	delete[] match;
       
   499 	return ret;
       
   500 	}
       
   501 
       
   502 void CdlTkUtil::AppendString(string& aTarget, const string& aAppend)
       
   503 	{
       
   504 	int resSize = aTarget.size() + aAppend.size();
       
   505 	if (aTarget.capacity() < resSize)
       
   506 		aTarget.reserve(resSize*2);
       
   507 	aTarget.append(aAppend);
       
   508 	}
       
   509 
       
   510 static string gCommandLine = "";
       
   511 
       
   512 string CdlTkUtil::CommandLine()
       
   513 	{
       
   514 	return gCommandLine;
       
   515 	}
       
   516 
       
   517 void CdlTkUtil::SetCommandLine(int argc, char* argv[])
       
   518 	{
       
   519 	string tool(argv[0]);
       
   520 	tool = tool.substr(tool.find_last_of('\\') + 1);
       
   521 	gCommandLine = tool.substr(0, tool.find_last_of('.'));
       
   522 	for (int ii=1; ii<argc; ii++)
       
   523 		{
       
   524 		AppendString(gCommandLine, " ");
       
   525 		AppendString(gCommandLine, argv[ii]);
       
   526 		}
       
   527 	}
       
   528 
       
   529 //
       
   530 // CdlTkUtil::CReplaceSet
       
   531 //
       
   532 
       
   533 void CdlTkUtil::CReplaceSet::Add(const string& aTarget, const string& aWith) 
       
   534 	{
       
   535 	push_back(make_pair(aTarget, aWith));
       
   536 	}
       
   537 
       
   538 void CdlTkUtil::ReadFile(std::string& aContent, const std::string& aFileName)
       
   539 	{
       
   540 	ifstream in;
       
   541 	OpenInput(in, aFileName);
       
   542 	aContent.erase();
       
   543 	const int KChars = 1024 + 1;
       
   544 	char buf[KChars];
       
   545 	while (!in.eof())
       
   546 		{
       
   547 		in.get(buf,KChars,0);
       
   548 		AppendString(aContent, buf);
       
   549 		}
       
   550 	in.close();
       
   551 	}
       
   552 
       
   553 void CdlTkUtil::WriteFile(const std::string& aContent, const std::string& aFileName)
       
   554 	{
       
   555 	ofstream out;
       
   556 	OpenOutput(out, aFileName);
       
   557 	out << aContent;
       
   558 	out.close();
       
   559 	}
       
   560 
       
   561 }	// end of namespace CdlCompilerToolkit