src/file.cpp

changeset 286
7a562bf3d829
parent 276
a21e49914264
child 288
2980d7fd948e
--- a/src/file.cpp	Thu Jun 13 16:33:17 2013 +0300
+++ b/src/file.cpp	Fri Jun 14 16:00:54 2013 +0300
@@ -74,9 +74,9 @@
 			return false;
 		}
 		
-		pathInfo.partsPath = fmt ("%s" DIRSLASH "parts", path.chars ());
-		pathInfo.LDConfigPath = fmt ("%s" DIRSLASH "LDConfig.ldr", path.chars ());
-		pathInfo.primsPath = fmt ("%s" DIRSLASH "p", path.chars ());
+		pathInfo.partsPath = fmt ("%1" DIRSLASH "parts", path);
+		pathInfo.LDConfigPath = fmt ("%1" DIRSLASH "LDConfig.ldr", path);
+		pathInfo.primsPath = fmt ("%1" DIRSLASH "p", path);
 		
 		return true;
 	}
@@ -117,10 +117,10 @@
 
 // =============================================================================
 str dirname (str path) {
-	long lastpos = path.last (DIRSLASH);
+	long lastpos = path.lastIndexOf (DIRSLASH);
 	
 	if (lastpos > 0)
-		return path.substr (0, lastpos);
+		return path.left (lastpos);
 	
 #ifndef _WIN32
 	if (path[0] == DIRSLASH_CHAR)
@@ -132,54 +132,54 @@
 
 // =============================================================================
 str basename (str path) {
-	long lastpos = path.last (DIRSLASH);
+	long lastpos = path.lastIndexOf (DIRSLASH);
 	
-	if (lastpos < (long) path.len () - 1)
-		return path.substr (lastpos + 1, -1);
+	if (lastpos != -1)
+		return path.mid (lastpos + 1);
 	
 	return path;
 }
 
 // =============================================================================
 FILE* openLDrawFile (str relpath, bool subdirs) {
-	printf ("%s: Try to open %s\n", __func__, relpath.c ());
+	printf ("%s: Try to open %s\n", __func__, qchars (relpath));
 	
 #ifndef WIN32
 	relpath.replace ("\\", "/");
 #endif // WIN32
 	
 	if (g_curfile != null) {
-		str partpath = fmt ("%s" DIRSLASH "%s", dirname (g_curfile->name ()).c (), relpath.c ());
-		printf ("try %s\n", partpath.c ());
-		FILE* fp = fopen (partpath, "r");
+		str partpath = fmt ("%1" DIRSLASH "%2", dirname (g_curfile->name ()), relpath);
+		printf ("try %s\n", qchars (partpath));
+		FILE* fp = fopen (qchars (partpath), "r");
 		
 		if (fp != null)
 			return fp;
 	}
 	
-	printf ("try %s\n", relpath.chars ());
-	FILE* fp = fopen (relpath, "r");
+	printf ("try %s\n", qchars (relpath));
+	FILE* fp = fopen (qchars (relpath), "r");
 	str fullPath;
 	
 	if (fp != null)
 		return fp;
 	
-	if (~io_ldpath.value) {
+	if (io_ldpath.value.length () > 0) {
 		// Try with just the LDraw path first
-		fullPath = fmt ("%s" DIRSLASH "%s", io_ldpath.value.chars(), relpath.chars());
-		printf ("try %s\n", fullPath.chars ());
+		fullPath = fmt ("%1" DIRSLASH "%2", io_ldpath, relpath);
+		printf ("try %s\n", qchars (fullPath));
 		
-		fp = fopen (fullPath, "r");
+		fp = fopen (qchars (fullPath), "r");
 		if (fp != null)
 			return fp;
 		
 		if (subdirs) {
 			for (auto subdir : initlist<const char*> ({"parts", "p"})) {
-				fullPath = fmt ("%s" DIRSLASH "%s" DIRSLASH "%s",
-					io_ldpath.value.chars(), subdir, relpath.chars());
+				fullPath = fmt ("%1" DIRSLASH "%2" DIRSLASH "%3",
+					io_ldpath, subdir, relpath);
 				
-				printf ("try %s\n", fullPath.chars ());
-				fp = fopen (fullPath.chars (), "r");
+				printf ("try %s\n", qchars (fullPath));
+				fp = fopen (qchars (fullPath), "r");
 				
 				if (fp)
 					return fp;
@@ -201,8 +201,9 @@
 	while (fgets (line, sizeof line, filePointer ())) {
 		// Trim the trailing newline
 		str data = line;
-		while (data[~data - 1] == '\n' || data[~data - 1] == '\r')
-			data -= 1;
+		qchar c;
+		while ((c = data[data.length () - 1]) == '\n' || c == '\r')
+			data.chop (1);
 		
 		LDObject* obj = parseLine (data);
 		assert (obj != null);
@@ -210,9 +211,9 @@
 		// Check for parse errors and warn about tthem
 		if (obj->getType () == LDObject::Gibberish) {
 			logf (LOG_Warning, "Couldn't parse line #%lu: %s\n",
-				m_progress + 1, static_cast<LDGibberish*> (obj)->reason.chars());
+				m_progress + 1, qchars (static_cast<LDGibberish*> (obj)->reason));
 			
-			logf (LOG_Warning, "- Line was: %s\n", data.chars());
+			logf (LOG_Warning, "- Line was: %s\n", qchars (data));
 			
 			if (m_warningsPointer)
 				(*m_warningsPointer)++;
@@ -300,21 +301,17 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 LDOpenFile* openDATFile (str path, bool search) {
-	logf ("Opening %s...\n", path.chars());
-	
 	// Convert the file name to lowercase since some parts contain uppercase
 	// file names. I'll assume here that the library will always use lowercase
 	// file names for the actual parts..
 	FILE* fp;
 	if (search)
-		fp = openLDrawFile (-path, true);
+		fp = openLDrawFile (path.toLower (), true);
 	else
-		fp = fopen (path, "r");
+		fp = fopen (qchars (path), "r");
 	
-	if (!fp) {
-		logf (LOG_Error, "Couldn't open %s: %s\n", path.chars (), strerror (errno));
+	if (!fp)
 		return null;
-	}
 	
 	LDOpenFile* oldLoad = g_curfile;
 	LDOpenFile* load = new LDOpenFile;
@@ -341,7 +338,7 @@
 	g_loadedFiles << load;
 	
 	logf ("File %s parsed successfully (%lu warning%s).\n",
-		path.chars(), numWarnings, plural (numWarnings));
+		qchars (path), numWarnings, plural (numWarnings));
 	
 	return load;
 }
@@ -355,25 +352,25 @@
 	// If we have unsaved changes, warn and give the option of saving.
 	if (!implicit () && history ().pos () != savePos ()) {
 		switch (QMessageBox::question (g_win, "Unsaved Changes",
-			fmt ("There are unsaved changes to %s. Should it be saved?",
-			(name ().len () > 0) ? name ().c () : "<anonymous>"),
+			fmt ("There are unsaved changes to %1. Should it be saved?",
+			(name ().length () > 0) ? name () : "<anonymous>"),
 			(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel), QMessageBox::Cancel))
 		{
 		case QMessageBox::Yes:
 			// If we don't have a file path yet, we have to ask the user for one.
-			if (name ().len () == 0) {
+			if (name ().length () == 0) {
 				str newpath = QFileDialog::getSaveFileName (g_win, "Save As",
 					g_curfile->name (), "LDraw files (*.dat *.ldr)");
 				
-				if (newpath.len () == 0)
+				if (newpath.length () == 0)
 					return false;
 				
 				setName (newpath);
 			}
 			
 			if (!save ()) {
-				str errormsg = fmt ("Failed to save %s: %s\nDo you still want to close?",
-					name ().c (), strerror (errno));
+				str errormsg = fmt ("Failed to save %1: %2\nDo you still want to close?",
+					name (), strerror (errno));
 				
 				if (QMessageBox::critical (g_win, "Save Failure", errormsg,
 					(QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::No)
@@ -438,28 +435,35 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void addRecentFile (str path) {
-	vector<str> rfiles = io_recentfiles.value.split ('@');
+	QStringList rfiles = io_recentfiles.value.split ('@');
+	
+	int idx = 0;
 	
-	ulong idx = rfiles.find (path);
+	for (str& it : rfiles) {
+		if (it == path)
+			break;
+		
+		idx++;
+	}
 	
 	// If this file already is in the list, pop it out.
-	if (idx != -1u) {
+	if (idx != rfiles.size ()) {
 		if (rfiles.size () == 1)
 			return; // only recent file - do nothing
 		
 		// Pop it out.
-		rfiles.erase (idx);
+		rfiles.removeAt (idx);
 	}
 	
 	// If there's too many recent files, drop one out.
 	while (rfiles.size () > (5 - 1))
-		rfiles.erase (0);
+		rfiles.removeAt (0);
 	
 	// Add the file
 	rfiles.push_back (path);
 	
 	// Rebuild the config string
-	io_recentfiles = str::join (rfiles, "@");
+	io_recentfiles = rfiles.join ("@");
 	
 	config::save ();
 	g_win->updateRecentFilesMenu ();
@@ -477,7 +481,7 @@
 	if (!file) {
 		// Tell the user loading failed.
 		setlocale (LC_ALL, "C");
-		critical (fmt ("Failed to open %s: %s", path.chars(), strerror (errno)));
+		critical (fmt ("Failed to open %1: %2", path, strerror (errno)));
 		
 		g_loadingMainFile = false;
 		return;
@@ -504,10 +508,10 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 bool LDOpenFile::save (str savepath) {
-	if (!~savepath)
+	if (!savepath.length ())
 		savepath = name ();
 	
-	FILE* fp = fopen (savepath, "w");
+	FILE* fp = fopen (qchars (savepath), "w");
 	
 	if (!fp)
 		return false;
@@ -519,15 +523,15 @@
 	if (!implicit () && objs ().size () >= 2 && object (1)->getType () == LDObject::Comment) {
 		fpathComment = static_cast<LDComment*> (object (1));
 		
-		if (fpathComment->text.substr (0, 6) == "Name: ") {
+		if (fpathComment->text.left (6) == "Name: ") {
 			str newfname;
 			str dir = basename (dirname (savepath));
 			
 			if (dir == "s" || dir == "48")
-				newfname = fmt ("%s\\", dir.c ());
+				newfname = dir + "\\";
 			
 			newfname += basename (savepath);
-			fpathComment->text = fmt ("Name: %s", newfname.c ());
+			fpathComment->text = fmt ("Name: %1", newfname);
 			g_win->buildObjList ();
 		}
 	}
@@ -535,8 +539,8 @@
 	// Write all entries now
 	for (LDObject* obj : objs ()) {
 		// LDraw requires files to have DOS line endings
-		str line = fmt ("%s\r\n", obj->raw ().chars ());
-		fwrite (line.chars(), 1, line.len (), fp);
+		str line = obj->raw () + "\r\n";
+		fwrite (qchars (line), 1, line.length (), fp);
 	}
 	
 	fclose (fp);
@@ -556,13 +560,13 @@
 #define CHECK_TOKEN_NUMBERS(MIN,MAX) \
 	for (ushort i = MIN; i <= MAX; ++i) \
 		if (!isNumber (tokens[i])) \
-			return new LDGibberish (line, fmt ("Token #%u was `%s`, expected a number", \
-				(i + 1), tokens[i].chars()));
+			return new LDGibberish (line, fmt ("Token #%1 was `%2`, expected a number", \
+				(i + 1), tokens[i]));
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-static vertex parseVertex (vector<str>& s, const ushort n) {
+static vertex parseVertex (QStringList& s, const ushort n) {
 	// Disable the locale while parsing the line or atof's behavior changes
 	// between locales (i.e. fails to read decimals properly). That is
 	// quite undesired...
@@ -570,7 +574,7 @@
 	
 	vertex v;
 	for (const Axis ax : g_Axes)
-		v[ax] = atof (s[n + ax]);
+		v[ax] = s[n + ax].toFloat ();
 	
 	return v;
 }
@@ -579,23 +583,23 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 LDObject* parseLine (str line) {
-	vector<str> tokens = line.split (" ");
+	QStringList tokens = line.split (" ", str::SkipEmptyParts);
 	
 	if (!tokens.size ()) {
 		// Line was empty, or only consisted of whitespace
 		return new LDEmpty;
 	}
 	
-	if (~tokens[0] != 1)
+	if (tokens[0].length () != 1)
 		return new LDGibberish (line, "Illogical line code");
 	
-	const char c = tokens[0][0];
-	switch (c - '0') {
+	const qchar c = tokens[0][0];
+	switch (c.toAscii () - '0') {
 	case 0:
 		{
 			// Comment
 			str comm;
-			for (uint i = 1; i < tokens.size(); ++i) {
+			for (int i = 1; i < tokens.size(); ++i) {
 				comm += tokens[i];
 				
 				if (i != tokens.size() - 1)
@@ -605,7 +609,7 @@
 			// Handle BFC statements
 			if (tokens.size() > 2 && tokens[1] == "BFC") {
 				for (short i = 0; i < LDBFC::NumStatements; ++i)
-					if (comm == fmt ("BFC %s", LDBFC::statements [i]))
+					if (comm == fmt ("BFC %1", LDBFC::statements [i]))
 						return new LDBFC ((LDBFC::Type) i);
 				
 				// MLCAD is notorious for stuffing these statements in parts it
@@ -624,10 +628,10 @@
 					CHECK_TOKEN_NUMBERS (3, 6)
 					
 					LDVertex* obj = new LDVertex;
-					obj->setColor (atol (tokens[3]));
+					obj->setColor (tokens[3].toLong ());
 					
 					for (const Axis ax : g_Axes)
-						obj->pos[ax] = atof (tokens[4 + ax]); // 4 - 6
+						obj->pos[ax] = tokens[4 + ax].toDouble (); // 4 - 6
 					
 					return obj;
 				}
@@ -639,27 +643,27 @@
 					LDRadial::Type eType = LDRadial::NumTypes;
 					
 					for (int i = 0; i < LDRadial::NumTypes; ++i) {
-						if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).upper ().strip (' ') == tokens[3]) {
+						if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).toUpper ().remove (' ') == tokens[3]) {
 							eType = (LDRadial::Type) i;
 							break;
 						}
 					}
 					
 					if (eType == LDRadial::NumTypes)
-						return new LDGibberish (line, fmt ("Unknown radial type %s", tokens[3].chars ()));
+						return new LDGibberish (line, fmt ("Unknown radial type %1", tokens[3]));
 					
 					LDRadial* obj = new LDRadial;
 					
 					obj->setType (eType);
-					obj->setColor (atol (tokens[4]));
-					obj->setSegments (atol (tokens[5]));
-					obj->setDivisions (atol (tokens[6]));
-					obj->setNumber (atol (tokens[7]));
+					obj->setColor (tokens[4].toLong ());
+					obj->setSegments (tokens[5].toLong ());
+					obj->setDivisions (tokens[6].toLong ());
+					obj->setNumber (tokens[7].toLong ());
 					obj->setPosition (parseVertex (tokens, 8)); // 8 - 10
 					
 					matrix transform;
 					for (short i = 0; i < 9; ++i)
-						transform[i] = atof (tokens[i + 11]); // 11 - 19
+						transform[i] = tokens[i + 11].toDouble (); // 11 - 19
 					
 					obj->setTransform (transform);
 					return obj;
@@ -689,12 +693,12 @@
 				return new LDGibberish (line, "Could not open referred file");
 			
 			LDSubfile* obj = new LDSubfile;
-			obj->setColor (atol (tokens[1]));
+			obj->setColor (tokens[1].toLong ());
 			obj->setPosition (parseVertex (tokens, 2)); // 2 - 4
 			
 			matrix transform;
 			for (short i = 0; i < 9; ++i)
-				transform[i] = atof (tokens[i + 5]); // 5 - 13
+				transform[i] = tokens[i + 5].toDouble (); // 5 - 13
 			
 			obj->setTransform (transform);
 			obj->setFileInfo (load);
@@ -708,7 +712,7 @@
 			
 			// Line
 			LDLine* obj = new LDLine;
-			obj->setColor (atol (tokens[1]));
+			obj->setColor (tokens[1].toLong ());
 			for (short i = 0; i < 2; ++i)
 				obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 7
 			return obj;
@@ -721,7 +725,7 @@
 			
 			// Triangle
 			LDTriangle* obj = new LDTriangle;
-			obj->setColor (atol (tokens[1]));
+			obj->setColor (tokens[1].toLong ());
 			
 			for (short i = 0; i < 3; ++i)
 				obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 10
@@ -736,7 +740,7 @@
 			
 			// Quadrilateral
 			LDQuad* obj = new LDQuad;
-			obj->setColor (atol (tokens[1]));
+			obj->setColor (tokens[1].toLong ());
 			
 			for (short i = 0; i < 4; ++i)
 				obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13
@@ -751,7 +755,7 @@
 			
 			// Conditional line
 			LDCondLine* obj = new LDCondLine;
-			obj->setColor (atol (tokens[1]));
+			obj->setColor (tokens[1].toLong ());
 			
 			for (short i = 0; i < 4; ++i)
 				obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13
@@ -858,8 +862,6 @@
 vector<partListEntry> g_PartList;
 
 void initPartList () {
-	logf ("%s: initializing parts.lst\n", __func__);
-	
 	FILE* fp = openLDrawFile ("parts.lst", false);
 	
 	if (!fp)

mercurial