2
0
Эх сурвалжийг харах

Moved out non-core functions from the String type for easier maintenance.

David Piuva 5 жил өмнө
parent
commit
fe47c67848

+ 8 - 8
Source/DFPSR/api/configAPI.cpp

@@ -32,21 +32,21 @@ void dsr::config_parse_ini(const ReadableString& content, ConfigIniCallback rece
 		// Get the current line
 		// Get the current line
 		ReadableString command = lines[l];
 		ReadableString command = lines[l];
 		// Skip comments
 		// Skip comments
-		int commentIndex = command.findFirst(U';');
+		int commentIndex = string_findFirst(command, U';');
 		if (commentIndex > -1) {
 		if (commentIndex > -1) {
-			command = command.before(commentIndex);
+			string_before(command, commentIndex);
 		}
 		}
 		// Find assignments
 		// Find assignments
-		int assignmentIndex = command.findFirst(U'=');
+		int assignmentIndex = string_findFirst(command, U'=');
 		if (assignmentIndex > -1) {
 		if (assignmentIndex > -1) {
-			ReadableString key = string_removeOuterWhiteSpace(command.before(assignmentIndex));
-			ReadableString value = string_removeOuterWhiteSpace(command.after(assignmentIndex));
+			ReadableString key = string_removeOuterWhiteSpace(string_before(command, assignmentIndex));
+			ReadableString value = string_removeOuterWhiteSpace(string_after(command, assignmentIndex));
 			receiverLambda(block, key, value);
 			receiverLambda(block, key, value);
 		} else {
 		} else {
-			int blockStartIndex = command.findFirst(U'[');
-			int blockEndIndex = command.findFirst(U']');
+			int blockStartIndex = string_findFirst(command, U'[');
+			int blockEndIndex = string_findFirst(command, U']');
 			if (blockStartIndex > -1 && blockEndIndex > -1) {
 			if (blockStartIndex > -1 && blockEndIndex > -1) {
-				block = string_removeOuterWhiteSpace(command.inclusiveRange(blockStartIndex + 1, blockEndIndex - 1));
+				block = string_removeOuterWhiteSpace(string_inclusiveRange(command, blockStartIndex + 1, blockEndIndex - 1));
 			}
 			}
 		}
 		}
 	}
 	}

+ 47 - 47
Source/DFPSR/base/text.cpp

@@ -49,48 +49,6 @@ static bool isWhiteSpace(DsrChar c) {
 	return c <= U' ' || c == U'\t' || c == U'\r';
 	return c <= U' ' || c == U'\t' || c == U'\r';
 }
 }
 
 
-int ReadableString::findFirst(DsrChar toFind, int startIndex) const {
-	for (int i = startIndex; i < this->length(); i++) {
-		if (this->readSection[i] == toFind) {
-			return i;
-		}
-	}
-	return -1;
-}
-
-int ReadableString::findLast(DsrChar toFind) const {
-	for (int i = this->length() - 1; i >= 0; i--) {
-		if (this->readSection[i] == toFind) {
-			return i;
-		}
-	}
-	return -1;
-}
-
-ReadableString ReadableString::exclusiveRange(int inclusiveStart, int exclusiveEnd) const {
-	return this->getRange(inclusiveStart, exclusiveEnd - inclusiveStart);
-}
-
-ReadableString ReadableString::inclusiveRange(int inclusiveStart, int inclusiveEnd) const {
-	return this->getRange(inclusiveStart, inclusiveEnd + 1 - inclusiveStart);
-}
-
-ReadableString ReadableString::before(int exclusiveEnd) const {
-	return this->exclusiveRange(0, exclusiveEnd);
-}
-
-ReadableString ReadableString::until(int inclusiveEnd) const {
-	return this->inclusiveRange(0, inclusiveEnd);
-}
-
-ReadableString ReadableString::from(int inclusiveStart) const {
-	return this->exclusiveRange(inclusiveStart, this->length());
-}
-
-ReadableString ReadableString::after(int exclusiveStart) const {
-	return this->from(exclusiveStart + 1);
-}
-
 String& Printable::toStream(String& target) const {
 String& Printable::toStream(String& target) const {
 	return this->toStreamIndented(target, U"");
 	return this->toStreamIndented(target, U"");
 }
 }
@@ -217,7 +175,7 @@ ReadableString dsr::string_removeOuterWhiteSpace(const ReadableString &text) {
 		return ReadableString();
 		return ReadableString();
 	} else {
 	} else {
 		// Subset
 		// Subset
-		return text.inclusiveRange(first, last);
+		return string_inclusiveRange(text, first, last);
 	}
 	}
 }
 }
 
 
