+// text.cpp - Text functions.
+//
+// (c) 2016-2017 Xestia Software Development.
+//
+// This file is part of Xestia Calendar.
+//
+// Xestia Calendar is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by the
+// Free Software Foundation, version 3 of the license.
+//
+// Xestia Calendar is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with Xestia Calendar. If not, see <http://www.gnu.org/licenses/>
+
#include "text.h"
using namespace std;
-multimap<string, string> ProcessTextVectors(vector<string> *TextProperties,
- vector<string> *TextValues,
- bool SearchMultiple,
- string Property){
+multimap<string, string> ProcessTextVectors(vector<string> *textProperties,
+ vector<string> *textValues,
+ bool searchMultiple,
+ string property){
- multimap<string,string> ProcessResult;
+ multimap<string,string> processResult;
// Go through each of the values.
- int TextSeekCount = 0;
- int TextPropertySize = 0;
- int PropertySeekCount = 0;
+ int textSeekCount = 0;
+ int textPropertySize = 0;
+ int propertySeekCount = 0;
+ string propertyName = "";
+ int propertyNameSize = 0;
+ char bufferChar = 0;
+
+ for (vector<string>::iterator iter = textProperties->begin();
+ iter != textProperties->end(); iter++){
+
+ textPropertySize = iter->size();
+
+ if (textPropertySize == 0){
+
+ // Text property size is 0. Go to the next
+ // pair.
+
+ continue;
+
+ }
+
+ // Get the property data up to the first semi-colon.
+
+ while (textSeekCount < textPropertySize){
+
+ bufferChar = (*iter)[textSeekCount];
+
+ if (bufferChar == ';'){
+ break;
+ }
+
+ propertyName += bufferChar;
+
+ textSeekCount++;
+
+ }
+
+ if (*iter == property || propertyName == property){
+
+ processResult.insert(make_pair((*textProperties)[propertySeekCount],
+ (*textValues)[propertySeekCount]));
+
+ // Check to continue if one is found.
+
+ if (searchMultiple == false){
+
+ // Found one, don't search for anymore.
+
+ break;
+
+ }
+
+ }
+
+ propertySeekCount++;
+ textPropertySize = 0;
+ textSeekCount = 0;
+ propertyName.clear();
+
+ }
+
+ return processResult;
+
+}
+
+map<string, string> SplitValues(string inputData){
+
+ map<string,string> finalSplitValues;
+ map<int,int> splitPoints;
+ map<int,int> splitLength;
+ size_t intPropertyLen = inputData.size();
+ int intSplitsFound = 0;
+ int intSplitSize = 0;
+ int intSplitSeek = 0;
+ int intPrevSplitFound = 0;
+
+ // Get the split points.
+
+ for (int i = 0; i <= intPropertyLen; i++){
+
+ intSplitSize++;
+
+ inputData.substr(intPrevSplitFound, intSplitSize);
+
+ if (inputData.substr(i, 1) == ";" &&
+ inputData.substr((i - 1), 1) != "\\"){
+
+ if (intSplitsFound > 0){
+
+ // Split the value into two.
+
+ PropertyNameValue nVData = SplitNameValue(inputData.substr(intPrevSplitFound, (intSplitSize - 1)));
+
+ if (finalSplitValues.find(nVData.name) != finalSplitValues.end()){
+ finalSplitValues.insert(make_pair(nVData.name, nVData.value));
+ } else {
+ finalSplitValues[nVData.name] = nVData.value;
+ }
+
+ }
+
+ intPrevSplitFound = i + 1;
+ intSplitSize = 0;
+ intSplitsFound++;
+
+ }
+
+ }
+
+ if (intSplitsFound > 0){
+
+ PropertyNameValue nVData = SplitNameValue(inputData.substr(intPrevSplitFound, (intSplitSize - 1)));
+
+ if (finalSplitValues.find(nVData.name) != finalSplitValues.end()){
+ finalSplitValues.insert(make_pair(nVData.name, nVData.value));
+ } else {
+ finalSplitValues[nVData.name] = nVData.value;
+ }
- for (vector<string>::iterator iter = TextProperties->begin();
- iter != TextProperties->end(); iter++){
+ }
- if (*iter == Property){
+ return finalSplitValues;
+
+}
+
+PropertyNameValue SplitNameValue(string inputData){
+
+ PropertyNameValue finalNameValue;
+ int inputDataLength = inputData.size();
+ int seekCount = 0;
+ bool quoteMode = false;
+ bool dataFound = false;
+
+ while (seekCount < inputDataLength){
+
+ if (inputData[seekCount] == '='){
+
+ finalNameValue.name = inputData.substr(0, seekCount);
- ProcessResult.insert(make_pair((*TextProperties)[PropertySeekCount],
- (*TextValues)[PropertySeekCount]));
+ try{
+ finalNameValue.value = inputData.substr((seekCount + 1));
+ }
+ catch (const out_of_range &oor){
+ // Do nothing. Have an empty final value.
+ }
+
+ dataFound = true;
+ break;
}
+
+ seekCount++;
+
+ }
+
+ if (dataFound == false){
+
+ finalNameValue.name = inputData;
+
+ }
+
+ // Check if the value has quotes at the start and end.
+ // Remove them if this is the case.
+
+ if (finalNameValue.value.front() == '\"' &&
+ finalNameValue.value.back() == '\"'){
+
+ finalNameValue.value.erase(0, 1);
+ finalNameValue.value.erase((finalNameValue.value.size() - 1), 1);
- PropertySeekCount++;
+ }
+
+ return finalNameValue;
+
+}
+
+bool HexToInt(std::string *hexString, int *number){
+
+ // Check that each character in the string is a number
+ // or a letter (a-f/A-F).
+
+ char charLetter = 0;
+ int charNum = 0;
+
+ for (int charSeek = 0;
+ charSeek < hexString->size(); charSeek++){
+
+ // Check if character is a number (0-9).
+ charLetter = hexString->at(charSeek);
+ charNum = charLetter;
+
+ if (charNum >= 48 &&
+ charNum <= 57){
+
+ continue;
+
+ }
+
+ // Check if character is a letter (A-F)
+
+ if (charNum >= 65 &&
+ charNum <= 70){
+
+ continue;
+
+ }
+
+ // Check if character is a letter (a-f).
+
+ if (charNum >= 97 &&
+ charNum <= 102){
+
+ continue;
+
+ }
+
+ // Exit from subroutine as character is invalid.
+
+ return false;
+
+ }
+
+ // Convert a Hex value that is in string to integer.
+
+ try {
+
+ *number = stoi((*hexString), nullptr, 16);
+
}
+
+ catch (const std::invalid_argument &err){
- return ProcessResult;
+ return false;
+
+ }
+
+ catch (const std::out_of_range &err){
+
+ return false;
+
+ }
+
+ return true;
+
+}
+
+bool IntToHex(int *number, std::string *hexString, int hexFill){
+
+ stringstream stringData;
+ stringData << setfill('0') << hex << setw(hexFill) << (*number);
+ (*hexString) = stringData.str();
+
+ return true;
+
+}
+
+void SplitPathFilename(string *calendarEntryHREF, string *entryURIPath,
+ string *entryFilename){
+
+ // Look for the last forward slash.
+ int lastForwardSlash = -1;
+ int charSeek = 0;
+ string stringIterChar = "";
+
+ for (string::iterator stringIter = calendarEntryHREF->begin();
+ stringIter != calendarEntryHREF->end(); stringIter++){
+
+ stringIterChar = *stringIter;
+
+ if (stringIterChar == "/"){
+ lastForwardSlash = charSeek;
+ }
+
+ charSeek++;
+
+ }
+
+ if (lastForwardSlash == -1){
+
+ return;
+
+ }
+
+ // Get the string before the last hash for the path.
+
+ (*entryURIPath) = calendarEntryHREF->substr(0, (lastForwardSlash + 1));
+
+ // Get the string after the last hash for the filename.
+
+ (*entryFilename) = calendarEntryHREF->substr((lastForwardSlash + 1));
+
+}
+
+string OutputText(string *textInput){
+
+ string outputTextData;
+ string outputLine;
+ int charSeek = 0;
+ int lineSeek = 0;
+ int maxLineSeek = 77;
+
+ for (charSeek = 0; charSeek < textInput->size(); charSeek++){
+
+ lineSeek++;
+
+ if (lineSeek == maxLineSeek){
+
+ if (textInput->substr(charSeek, 1) != "\n"){
+ outputLine += textInput->substr(charSeek, 1);
+ }
+ outputLine += "\n";
+ outputTextData += outputLine;
+ outputLine = " ";
+ lineSeek = 0;
+ maxLineSeek = 76;
+ continue;
+
+ }
+
+ outputLine += textInput->substr(charSeek, 1);
+
+ }
+
+ if (outputLine != " "){
+
+ outputTextData += outputLine;
+
+ }
+
+ return outputTextData;
+
}
\ No newline at end of file