// 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
#include "text.h"
using namespace std;
multimap ProcessTextVectors(vector *TextProperties,
vector *TextValues,
bool SearchMultiple,
string Property){
multimap ProcessResult;
// Go through each of the values.
int TextSeekCount = 0;
int TextPropertySize = 0;
int PropertySeekCount = 0;
string PropertyName = "";
int PropertyNameSize = 0;
char BufferChar = 0;
for (vector::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 SplitValues(string InputData){
map FinalSplitValues;
map SplitPoints;
map 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;
}
}
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);
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);
}
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 Char = 0;
int CharNum = 0;
for (int CharSeek = 0;
CharSeek < HexString->size(); CharSeek++){
// Check if character is a number (0-9).
Char = HexString->at(CharSeek);
CharNum = Char;
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 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;
}