@@ -264,8 +222,8 @@ String dsr::string_mangleQuote(const ReadableString &rawText) {
 }
 }
 
 
 String dsr::string_unmangleQuote(const ReadableString& mangledText) {
 String dsr::string_unmangleQuote(const ReadableString& mangledText) {
-	int firstQuote = mangledText.findFirst('\"');
-	int lastQuote = mangledText.findLast('\"');
+	int firstQuote = string_findFirst(mangledText, '\"');
+	int lastQuote = string_findLast(mangledText, '\"');
 	String result;
 	String result;
 	if (firstQuote == -1 || lastQuote == -1 || firstQuote == lastQuote) {
 	if (firstQuote == -1 || lastQuote == -1 || firstQuote == lastQuote) {
 		throwError(U"Cannot unmangle using string_unmangleQuote without beginning and ending with quote signs!\n", mangledText, "\n");
 		throwError(U"Cannot unmangle using string_unmangleQuote without beginning and ending with quote signs!\n", mangledText, "\n");
@@ -708,12 +666,12 @@ void dsr::string_split_inPlace(List<ReadableString> &target, const ReadableStrin
 	for (int i = 0; i < source.length(); i++) {
 	for (int i = 0; i < source.length(); i++) {
 		DsrChar c = source[i];
 		DsrChar c = source[i];
 		if (c == separator) {
 		if (c == separator) {
-			target.push(source.exclusiveRange(sectionStart, i));
+			target.push(string_exclusiveRange(source, sectionStart, i));
 			sectionStart = i + 1;
 			sectionStart = i + 1;
 		}
 		}
 	}
 	}
 	if (source.length() > sectionStart) {
 	if (source.length() > sectionStart) {
-		target.push(source.exclusiveRange(sectionStart, source.length()));;
+		target.push(string_exclusiveRange(source, sectionStart, source.length()));;
 	}
 	}
 }
 }
 
 
@@ -833,3 +791,45 @@ double dsr::string_toDouble(const ReadableString& source) {
 	}
 	}
 }
 }
 
 
