#include // Set up DB void marstr::database::setUpDatabase(string dbname, vector fieldnames, vector datatypes) { // Set the name DatabaseName = dbname; // Acquire the field names int i; for (i=1; i<=fieldnames.size(); i++) { FieldNames.push_back(fieldnames[i-1]); } // Acquire the field data types for (i=1; i<=datatypes.size(); i++) { RowDatatypes.push_back(datatypes[i-1]); } } // Adds a pre-created row void marstr::database::addRow(databaserow row) { // Check if the row has the same amount of fields that we expect there to be if (row.RowFields.size() == FieldNames.size()) { Rows.push_back(row); } } // Deletes the specified row void marstr::database::deleteRow(int rowNumber) { // Create a new vector with the specified row omitted vector rows; // Go through existing rows and add them to the above vector // (except rowNumber) int i; for (i=1; i<=Rows.size(); i++) { if (i!=rowNumber) { rows.push_back(Rows[i-1]); } } // Now clear the real vector Rows.clear(); // And add the rows we got to the real rows for (i=1; i<=rows.size(); i++) { Rows.push_back(rows[i-1]); } // Clear the tmp vector rows.clear(); } // Updates the content of a specific field in a specific row void marstr::database::updateFieldInRow(int rowNumber, int fieldNumber, string content) { // Make sure the row and field exist if (rowNumber <= Rows.size() && fieldNumber <= FieldNames.size()) { // When updating a field, it is probably not a null field Rows[rowNumber].RowFields[fieldNumber].NullField = false; // It can be either one of these... so make sure they exist int newInt = 0; short newShort = 0; float newFloat = 0.0f; double newDouble = 0.0f; string newString = content; // Find the datatype for the field int datatype = RowDatatypes[fieldNumber]; // Convert the field if (datatype == MARSTR_DB_INT) { newInt = atoi(content.c_str()); Rows[rowNumber].RowFields[fieldNumber].fieldInt = newInt; } if (datatype == MARSTR_DB_SHORT) { newShort = atoi(content.c_str()); Rows[rowNumber].RowFields[fieldNumber].fieldShort = newShort; } if (datatype == MARSTR_DB_FLOAT) { newFloat = atof(content.c_str()); Rows[rowNumber].RowFields[fieldNumber].fieldFloat = newFloat; } if (datatype == MARSTR_DB_DOUBLE) { newDouble = atof(content.c_str()); Rows[rowNumber].RowFields[fieldNumber].fieldDouble = newDouble; } if (datatype == MARSTR_DB_STRING) { Rows[rowNumber].RowFields[fieldNumber].fieldString = content; } } } // Defines a field to be a null field or not void marstr::database::fieldIsNullField(int rowNumber, int fieldNumber, bool isNull) { // Make sure the row and field exist if (rowNumber <= Rows.size() && fieldNumber <= FieldNames.size()) { Rows[rowNumber].RowFields[fieldNumber].NullField = isNull; } } // Creates an empty db to be filled later void marstr::database::createDatabase(string filename, string dbname, vector fieldnames, vector datatypes) { setUpDatabase(dbname, fieldnames, datatypes); } // Load database, but only the header - no content void marstr::database::openDatabaseLink(string filename) { // Remember file name DatabaseFileName = filename; // File IO object _linkIO = new fileio(); // Open DB _linkIO->openFileForReading(filename); // Read header and version string hdrString = _linkIO->readString(); float hdrVersion = _linkIO->readFloat(); // Check if the header works out string hdrStringCheck = "MARSTRDB"; if (hdrVersion == 1) // String check to be implemented { // Then this is a valid database DatabaseFileName = filename; // Read database name DatabaseName = _linkIO->readString(); // Get number of field names int amountOfFields = _linkIO->readInt(); // Read in the field names themselves int i, j; for (i=1; i<=amountOfFields; i++) { FieldNames.push_back(_linkIO->readString()); } // Acquire the data types of each field for (i=1; i<=amountOfFields; i++) { RowDatatypes.push_back(_linkIO->readInt()); } // Number of rows in total int numberOfRows = _linkIO->readInt(); } } databaserow marstr::database::nextDatabaseRow() { // The row to be constructed databaserow row; for (int j=1; j<=FieldNames.size(); j++) { // The field to be added to the row databasefield fld; // OK find out if the field has content (null field) int isNullField = _linkIO->readInt(); // If this is a null field, set the field to be so and add it // to the row if (isNullField == 1) { fld.NullField = true; row.RowFields.push_back(fld); } // If we have data, read according to the data type, set the // value into the field, and add the field to the row if (isNullField == 0) { // Not a null field fld.NullField = false; if (RowDatatypes[j-1] == MARSTR_DB_INT) { int fldval = _linkIO->readInt(); fld.fieldInt = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_UINT) { unsigned int fldval = _linkIO->readUInt(); fld.fieldUInt = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_SHORT) { short fldval = _linkIO->readInt(); fld.fieldShort = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_USHORT) { unsigned short fldval = _linkIO->readUShort(); fld.fieldUShort = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_LONG) { long fldval = _linkIO->readLong(); fld.fieldLong = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_ULONG) { unsigned long fldval = _linkIO->readULong(); fld.fieldULong = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_FLOAT) { float fldval = _linkIO->readFloat(); fld.fieldFloat = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_DOUBLE) { double fldval = _linkIO->readDouble(); fld.fieldDouble = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_STRING) { string fldval = _linkIO->readString(); fld.fieldString = fldval; } // Add the field row.RowFields.push_back(fld); } } return row; } void marstr::database::goToFirstRow() { _linkIO->closeFileForReading(); openDatabaseLink(DatabaseFileName); } // Loads a database from file void marstr::database::loadDatabase(string filename) { // File IO object fileio *FileIO = new fileio(); // Remember file name DatabaseFileName = filename; // Open DB FileIO->openFileForReading(filename); // Read header and version string hdrString = FileIO->readString(); float hdrVersion = FileIO->readFloat(); // Check if the header works out string hdrStringCheck = "MARSTRDB"; if (hdrVersion == 1) // String check to be implemented { // Then this is a valid database DatabaseFileName = filename; // Read database name DatabaseName = FileIO->readString(); // Get number of field names int amountOfFields = FileIO->readInt(); // Read in the field names themselves int i, j; for (i=1; i<=amountOfFields; i++) { FieldNames.push_back(FileIO->readString()); } // Acquire the data types of each field for (i=1; i<=amountOfFields; i++) { RowDatatypes.push_back(FileIO->readInt()); } // Number of rows in total int numberOfRows = FileIO->readInt(); // Go through the remainder of the file to acquire the content // of each row and their fields for (i=1; i<=numberOfRows; i++) { // The row to be constructed databaserow row; for (j=1; j<=FieldNames.size(); j++) { // The field to be added to the row databasefield fld; // OK find out if the field has content (null field) int isNullField = FileIO->readInt(); // If this is a null field, set the field to be so and add it // to the row if (isNullField == 1) { fld.NullField = true; row.RowFields.push_back(fld); } // If we have data, read according to the data type, set the // value into the field, and add the field to the row if (isNullField == 0) { // Not a null field fld.NullField = false; if (RowDatatypes[j-1] == MARSTR_DB_INT) { int fldval = FileIO->readInt(); fld.fieldInt = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_UINT) { unsigned int fldval = FileIO->readUInt(); fld.fieldUInt = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_SHORT) { short fldval = FileIO->readInt(); fld.fieldShort = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_USHORT) { unsigned short fldval = FileIO->readUShort(); fld.fieldUShort = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_LONG) { long fldval = FileIO->readLong(); fld.fieldLong = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_ULONG) { unsigned long fldval = FileIO->readULong(); fld.fieldULong = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_FLOAT) { float fldval = FileIO->readFloat(); fld.fieldFloat = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_DOUBLE) { double fldval = FileIO->readDouble(); fld.fieldDouble = fldval; } if (RowDatatypes[j-1] == MARSTR_DB_STRING) { string fldval = FileIO->readString(); fld.fieldString = fldval; } // Add the field row.RowFields.push_back(fld); } } // Add the completed row Rows.push_back(row); } // Magic number check int Magic = (Rows.size() * RowDatatypes.size()); int MagicInFile = FileIO->readInt(); // If the magic does not stack up, clear all data if (Magic != MagicInFile) { Rows.clear(); } } // Close the pipe FileIO->closeFileForReading(); // That's it } // Saves the database to the specified file. Use when everything is done! void marstr::database::saveDatabase() { // File IO object// File IO object fileio *FileIO = new fileio(); // Open the DB FileIO->openFileForWriting(DatabaseFileName); // Write a header FileIO->writeString("MARSTRDB"); // Write a version FileIO->writeFloat(1.0); // Write database name FileIO->writeString(DatabaseName); // Write number of field names FileIO->writeInt(FieldNames.size()); // The field names themselves int i, j; for (i=1; i<=FieldNames.size(); i++) { FileIO->writeString(FieldNames[i-1]); } // The datatypes in each field for (i=1; i<=RowDatatypes.size(); i++) { FileIO->writeInt(RowDatatypes[i-1]); } // Write number of rows FileIO->writeInt(Rows.size()); // Go through the rows and write the content, depending on if the field is // a null field or not for (i=1; i<=Rows.size(); i++) { for (j=1; j<=Rows[i-1].RowFields.size(); j++) { // Write down an int to signalize if the field has data or not int isNull = 0; if (Rows[i-1].RowFields[j-1].NullField == true) { isNull = 1; } if (Rows[i-1].RowFields[j-1].NullField == false) { isNull = 0; } FileIO->writeInt(isNull); // Write actual data if field is not null if (isNull == 0) { if (RowDatatypes[j-1] == MARSTR_DB_SHORT) // short { FileIO->writeInt(Rows[i-1].RowFields[j-1].fieldShort); } if (RowDatatypes[j-1] == MARSTR_DB_INT) // int { FileIO->writeInt(Rows[i-1].RowFields[j-1].fieldInt); } if (RowDatatypes[j-1] == MARSTR_DB_UINT) // uint { FileIO->writeUInt(Rows[i-1].RowFields[j-1].fieldUInt); } if (RowDatatypes[j-1] == MARSTR_DB_LONG) // long { FileIO->writeLong(Rows[i-1].RowFields[j-1].fieldLong); } if (RowDatatypes[j-1] == MARSTR_DB_ULONG) // ulong { FileIO->writeULong(Rows[i-1].RowFields[j-1].fieldULong); } if (RowDatatypes[j-1] == MARSTR_DB_FLOAT) // float { FileIO->writeFloat(Rows[i-1].RowFields[j-1].fieldFloat); } if (RowDatatypes[j-1] == MARSTR_DB_DOUBLE) // double { FileIO->writeDouble(Rows[i-1].RowFields[j-1].fieldDouble); } if (RowDatatypes[j-1] == MARSTR_DB_STRING) // string { FileIO->writeString(Rows[i-1].RowFields[j-1].fieldString); } } } } // Write a magic number for verification int Magic = (Rows.size() * RowDatatypes.size()); FileIO->writeInt(Magic); // Close DB FileIO->closeFileForWriting(); // That's it } void marstr::database::closeDatabase(bool save) { if (save == true) { saveDatabase(); } Rows.clear(); } vector marstr::database::findRowsWithValueInColumn(string value, string colname) { // The result with the index IDs vector rows; // The column index to be searched int colindex = -1; for (int i=0; i