+int dsr::string_findFirst(const ReadableString& source, DsrChar toFind, int startIndex) {
+	for (int i = startIndex; i < source.length(); i++) {
+		if (source[i] == toFind) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+int dsr::string_findLast(const ReadableString& source, DsrChar toFind) {
+	for (int i = source.length() - 1; i >= 0; i--) {
+		if (source[i] == toFind) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+ReadableString dsr::string_exclusiveRange(const ReadableString& source, int inclusiveStart, int exclusiveEnd) {
+	return source.getRange(inclusiveStart, exclusiveEnd - inclusiveStart);
+}
+
+ReadableString dsr::string_inclusiveRange(const ReadableString& source, int inclusiveStart, int inclusiveEnd) {
+	return source.getRange(inclusiveStart, inclusiveEnd + 1 - inclusiveStart);
+}
+
+ReadableString dsr::string_before(const ReadableString& source, int exclusiveEnd) {
+	return string_exclusiveRange(source, 0, exclusiveEnd);
+}
+
+ReadableString dsr::string_until(const ReadableString& source, int inclusiveEnd) {
+	return string_inclusiveRange(source, 0, inclusiveEnd);
+}
+
+ReadableString dsr::string_from(const ReadableString& source, int inclusiveStart) {
+	return string_exclusiveRange(source, inclusiveStart, source.length());
+}
+
+ReadableString dsr::string_after(const ReadableString& source, int exclusiveStart) {
+	return string_from(source, exclusiveStart + 1);
+}
+

+ 13 - 21
Source/DFPSR/base/text.h

@@ -62,34 +62,18 @@ protected:
 	bool checkBound(int start, int length, bool warning = true) const;
 	bool checkBound(int start, int length, bool warning = true) const;
 	// Internal constructor
 	// Internal constructor
 	ReadableString(const DsrChar *content, int sectionLength);
 	ReadableString(const DsrChar *content, int sectionLength);
+public:
 	// Create a string from an existing string
 	// Create a string from an existing string
 	// When there's no reference counter, it's important that the memory remains allocated until the application terminates
 	// When there's no reference counter, it's important that the memory remains allocated until the application terminates
 	// Just like when reading elements in a for loop, out-of-range only causes an exception if length > 0
 	// Just like when reading elements in a for loop, out-of-range only causes an exception if length > 0
 	//   Length lesser than 1 will always return an empty string
 	//   Length lesser than 1 will always return an empty string
 	virtual ReadableString getRange(int start, int length) const;
 	virtual ReadableString getRange(int start, int length) const;
-public:
 	// Converting to unknown character encoding using only the ascii character subset
 	// Converting to unknown character encoding using only the ascii character subset
 	// A bug in GCC linking forces these to be virtual
 	// A bug in GCC linking forces these to be virtual
 	virtual std::ostream& toStream(std::ostream& out) const;
 	virtual std::ostream& toStream(std::ostream& out) const;
 	virtual std::string toStdString() const;
 	virtual std::string toStdString() const;
 public:
 public:
-	// Get the index of the first character in content matching toFind, or -1 if it doesn't exist.
-	int findFirst(DsrChar toFind, int startIndex = 0) const;
-	// Get the index of the last character in content matching toFind, or -1 if it doesn't exist.
-	int findLast(DsrChar toFind) const;
-	// Exclusive intervals represent the divisions between characters |⁰ A |¹ B |² C |³...
-	//   0..2 of "ABC" then equals "AB", which has length 2 just like the index difference
-	//   0..3 gets the whole "ABC" range, by starting from zero and ending with the character count
-	ReadableString exclusiveRange(int inclusiveStart, int exclusiveEnd) const;
-	// Inclusive intervals represent whole characters | A⁰ | B¹ | C² |...
-	//   0..2 of "ABC" then equals "ABC", by taking character 0 (A), 1 (B) and 2 (C)
-	ReadableString inclusiveRange(int inclusiveStart, int inclusiveEnd) const;
-	// Simplified ranges
-	ReadableString before(int exclusiveEnd) const;
-	ReadableString until(int inclusiveEnd) const;
-	ReadableString from(int inclusiveStart) const;
-	ReadableString after(int exclusiveStart) const;
-	// Value conversion
+	// TODO: Remove
 	int64_t toInteger() const;
 	int64_t toInteger() const;
 	double toDouble() const;
 	double toDouble() const;
 };
 };
@@ -128,13 +112,12 @@ protected:
 	std::shared_ptr<Buffer> buffer;
 	std::shared_ptr<Buffer> buffer;
 	// Same as readSection, but with write access
 	// Same as readSection, but with write access
 	char32_t* writeSection = nullptr;
 	char32_t* writeSection = nullptr;
+	// Internal constructor
+	String(std::shared_ptr<Buffer> buffer, DsrChar *content, int sectionLength);
 public:
 public:
 	// The number of DsrChar characters that can be contained in the allocation before reaching the buffer's end
 	// The number of DsrChar characters that can be contained in the allocation before reaching the buffer's end
 	//   This doesn't imply that it's always okay to write to the remaining space, because the buffer may be shared
 	//   This doesn't imply that it's always okay to write to the remaining space, because the buffer may be shared
 	int capacity();
 	int capacity();
-protected:
-	// Internal constructor
-	String(std::shared_ptr<Buffer> buffer, DsrChar *content, int sectionLength);
 	// Create a string from the existing buffer without allocating any heap memory
 	// Create a string from the existing buffer without allocating any heap memory
 	ReadableString getRange(int start, int length) const override;
 	ReadableString getRange(int start, int length) const override;
 private:
 private:
@@ -215,6 +198,15 @@ std::ostream& string_toStream(std::ostream& target, const T& source) {
 // ---------------- Procedural API ----------------
 // ---------------- Procedural API ----------------
 
 
 
 
+int string_findFirst(const ReadableString& source, DsrChar toFind, int startIndex = 0);
+int string_findLast(const ReadableString& source, DsrChar toFind);
+ReadableString string_exclusiveRange(const ReadableString& source, int inclusiveStart, int exclusiveEnd);
+ReadableString string_inclusiveRange(const ReadableString& source, int inclusiveStart, int inclusiveEnd);
+ReadableString string_before(const ReadableString& source, int exclusiveEnd);
+ReadableString string_until(const ReadableString& source, int inclusiveEnd);
+ReadableString string_from(const ReadableString& source, int inclusiveStart);
+ReadableString string_after(const ReadableString& source, int exclusiveStart);
+
 // Post-condition:
 // Post-condition:
 //   Returns a list of strings from source by splitting along separator.
 //   Returns a list of strings from source by splitting along separator.
 // The separating characters are excluded from the resulting strings.
 // The separating characters are excluded from the resulting strings.

+ 3 - 3
Source/DFPSR/font/Font.cpp

@@ -160,7 +160,7 @@ void RasterFontImpl::printMultiLine(ImageRgbaU8& target, const ReadableString& c
 		DsrChar code = content[i];
 		DsrChar code = content[i];
 		if (code == 10) {
 		if (code == 10) {
 			// Print the completed line
 			// Print the completed line
-			this->printLine(target, content.exclusiveRange(rowStartIndex, i), IVector2D(bound.left(), y), color);
+			this->printLine(target, string_exclusiveRange(content, rowStartIndex, i), IVector2D(bound.left(), y), color);
 			y += this->size; if (y + this->size > bound.bottom()) { return; }
 			y += this->size; if (y + this->size > bound.bottom()) { return; }
 			lineWidth = 0;
 			lineWidth = 0;
 			rowStartIndex = i + 1;
 			rowStartIndex = i + 1;
@@ -181,7 +181,7 @@ void RasterFontImpl::printMultiLine(ImageRgbaU8& target, const ReadableString& c
 						// The word is too big to be printed as a whole
 						// The word is too big to be printed as a whole
 						splitIndex = i;
 						splitIndex = i;
 					}
 					}
-					ReadableString partialLine = content.exclusiveRange(rowStartIndex, splitIndex);
+					ReadableString partialLine = string_exclusiveRange(content, rowStartIndex, splitIndex);
 					int partialLength = this->getLineWidth(partialLine);
 					int partialLength = this->getLineWidth(partialLine);
 					if (partialLength <= bound.width()) {
 					if (partialLength <= bound.width()) {
 						this->printLine(target, partialLine, IVector2D(bound.left(), y), color);
 						this->printLine(target, partialLine, IVector2D(bound.left(), y), color);
@@ -205,7 +205,7 @@ void RasterFontImpl::printMultiLine(ImageRgbaU8& target, const ReadableString& c
 			}
 			}
 		}
 		}
 	}
 	}
-	this->printLine(target, content.from(rowStartIndex), IVector2D(bound.left(), y), color);
+	this->printLine(target, string_from(content, rowStartIndex), IVector2D(bound.left(), y), color);
 }
 }
 
 
 int32_t RasterFontImpl::getLineWidth(const ReadableString& content) const {
 int32_t RasterFontImpl::getLineWidth(const ReadableString& content) const {

+ 6 - 6
Source/DFPSR/gui/FlexRegion.cpp

@@ -28,17 +28,17 @@ using namespace dsr;
 PERSISTENT_DEFINITION(FlexValue)
 PERSISTENT_DEFINITION(FlexValue)
 
 
 bool FlexValue::assignValue(const ReadableString &text) {
 bool FlexValue::assignValue(const ReadableString &text) {
-	int perCentIndex = text.findFirst('%');
+	int perCentIndex = string_findFirst(text, U'%');
 	if (perCentIndex > -1) {
 	if (perCentIndex > -1) {
 		// Explicit %
 		// Explicit %
-		ReadableString leftSide = text.before(perCentIndex);
-		ReadableString rightSide = text.after(perCentIndex);
-		this->ratio = leftSide.toInteger();
-		this->offset = rightSide.toInteger();
+		ReadableString leftSide = string_before(text, perCentIndex);
+		ReadableString rightSide = string_after(text, perCentIndex);
+		this->ratio = string_toInteger(leftSide);
+		this->offset = string_toInteger(rightSide);
 	} else {
 	} else {
 		// Implicitly 0%
 		// Implicitly 0%
 		this->ratio = 0;
 		this->ratio = 0;
-		this->offset = text.toInteger();
+		this->offset = string_toInteger(text);
 	}
 	}
 	return true; // TODO: Discriminate bad input
 	return true; // TODO: Discriminate bad input
 }
 }

+ 10 - 10
Source/DFPSR/machine/VirtualMachine.cpp

@@ -43,15 +43,15 @@ VirtualMachine::VirtualMachine(const ReadableString& code, const std::shared_ptr
 	for (int l = 0; l < lines.length(); l++) {
 	for (int l = 0; l < lines.length(); l++) {
 		ReadableString currentLine = lines[l];
 		ReadableString currentLine = lines[l];
 		// If the line has a comment, then skip everything from #
 		// If the line has a comment, then skip everything from #
-		int commentIndex = currentLine.findFirst(U'#');
+		int commentIndex = string_findFirst(currentLine, U'#');
 		if (commentIndex > -1) {
 		if (commentIndex > -1) {
-			currentLine = currentLine.before(commentIndex);
+			currentLine = string_before(currentLine, commentIndex);
 		}
 		}
 		currentLine = string_removeOuterWhiteSpace(currentLine);
 		currentLine = string_removeOuterWhiteSpace(currentLine);
-		int colonIndex = currentLine.findFirst(U':');
+		int colonIndex = string_findFirst(currentLine, U':');
 		if (colonIndex > -1) {
 		if (colonIndex > -1) {
-			ReadableString command = string_removeOuterWhiteSpace(currentLine.before(colonIndex));
-			ReadableString argumentLine = currentLine.after(colonIndex);
+			ReadableString command = string_removeOuterWhiteSpace(string_before(currentLine, colonIndex));
+			ReadableString argumentLine = string_after(currentLine, colonIndex);
 			string_split_inPlace(arguments, argumentLine, U',');
 			string_split_inPlace(arguments, argumentLine, U',');
 			this->interpretMachineWord(command, arguments);
 			this->interpretMachineWord(command, arguments);
 		} else if (currentLine.length() > 0) {
 		} else if (currentLine.length() > 0) {
@@ -192,12 +192,12 @@ VMA VirtualMachine::VMAfromText(int methodIndex, const ReadableString& content)
 	} else if (first >= U'0' && first <= U'9') {
 	} else if (first >= U'0' && first <= U'9') {
 		return VMA(FixedPoint::fromText(content));
 		return VMA(FixedPoint::fromText(content));
 	} else {
 	} else {
-		int leftIndex = content.findFirst(U'<');
-		int rightIndex = content.findLast(U'>');
+		int leftIndex = string_findFirst(content, U'<');
+		int rightIndex = string_findLast(content, U'>');
 		if (leftIndex > -1 && rightIndex > -1) {
 		if (leftIndex > -1 && rightIndex > -1) {
-			ReadableString name = string_removeOuterWhiteSpace(content.before(leftIndex));
-			ReadableString typeName = string_removeOuterWhiteSpace(content.inclusiveRange(leftIndex + 1, rightIndex - 1));
-			ReadableString remainder = string_removeOuterWhiteSpace(content.after(rightIndex));
+			ReadableString name = string_removeOuterWhiteSpace(string_before(content, leftIndex));
+			ReadableString typeName = string_removeOuterWhiteSpace(string_inclusiveRange(content, leftIndex + 1, rightIndex - 1));
+			ReadableString remainder = string_removeOuterWhiteSpace(string_after(content, rightIndex));
 			if (remainder.length() > 0) {
 			if (remainder.length() > 0) {
 				throwError("No code allowed after > for in-place temp declarations!\n");
 				throwError("No code allowed after > for in-place temp declarations!\n");
 			}
 			}

+ 7 - 7
Source/DFPSR/math/FixedPoint.cpp

@@ -255,15 +255,15 @@ FixedPoint FixedPoint::fromMantissa(int64_t mantissa) {
 
 
 FixedPoint FixedPoint::fromText(const ReadableString& text) {
 FixedPoint FixedPoint::fromText(const ReadableString& text) {
 	ReadableString content = string_removeOuterWhiteSpace(text);
 	ReadableString content = string_removeOuterWhiteSpace(text);
-	bool isSigned = content.findFirst(U'-') > -1; // Should also be last
-	int decimal = content.findFirst(U'.');
-	int colon = content.findFirst(U':');
+	bool isSigned = string_findFirst(content, U'-') > -1; // Should also be last
+	int decimal = string_findFirst(content, U'.');
+	int colon = string_findFirst(content, U':');
 	int64_t result = 0;
 	int64_t result = 0;
 	if (decimal > -1 && colon == -1) {
 	if (decimal > -1 && colon == -1) {
 		// Floating-point decimal
 		// Floating-point decimal
 		// TODO: Give warnings for incorrect whole integers
 		// TODO: Give warnings for incorrect whole integers
-		int64_t wholeInteger = string_parseInteger(content.before(decimal));
-		ReadableString decimals = content.after(decimal);
+		int64_t wholeInteger = string_parseInteger(string_before(content, decimal));
+		ReadableString decimals = string_after(content, decimal);
 		uint64_t fraction = 0; // Extra high precision for accumulation
 		uint64_t fraction = 0; // Extra high precision for accumulation
 		for (int i = 0; i < decimals.length(); i++) {
 		for (int i = 0; i < decimals.length(); i++) {
 			DsrChar digit = decimals[i];
 			DsrChar digit = decimals[i];
@@ -278,8 +278,8 @@ FixedPoint FixedPoint::fromText(const ReadableString& text) {
 	} else if (decimal == -1 && colon > -1) {
 	} else if (decimal == -1 && colon > -1) {
 		// Whole integer and 16-bit fraction
 		// Whole integer and 16-bit fraction
 		// TODO: Give warnings for incorrect integers
 		// TODO: Give warnings for incorrect integers
-		int64_t wholeInteger = string_parseInteger(content.before(colon));
-		int64_t fraction = string_parseInteger(content.after(colon));
+		int64_t wholeInteger = string_parseInteger(string_before(content, colon));
+		int64_t fraction = string_parseInteger(string_after(content, colon));
 		clampForSaturatedWhole(wholeInteger);
 		clampForSaturatedWhole(wholeInteger);
 		if (isSigned) { fraction = -fraction; }
 		if (isSigned) { fraction = -fraction; }
 		result = (wholeInteger * 65536) + fraction;
 		result = (wholeInteger * 65536) + fraction;

+ 6 - 6
Source/DFPSR/persistent/ClassFactory.cpp

@@ -141,19 +141,19 @@ std::shared_ptr<Persistent> dsr::createPersistentClassFromText(const ReadableStr
 	List<ReadableString> lines = string_split(text, U'\n');
 	List<ReadableString> lines = string_split(text, U'\n');
 	for (int l = 0; l < lines.length(); l++) {
 	for (int l = 0; l < lines.length(); l++) {
 		ReadableString line = lines[l];
 		ReadableString line = lines[l];
-		int equalityIndex = line.findFirst('=');
+		int equalityIndex = string_findFirst(line, '=');
 		if (equalityIndex > -1) {
 		if (equalityIndex > -1) {
 			// Assignment
 			// Assignment
-			String key = string_removeOuterWhiteSpace(line.before(equalityIndex));
-			String value = string_removeOuterWhiteSpace(line.after(equalityIndex));
+			String key = string_removeOuterWhiteSpace(string_before(line, equalityIndex));
+			String value = string_removeOuterWhiteSpace(string_after(line, equalityIndex));
 			stack.last()->setProperty(key, value);
 			stack.last()->setProperty(key, value);
 		} else {
 		} else {
-			int colonIndex = line.findFirst(':');
+			int colonIndex = string_findFirst(line, ':');
 			if (colonIndex > -1) {
 			if (colonIndex > -1) {
 				// Declaration
 				// Declaration
-				String keyword = string_removeOuterWhiteSpace(line.before(colonIndex));
+				String keyword = string_removeOuterWhiteSpace(string_before(line, colonIndex));
 				if (string_caseInsensitiveMatch(keyword, U"Begin")) {
 				if (string_caseInsensitiveMatch(keyword, U"Begin")) {
-					String type = string_removeOuterWhiteSpace(line.after(colonIndex));
+					String type = string_removeOuterWhiteSpace(string_after(line, colonIndex));
 					newObject = dsr::createPersistentClass(type);
 					newObject = dsr::createPersistentClass(type);
 					if (rootObject.get() == nullptr) {
 					if (rootObject.get() == nullptr) {
 						rootObject = newObject;
 						rootObject = newObject;

+ 1 - 1
Source/DFPSR/persistent/atomic/PersistentStringList.cpp

@@ -41,7 +41,7 @@ bool PersistentStringList::assignValue(const ReadableString &text) {
 				i++; // Skip the following character as content
 				i++; // Skip the following character as content
 			} else if (c == U'\"') { // Quote sign
 			} else if (c == U'\"') { // Quote sign
 				// End the quote
 				// End the quote
-				String content = string_unmangleQuote(string_removeOuterWhiteSpace(text.inclusiveRange(start, i)));
+				String content = string_unmangleQuote(string_removeOuterWhiteSpace(string_inclusiveRange(text, start, i)));
 				this->value.push(content);
 				this->value.push(content);
 				hadComma = false;
 				hadComma = false;
 				quoted = false;
 				quoted = false;

+ 2 - 2
Source/DFPSR/render/ResourcePool.cpp

@@ -45,9 +45,9 @@ const ImageRgbaU8 BasicResourcePool::fetchImageRgba(const String& name) {
 		int existingIndex = this->findImageRgba(name);
 		int existingIndex = this->findImageRgba(name);
 		if (existingIndex > -1) {
 		if (existingIndex > -1) {
 			result = imageRgbaList[existingIndex].ref;
 			result = imageRgbaList[existingIndex].ref;
-		} else if (name.findFirst(U'.') > -1) {
+		} else if (string_findFirst(name, U'.') > -1) {
 			throwError("The image \"", name, "\" had a forbidden dot in the name. Images in resource pools are fetched without the extension to allow changing image format without changing what it's called in other resources.\n");
 			throwError("The image \"", name, "\" had a forbidden dot in the name. Images in resource pools are fetched without the extension to allow changing image format without changing what it's called in other resources.\n");
-		} else if (name.findFirst(U'/') > -1 && name.findFirst(U'\\') > -1) {
+		} else if (string_findFirst(name, U'/') > -1 && string_findFirst(name, U'\\') > -1) {
 			throwError("The image \"", name, "\" contained a path separator, which is not allowed because of ambiguity. The same file can have multiple paths to the same folder and multiple files can have the same name in different folders.\n");
 			throwError("The image \"", name, "\" contained a path separator, which is not allowed because of ambiguity. The same file can have multiple paths to the same folder and multiple files can have the same name in different folders.\n");
 		} else {
 		} else {
 			// Look for a png image
 			// Look for a png image

+ 4 - 4
Source/DFPSR/render/model/format/dmf1.cpp

@@ -229,7 +229,7 @@ static void readToken(ParserState &state, const String &fileContent, int start,
 		if (fileContent[start] == U'(' && fileContent[end] == U')') {
 		if (fileContent[start] == U'(' && fileContent[end] == U')') {
 			// Property
 			// Property
 			if (state.parserState == ParserState_WaitForProperty || state.parserState == ParserState_WaitForIndexOrProperty) {
 			if (state.parserState == ParserState_WaitForProperty || state.parserState == ParserState_WaitForIndexOrProperty) {
-				setProperty(state, state.lastPropertyName, state.propertyIndex, fileContent.inclusiveRange(start + 1, end - 1));
+				setProperty(state, state.lastPropertyName, state.propertyIndex, string_inclusiveRange(fileContent, start + 1, end - 1));
 				state.parserState = ParserState_WaitForStatement;
 				state.parserState = ParserState_WaitForStatement;
 				state.propertyIndex = 0; // Reset index for the next property
 				state.propertyIndex = 0; // Reset index for the next property
 			} else {
 			} else {
@@ -238,7 +238,7 @@ static void readToken(ParserState &state, const String &fileContent, int start,
 		} else if (fileContent[start] == U'[' && fileContent[end] == U']') {
 		} else if (fileContent[start] == U'[' && fileContent[end] == U']') {
 			// Index
 			// Index
 			if (state.parserState == ParserState_WaitForIndexOrProperty) {
 			if (state.parserState == ParserState_WaitForIndexOrProperty) {
-				state.propertyIndex = roundIndex(string_parseDouble(fileContent.inclusiveRange(start + 1, end - 1)));
+				state.propertyIndex = roundIndex(string_parseDouble(string_inclusiveRange(fileContent, start + 1, end - 1)));
 			} else {
 			} else {
 				printText("Unexpected index!\n");
 				printText("Unexpected index!\n");
 			}
 			}
@@ -249,7 +249,7 @@ static void readToken(ParserState &state, const String &fileContent, int start,
 					printText("Name of namespace is too long!\n");
 					printText("Name of namespace is too long!\n");
 				} else {
 				} else {
 					// Change namespace and create things
 					// Change namespace and create things
-					changeNamespace(state, fileContent.inclusiveRange(start + 1, end - 1));
+					changeNamespace(state, string_inclusiveRange(fileContent, start + 1, end - 1));
 				}
 				}
 			} else {
 			} else {
 				printText("Change of namespace before finishing the last statement!\n");
 				printText("Change of namespace before finishing the last statement!\n");
@@ -261,7 +261,7 @@ static void readToken(ParserState &state, const String &fileContent, int start,
 				if (end - start > 258) {
 				if (end - start > 258) {
 					printText("Name of property is too long!\n");
 					printText("Name of property is too long!\n");
 				} else {
 				} else {
-					state.lastPropertyName = fileContent.inclusiveRange(start, end);
+					state.lastPropertyName = string_inclusiveRange(fileContent, start, end);
 					state.parserState = ParserState_WaitForIndexOrProperty;
 					state.parserState = ParserState_WaitForIndexOrProperty;
 				}
 				}
 			}
 			}

+ 2 - 2
Source/SDK/sandbox/sprite/spriteAPI.cpp

@@ -979,8 +979,8 @@ static bool approximateTextMatch(const ReadableString &a, const ReadableString &
 			while (isDigit(a[readerA])) { readerA++; }
 			while (isDigit(a[readerA])) { readerA++; }
 			while (isDigit(b[readerB])) { readerB++; }
 			while (isDigit(b[readerB])) { readerB++; }
 			// Approximate values
 			// Approximate values
-			double valueA = string_parseDouble(a.exclusiveRange(startA, readerA));
-			double valueB = string_parseDouble(b.exclusiveRange(startB, readerB));
+			double valueA = string_parseDouble(string_exclusiveRange(a, startA, readerA));
+			double valueB = string_parseDouble(string_exclusiveRange(b, startB, readerB));
 			// Check the difference
 			// Check the difference
 			double diff = valueB - valueA;
 			double diff = valueB - valueA;
 			if (diff > tolerance || diff < -tolerance) {
 			if (diff > tolerance || diff < -tolerance) {

+ 13 - 13
Source/SDK/sandbox/tool.cpp

@@ -597,11 +597,11 @@ static void loadPlyModel(ParserState& state, const ReadableString& content, bool
 }
 }
 
 
 static void loadModel(ParserState& state, const ReadableString& filename, bool shadow, bool flipX) {
 static void loadModel(ParserState& state, const ReadableString& filename, bool shadow, bool flipX) {
-	int lastDotIndex = filename.findLast(U'.');
+	int lastDotIndex = string_findLast(filename, U'.');
 	if (lastDotIndex == -1) {
 	if (lastDotIndex == -1) {
 		printText("The model's filename ", filename, " does not have an extension!\n");
 		printText("The model's filename ", filename, " does not have an extension!\n");
 	} else {
 	} else {
-		ReadableString extension = filename.after(lastDotIndex);
+		ReadableString extension = string_after(filename, lastDotIndex);
 		if (string_caseInsensitiveMatch(extension, U"PLY")) {
 		if (string_caseInsensitiveMatch(extension, U"PLY")) {
 			// Store the whole model file in a string for fast reading
 			// Store the whole model file in a string for fast reading
 			String content = string_load(state.sourcePath + filename);
 			String content = string_load(state.sourcePath + filename);
@@ -729,23 +729,23 @@ static void parse_dsm(ParserState& state, const ReadableString& content) {
 		// Get the current line
 		// Get the current line
 		ReadableString line = lines[l];
 		ReadableString line = lines[l];
 		// Skip comments
 		// Skip comments
-		int commentIndex = line.findFirst(U';');
+		int commentIndex = string_findFirst(line, U';');
 		if (commentIndex > -1) {
 		if (commentIndex > -1) {
-			line = string_removeOuterWhiteSpace(line.before(commentIndex));
+			line = string_removeOuterWhiteSpace(string_before(line, commentIndex));
 		}
 		}
 		if (line.length() > 0) {
 		if (line.length() > 0) {
 			// Find assignments
 			// Find assignments
-			int assignmentIndex = line.findFirst(U'=');
-			int colonIndex = line.findFirst(U':');
-			int blockStartIndex = line.findFirst(U'<');
-			int blockEndIndex = line.findFirst(U'>');
+			int assignmentIndex = string_findFirst(line, U'=');
+			int colonIndex = string_findFirst(line, U':');
+			int blockStartIndex = string_findFirst(line, U'<');
+			int blockEndIndex = string_findFirst(line, U'>');
 			if (assignmentIndex > -1) {
 			if (assignmentIndex > -1) {
-				ReadableString key = string_removeOuterWhiteSpace(line.before(assignmentIndex));
-				ReadableString value = string_removeOuterWhiteSpace(line.after(assignmentIndex));
+				ReadableString key = string_removeOuterWhiteSpace(string_before(line, assignmentIndex));
+				ReadableString value = string_removeOuterWhiteSpace(string_after(line, assignmentIndex));
 				parse_assignment(state, key, value);
 				parse_assignment(state, key, value);
 			} else if (colonIndex > -1) {
 			} else if (colonIndex > -1) {
-				ReadableString command = string_removeOuterWhiteSpace(line.before(colonIndex));
-				ReadableString argContent = line.after(colonIndex);
+				ReadableString command = string_removeOuterWhiteSpace(string_before(line, colonIndex));
+				ReadableString argContent = string_after(line, colonIndex);
 				string_split_inPlace(args, argContent, U',');
 				string_split_inPlace(args, argContent, U',');
 				for (int a = 0; a < args.length(); a++) {
 				for (int a = 0; a < args.length(); a++) {
 					args[a] = string_removeOuterWhiteSpace(args[a]);
 					args[a] = string_removeOuterWhiteSpace(args[a]);
@@ -758,7 +758,7 @@ static void parse_dsm(ParserState& state, const ReadableString& content) {
 					printText("    Unrecognized command ", command, ".\n");
 					printText("    Unrecognized command ", command, ".\n");
 				}
 				}
 			} else if (blockStartIndex > -1 && blockEndIndex > -1) {
 			} else if (blockStartIndex > -1 && blockEndIndex > -1) {
-				String block = string_removeOuterWhiteSpace(line.inclusiveRange(blockStartIndex + 1, blockEndIndex - 1));
+				String block = string_removeOuterWhiteSpace(string_inclusiveRange(line, blockStartIndex + 1, blockEndIndex - 1));
 				parse_scope(state, block);
 				parse_scope(state, block);
 			} else {
 			} else {
 				printText("Unrecognized content \"", line, "\" on line ", l + 1, ".\n");
 				printText("Unrecognized content \"", line, "\" on line ", l + 1, ".\n");

+ 9 - 9
Source/test/tests/StringTest.cpp

@@ -46,15 +46,15 @@ START_TEST(String)
 	{ // Sub-strings
 	{ // Sub-strings
 		dsr::ReadableString abcd = U"abcd";
 		dsr::ReadableString abcd = U"abcd";
 		dsr::String efgh = U"efgh";
 		dsr::String efgh = U"efgh";
-		ASSERT_MATCH(abcd.inclusiveRange(0, 3), U"abcd");
-		ASSERT_MATCH(abcd.exclusiveRange(1, 2), U"b");
-		ASSERT_MATCH(efgh.inclusiveRange(2, 3), U"gh");
-		ASSERT_MATCH(efgh.exclusiveRange(3, 4), U"h");
-		ASSERT_MATCH(dsr::string_combine(abcd.from(2), efgh.before(2)), U"cdef");
-		ASSERT_MATCH(abcd.exclusiveRange(0, 0), U""); // No size returns nothing
-		ASSERT_MATCH(abcd.exclusiveRange(-1, -2), U""); // A negative size doesn't have to be inside
-		ASSERT_CRASH(abcd.inclusiveRange(-1, -1)); // Index below bound expected
-		ASSERT_CRASH(abcd.inclusiveRange(4, 4)); // Index above bound expected
+		ASSERT_MATCH(dsr::string_inclusiveRange(abcd, 0, 3), U"abcd");
+		ASSERT_MATCH(dsr::string_exclusiveRange(abcd, 1, 2), U"b");
+		ASSERT_MATCH(dsr::string_inclusiveRange(efgh, 2, 3), U"gh");
+		ASSERT_MATCH(dsr::string_exclusiveRange(efgh, 3, 4), U"h");
+		ASSERT_MATCH(dsr::string_combine(string_from(abcd, 2), string_before(efgh, 2)), U"cdef");
+		ASSERT_MATCH(dsr::string_exclusiveRange(abcd, 0, 0), U""); // No size returns nothing
+		ASSERT_MATCH(dsr::string_exclusiveRange(abcd, -1, -2), U""); // A negative size doesn't have to be inside
+		ASSERT_CRASH(dsr::string_inclusiveRange(abcd, -1, -1)); // Index below bound expected
+		ASSERT_CRASH(dsr::string_inclusiveRange(abcd, 4, 4)); // Index above bound expected
 	}
 	}
 	{ // Processing
 	{ // Processing
 		dsr::String buffer = U"Garbage";
 		dsr::String buffer = U"Garbage";