diff --git a/.build/build.options.json b/.build/build.options.json index f213921ea7bd753452aa74a75cd6ff29cf8820aa..f59fa8745aae6da2f326a1c35e785842f57aac6e 100644 --- a/.build/build.options.json +++ b/.build/build.options.json @@ -1,12 +1,12 @@ { - "additionalFiles": "..,..", + "additionalFiles": "", "builtInLibrariesFolders": "/Applications/Arduino.app/Contents/Java/libraries", "builtInToolsFolders": "/Applications/Arduino.app/Contents/Java/tools-builder,/Applications/Arduino.app/Contents/Java/hardware/tools/avr,/Users/to/Library/Arduino15/packages", "compiler.optimization_flags": "", - "customBuildProperties": "build.path=/Users/to/sciebo/TT_Arduino/2_projects/serialTable/.build,build.warn_data_percentage=75,runtime.tools.arduinoOTA.path=/Users/to/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0,runtime.tools.arduinoOTA-1.3.0.path=/Users/to/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0,runtime.tools.avr-gcc.path=/Users/to/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7,runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/Users/to/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7,runtime.tools.avrdude.path=/Users/to/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17,runtime.tools.avrdude-6.3.0-arduino17.path=/Users/to/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17", + "customBuildProperties": "build.path=/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/.build,build.warn_data_percentage=75,runtime.tools.arduinoOTA.path=/Users/to/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0,runtime.tools.arduinoOTA-1.3.0.path=/Users/to/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0,runtime.tools.avr-gcc.path=/Users/to/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7,runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/Users/to/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7,runtime.tools.avrdude.path=/Users/to/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17,runtime.tools.avrdude-6.3.0-arduino17.path=/Users/to/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17", "fqbn": "arduino:avr:mega:cpu=atmega2560", "hardwareFolders": "/Applications/Arduino.app/Contents/Java/hardware,/Users/to/Library/Arduino15/packages", "otherLibrariesFolders": "/Users/to/sciebo/TT_Arduino/libraries", "runtime.ide.version": "10819", - "sketchLocation": "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" + "sketchLocation": "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/examples/serialTable/serialTable.ino" } \ No newline at end of file diff --git a/.build/core/core.a b/.build/core/core.a index 99c9279bdecf1eb3ad99f7f5311871bc732536b1..5c90a050d5c3e3d275975b09158b187121f819b4 100644 Binary files a/.build/core/core.a and b/.build/core/core.a differ diff --git a/.build/includes.cache b/.build/includes.cache index 4b6f9d106d58bc17206fc08fa4719dafc4abee8b..80a7b0161986ea8348c49e3e76210efe1ec7181e 100644 --- a/.build/includes.cache +++ b/.build/includes.cache @@ -10,12 +10,17 @@ "Includepath": "/Users/to/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/variants/mega" }, { - "Sourcefile": "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/.build/sketch/serialTable.ino.cpp", + "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/.build/sketch/serialTable.ino.cpp", + "Include": "UnitTests.h", + "Includepath": "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable" + }, + { + "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/.build/sketch/serialTable.ino.cpp", "Include": "AUnit.h", "Includepath": "/Users/to/sciebo/TT_Arduino/libraries/AUnit/src" }, { - "Sourcefile": "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/.build/sketch/serialTable.ino.cpp", + "Sourcefile": "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/.build/sketch/serialTable.ino.cpp", "Include": "", "Includepath": null }, diff --git a/.build/preproc/ctags_target_for_gcc_minus_e.cpp b/.build/preproc/ctags_target_for_gcc_minus_e.cpp index 924d9e23a4649a66c587fc5ab346018e605291bc..7da623636e616aa97ff591450a0883dcdbf923e5 100644 --- a/.build/preproc/ctags_target_for_gcc_minus_e.cpp +++ b/.build/preproc/ctags_target_for_gcc_minus_e.cpp @@ -1,7 +1,7 @@ -# 1 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" -# 2 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" 2 -# 3 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" 2 -# 4 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/serialTable.ino" 2 +# 1 "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/examples/serialTable/serialTable.ino" +# 2 "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/examples/serialTable/serialTable.ino" 2 +# 3 "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/examples/serialTable/serialTable.ino" 2 +# 4 "/Users/to/sciebo/TT_Arduino/libraries/thk_serialtable/examples/serialTable/serialTable.ino" 2 void setup() { diff --git a/.build/sketch/SerialTable.h b/.build/sketch/SerialTable.h deleted file mode 100644 index 49057b62133c114faeb28f6d41379d1b99dac93e..0000000000000000000000000000000000000000 --- a/.build/sketch/SerialTable.h +++ /dev/null @@ -1,354 +0,0 @@ -#line 1 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/SerialTable.h" -#ifndef SERIALTABLE_H -#define SERIALTABLE_H - -#include <Arduino.h> - -class SerialTable -{ -public: - SerialTable(const char *headers[], const int columnWidths[], size_t size) - : headers(headers), columnWidths(columnWidths), size(size) {} - - // Diese Methode gibt den Header an die serielle Schnittstelle aus - void printHeader() - { - String header = buildHeader(); - Serial.print(header); - } - - String buildHeader() - { - return buildLine('-') + buildRow(const_cast<char **>(headers), '='); // Kopfzeile mit '=' - } - - void printRow(char **t_row) - { - String row = buildRow(t_row); - Serial.print(row); - } - - String buildRow(char **t_row, char line = '-') - { - String output; - char buffer[256]; - int maxLines = 1; // Maximale Anzahl Zeilen über alle Spalten - - // Erste Phase: Teile jede Zelle in Zeilen und finde maximale Zeilenzahl - for (size_t i = 0; i < size; ++i) - { - if (truncateText) - { - truncateToColumnWidth(t_row[i], columnWidths[i], buffer); - } - else - { - splitStringByLength(t_row[i], columnWidths[i], buffer); - } - - // Zähle Zeilen in dieser Zelle - int lineCount = 1; - for (size_t j = 0; j < displayLength(buffer); j++) - { - if (buffer[j] == '\n') - lineCount++; - } - if (lineCount > maxLines) - maxLines = lineCount; - } - - // Zweite Phase: Baue die Zeilen auf - for (int line = 0; line < maxLines; line++) - { - output += "|"; - - // Gehe durch jede Spalte - for (size_t col = 0; col < size; ++col) - { - if (truncateText) - { - truncateToColumnWidth(t_row[col], columnWidths[col], buffer); - } - else - { - splitStringByLength(t_row[col], columnWidths[col], buffer); - } - - // Finde die aktuelle Zeile für diese Spalte - char *currentLine = buffer; - int currentLineNum = 0; - char tempBuffer[256] = ""; - - while (currentLineNum < line) - { - char *newline = strchr(currentLine, '\n'); - if (newline == NULL) - { - currentLine = ""; - break; - } - currentLine = newline + 1; - currentLineNum++; - } - - // Extrahiere die Zeile bis zum nächsten \n oder Ende - int j = 0; - while (currentLine[j] && currentLine[j] != '\n') - { - tempBuffer[j] = currentLine[j]; - j++; - } - tempBuffer[j] = '\0'; - - // Berechne die tatsächliche Anzeigelänge - int printedLength = displayLength(tempBuffer); - - // Füge den Inhalt und die fehlenden Leerzeichen hinzu - output += tempBuffer; - int spacesToAdd = columnWidths[col] - printedLength; - for (int k = 0; k < spacesToAdd; k++) - { - output += " "; - } - output += "|"; - } - output += "\n"; - } - - // Füge die Trennlinie hinzu - output += buildLine(line); - return output; - } - - void setTruncateText(bool value) - { - truncateText = value; - } - -public: // private: - const char **headers; - const int *columnWidths; - size_t size; - bool truncateText = false; - - static int displayLength(const char *text) - { - int length = 0; - for (int i = 0; text[i] != '\0'; ++i) - { - if ((text[i] & 0xC0) != 0x80) - { // Überspringe UTF-8 Fortsetzungsbytes - length++; - } - } - return length; - } - - static void safeStringCopy(char *dest, const char *src, size_t bufferSize) - { - if (strlen(src) >= bufferSize) - { - strncpy(dest, src, bufferSize - 1); - dest[bufferSize - 1] = '\0'; // NULL-termination sichergestellt - } - else - { - strcpy(dest, src); - } - } - - static void replaceUmlauts(char *text) - { - // UTF-8 Codes für Umlaute (hex): ä(c3 a4) ö(c3 b6) ü(c3 bc) Ä(c3 84) Ö(c3 96) Ü(c3 9c) ß(c3 9f) - struct UmlautPair - { - unsigned char bytes[2]; // UTF-8 bytes - const char *replacement; - }; - - const UmlautPair pairs[] = { - {{0xc3, 0xa4}, "ae"}, // ä - {{0xc3, 0xb6}, "oe"}, // ö - {{0xc3, 0xbc}, "ue"}, // ü - {{0xc3, 0x84}, "Ae"}, // Ä - {{0xc3, 0x96}, "Oe"}, // Ö - {{0xc3, 0x9c}, "Ue"}, // Ü - {{0xc3, 0x9f}, "ss"} // ß - }; - const int numPairs = sizeof(pairs) / sizeof(pairs[0]); - - size_t maxOutputLength = strlen(text) * 2 + 1; - char *buffer = (char *)malloc(maxOutputLength); - if (!buffer) - return; - - int k = 0; // Position im Ausgabepuffer - int i = 0; // Position im Eingabetext - - while (text[i] != '\0') - { - bool replaced = false; - - // Prüfe auf UTF-8 Sequenz - if ((unsigned char)text[i] == 0xc3 && text[i + 1] != '\0') - { - for (int j = 0; j < numPairs; ++j) - { - if ((unsigned char)text[i] == pairs[j].bytes[0] && - (unsigned char)text[i + 1] == pairs[j].bytes[1]) - { - // Kopiere Ersetzung - const char *replacement = pairs[j].replacement; - for (int r = 0; replacement[r] != '\0' && k < maxOutputLength - 1; ++r) - { - buffer[k++] = replacement[r]; - } - replaced = true; - i += 2; // Überspringe beide UTF-8 Bytes - break; - } - } - } - - if (!replaced && k < maxOutputLength - 1) - { - buffer[k++] = text[i++]; - } - } - - buffer[k] = '\0'; - strcpy(text, buffer); - free(buffer); - } - - // Neue Version von splitStringByLength - static void splitStringByLength(const char *input, int L, char *output) - { - int len = strlen(input); - int outputIndex = 0; - int currentLength = 0; - - for (int i = 0; i < len; ++i) - { - // Kopiere das aktuelle Zeichen zu Ausgabe - unsigned char curr = input[i]; - output[outputIndex++] = curr; - - // UTF-8-Handling: Überspringe zusätzliche Bytes für ein Multibyte-Zeichen - if ((curr & 0x80) != 0) - { - // Wenn das höchste Bit gesetzt ist, haben wir ein Multibyte-Zeichen - while ((input[i + 1] & 0xC0) == 0x80) - { - output[outputIndex++] = input[++i]; - } - } - - currentLength++; - - // Wenn die maximale Länge erreicht ist und das nächste Zeichen kein newline ist - if (currentLength == L && i + 1 < len && input[i + 1] != '\n') - { - output[outputIndex++] = '\n'; - currentLength = 0; - } - } - output[outputIndex] = '\0'; // Beende den String - } - - void truncateToColumnWidth(const char *input, int width, char *output) - { - int len = strlen(input); - if (len > width) - { - width = (width > 3) ? width - 3 : width; - strncpy(output, input, width); - strcpy(output + width, "..."); - } - else - { - strcpy(output, input); - } - } - - size_t calculateMaxLines(char **t_row) - { - size_t maxLines = 0; - - for (size_t i = 0; i < size; ++i) - { - const char *text = t_row[i]; - size_t textLength = strlen(text); - size_t lines = 1; - - for (size_t j = 0; j < textLength; ++j) - { - if (text[j] == '\n') - { - ++lines; - } - } - - maxLines = max(maxLines, lines); - } - - return maxLines; - } - - const char *getRowSegment(const char *text, int width, size_t line, char *buffer) - { - size_t textLength = strlen(text); - size_t lineStart = 0; - size_t currentLine = 0; - buffer[0] = '\0'; - - for (size_t i = 0; i < textLength; ++i) - { - if (currentLine == line) - { - lineStart = i; - break; - } - if (text[i] == '\n' || (i > 0 && (i % width) == 0)) - { - ++currentLine; - } - } - - if (lineStart >= textLength || currentLine != line) - { - return buffer; - } - - size_t charCount = 0; - for (size_t i = lineStart; i < textLength && charCount < width; ++i) - { - if (text[i] == '\n') - { - break; - } - buffer[charCount++] = text[i]; - } - - buffer[charCount] = '\0'; - - return buffer; - } - - String buildLine(char lineChar) - { - String line; - for (size_t i = 0; i < size; ++i) - { - line += '+'; - for (int j = 0; j < columnWidths[i]; ++j) - { - line += lineChar; - } - } - line += "+\n"; - return line; - } -}; - -#endif // SERIALTABLE_H \ No newline at end of file diff --git a/.build/sketch/UnitTests.h b/.build/sketch/UnitTests.h deleted file mode 100644 index 0a12d8ddeb70d4d08f61cff7b381dbc92e4e09c9..0000000000000000000000000000000000000000 --- a/.build/sketch/UnitTests.h +++ /dev/null @@ -1,343 +0,0 @@ -#line 1 "/Users/to/sciebo/TT_Arduino/2_projects/serialTable/UnitTests.h" -#include <AUnit.h> -#include "SerialTable.h" -using namespace aunit; - -test(SplitStringNoNewlines) -{ - char input[] = "This is a test string"; - int length = 5; - char expectedOutput[] = "This \nis a \ntest \nstrin\ng"; - char actualOutput[256] = {0}; // Ausreichend großer Puffer - - SerialTable::splitStringByLength(input, length, actualOutput); - - // Überprüfung der Länge der Strings - assertEqual(strlen(expectedOutput), strlen(actualOutput)); -/* - // Zusätzliche Debug-Ausgabe, um Hex-Werte zu sehen - for (size_t i = 0; i < strlen(actualOutput); ++i) - { - Serial.print("Expected: "); - Serial.print((int)expectedOutput[i]); - Serial.print(", Actual: "); - Serial.println((int)actualOutput[i]); - } -*/ - assertEqual(String(expectedOutput), String(actualOutput)); -} - -// Einzelner Testfall 2: Eingabe mit existierenden Zeilenumbrüchen -test(SplitStringWithNewlines) -{ - char input[] = "This\nis\na\ntest"; - int length = 4; - char expectedOutput[] = "This\nis\na\ntest"; - char actualOutput[256] = {0}; - SerialTable::splitStringByLength(input, length, actualOutput); - - assertEqual(String(expectedOutput), String(actualOutput)); -} - -// Einzelner Testfall 3: Länge größer als Eingabetext -test(SplitStringLengthGreaterThanText) -{ - char input[] = "Short"; - int length = 10; - char expectedOutput[] = "Short"; - char actualOutput[256] = {0}; - SerialTable::splitStringByLength(input, length, actualOutput); - - assertEqual(String(expectedOutput), String(actualOutput)); -} - -// Einzelner Testfall 4: Genau passende Länge -test(SplitStringExactLength) -{ - char input[] = "Lengthy"; - int length = 7; - char expectedOutput[] = "Lengthy"; - char actualOutput[256] = {0}; - SerialTable::splitStringByLength(input, length, actualOutput); - assertEqual(String(expectedOutput), String(actualOutput)); -} - -// Einzelner Testfall 5: Länge von 1 -test(SplitStringLengthOfOne) -{ - char input[] = "One"; - int length = 1; - char expectedOutput[] = "O\nn\ne"; - char actualOutput[256] = {0}; - SerialTable::splitStringByLength(input, length, actualOutput); - assertEqual(String(expectedOutput), String(actualOutput)); -} - -// Einzelner Testfall 6: Leerer Eingabestring -test(SplitStringEmptyInput) -{ - char input[] = ""; - int length = 5; - char expectedOutput[] = ""; - char actualOutput[256] = {0}; - SerialTable::splitStringByLength(input, length, actualOutput); - assertEqual(String(expectedOutput), String(actualOutput)); -} - -// Erstelle eine Hilfsfunktion für replaceUmlauts-Tests -test(replaceUmlautsTest) -{ - char text1[] = "Köln"; - SerialTable::replaceUmlauts(text1); - assertEqual("Koeln", text1); - - char text2[] = "München"; - SerialTable::replaceUmlauts(text2); - assertEqual("Muenchen", text2); - - char text3[] = "Straße"; - SerialTable::replaceUmlauts(text3); - assertEqual("Strasse", text3); -} - -// Erstelle eine Hilfsfunktion für truncateTextTest -test(truncateTextTest) -{ - char buffer[20]; - SerialTable table(nullptr, nullptr, 0); - - // Fall: Text passt in die Spaltenbreite - strcpy(buffer, "Hello"); - table.truncateToColumnWidth(buffer, 10, buffer); - assertEqual("Hello", buffer); - - // Fall: Text wird abgeschnitten - strcpy(buffer, "HelloWorld!"); - table.truncateToColumnWidth(buffer, 5, buffer); - assertEqual("He...", buffer); -} - -test(buildHeaderTest1) -{ - // Definiere header mit char*-Zeigern - const char *headers[] = {"Name", "Age", "City"}; - const int columnWidths[] = {10, 5, 10}; - SerialTable table(headers, columnWidths, 3); - - // Verwende buildHeader, um den Header-String zu erhalten - String header = table.buildHeader(); - - // Gib den Header über Serial aus - Serial.print(header); - Serial.flush(); - - // Erwartete Ausgabe des Headers - String expectedHeader = - "+----------+-----+----------+\n" - "|Name |Age |City |\n" - "+==========+=====+==========+\n"; - - // Vergleiche den erzeugten Header mit dem erwarteten Header - assertEqual(expectedHeader, header); -} - -test(buildHeaderTest2) -{ - // Definiere header mit char*-Zeigern - const char *headers[] = {"NameName Name", "Age Age Age", "CityCityCity"}; - const int columnWidths[] = {10, 5, 10}; - SerialTable table(headers, columnWidths, 3); - - // Verwende buildHeader, um den Header-String zu erhalten - String header = table.buildHeader(); - - // Gib den Header über Serial aus - Serial.print(header); - Serial.flush(); - - // Erwartete Ausgabe des Headers - String expectedHeader = - "+----------+-----+----------+\n" - "|NameName N|Age A|CityCityCi|\n" - "|ame |ge Ag|ty |\n" - "| |e | |\n" - "+==========+=====+==========+\n"; - - // Vergleiche den erzeugten Header mit dem erwarteten Header - assertEqual(expectedHeader, header); -} - -test(buildHeaderTest3) -{ - // Definiere header mit char*-Zeigern - const char *headers[] = {"ä123", "ö123", "ü123"}; - const int columnWidths[] = {4, 4, 4}; - SerialTable table(headers, columnWidths, 3); - - // Verwende buildHeader, um den Header-String zu erhalten - String header = table.buildHeader(); - - // Gib den Header über Serial aus - Serial.print(header); - Serial.flush(); - - // Erwartete Ausgabe des Headers - String expectedHeader = - "+----+----+----+\n" - "|ä123|ö123|ü123|\n" - "+====+====+====+\n"; - - // Vergleiche den erzeugten Header mit dem erwarteten Header - assertEqual(expectedHeader, header); -} - -test(printHeaderTest) -{ - // Verwende char*-Array statt String-Array - const char *headers[] = {"Name", "Age", "City"}; - const int columnWidths[] = {10, 5, 10}; - SerialTable table(headers, columnWidths, 3); - - table.printHeader(); - Serial.flush(); - - // Placeholder assertion, Verwendung eines Serial Monitor Tools empfohlen - assertTrue(true); -} - -test(buildRowTest) -{ - const char *headers[] = {"Name", "Age", "City"}; - const int columnWidths[] = {10, 5, 10}; - SerialTable table(headers, columnWidths, 3); - - char *rows[] = {"Alice", "30", "Wonderland"}; - - // Verwende buildRow, um den Zeilen-String zu bekommen - String rowOutput = table.buildRow(rows); - - // Gib die Zeile über Serial aus - Serial.print(rowOutput); - Serial.flush(); - - // Erwartete Ausgabe der Zeile - String expectedRowOutput = - "|Alice |30 |Wonderland|\n" - "+----------+-----+----------+\n"; - - // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String - assertEqual(expectedRowOutput, rowOutput); -} - -test(printRowWithMultipleLinesTest) -{ - const char *headers[] = {"Name", "Age", "City"}; - const int columnWidths[] = {10, 5, 5}; - SerialTable table(headers, columnWidths, 3); - - char *rows[] = {"Alice", "30", "Wonderland"}; - - // Verwende buildRow, um den Zeilen-String zu bekommen - String rowOutput = table.buildRow(rows); - - // Gib die Zeile über Serial aus - Serial.print(rowOutput); - Serial.flush(); - - // Erwartete Ausgabe der Zeile - String expectedRowOutput = - "|Alice |30 |Wonde|\n" - "| | |rland|\n" - "+----------+-----+-----+\n"; - - // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String - assertEqual(expectedRowOutput, rowOutput); -} - -test(printRowWithLongTextTest) -{ - const char *headers[] = {"Name", "Age", "City"}; - const int columnWidths[] = {10, 5, 10}; - SerialTable table(headers, columnWidths, 3); - - char *rows[] = {"A very long name", "12345", "A very long city name"}; - - // Verwende buildRow, um den Zeilen-String zu bekommen - String rowOutput = table.buildRow(rows); - - // Gib die Zeile über Serial aus - Serial.print(rowOutput); - Serial.flush(); - - // Erwartete Ausgabe der Zeile - String expectedRowOutput = - "|A very lon|12345|A very lon|\n" - "|g name | |g city nam|\n" - "| | |e |\n" - "+----------+-----+----------+\n"; - - // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String - assertEqual(expectedRowOutput, rowOutput); -} - -test(printEmptyRowTest) -{ - const char *headers[] = {"Name", "Age", "City"}; - const int columnWidths[] = {10, 5, 10}; - SerialTable table(headers, columnWidths, 3); - - char *rows[] = {"", "", ""}; - - // Verwende buildRow, um den Zeilen-String zu bekommen - String rowOutput = table.buildRow(rows); - - // Gib die Zeile über Serial aus - Serial.print(rowOutput); - Serial.flush(); - - // Erwartete Ausgabe der Zeile - String expectedRowOutput = - "| | | |\n" - "+----------+-----+----------+\n"; - - // Vergleiche den generierten Zeilen-String mit dem erwarteten Zeilen-String - assertEqual(expectedRowOutput, rowOutput); -} - -test(DisplayLengthBasic) { - assertEqual(5, SerialTable::displayLength("Hello")); -} - -test(DisplayLengthWithSpace) { - assertEqual(11, SerialTable::displayLength("Hello World")); -} - -test(DisplayLengthWithUmlauts) { - // "Müller" in UTF-8 hat eine Länge von 6 Zeichen (ä zählt als 1 Zeichen) - assertEqual(6, SerialTable::displayLength("Müller")); -} - -test(DisplayLengthOnlyUmlauts) { - // "äöü" in UTF-8 sollten jeweils als ein Zeichen zählen - assertEqual(3, SerialTable::displayLength("äöü")); -} - -test(DisplayLengthUTF8Emojis) { - // "😀😃😄" Emojis können mehrere Bytes haben, prüfen ob jedes nur als ein Zeichen gezählt wird - assertEqual(3, SerialTable::displayLength("😀😃😄")); -} - -test(DisplayLengthWithNewline) { - // "Hello\nWorld" hat eine Länge von 11 Zeichen, da \n als einzelnes Zeichen zählt - assertEqual(11, SerialTable::displayLength("Hello\nWorld")); -} - -test(DisplayLengthEmptyString) { - // Ein leerer String sollte eine Länge von 0 haben - assertEqual(0, SerialTable::displayLength("")); -} - -test(DisplayLengthSpaces) { - // " " hat eine Länge von 3 Leerzeichen - assertEqual(3, SerialTable::displayLength(" ")); -} diff --git a/README.md b/README.md index 5878c329d84ca5ba35c05b6ad6ad972793d29b6b..f88995229af7cc1891e2a8bf98fd4d08073d74e5 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,98 @@ -# thk_serialTable - - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - +# SerialTable (thk_serialTable) + +Die `SerialTable`-Klasse bietet eine komfortable Möglichkeit, tabellarische Daten über die serielle Schnittstelle auf einem Arduino-Gerät auszugeben. Sie unterstützt die Darstellung von mehrbyteigen UTF-8-Zeichen, wie z.B. Umlauten, und bietet Funktionen, um Textangaben innerhalb definierter Spaltenbreiten zu verwalten. +```cpp ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Vorname |Nachname |Alter|Stadt |Beruf |Unternehmen |Hobby |Bemerkung | ++==========+===============+=====+==========+==========+===============+==========+====================+ +|Alice |Wonderland |30 |Köln |Ingenieur |FirmaX |Schwimmen |Keine | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Bob |Builder |35 |Berlin |Architekt |Architektur AG |Bauen |Sehr erfahren | +| |Jr | | | | | | | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Charlie |Brown |28 |Hamburg |Designer |Die Design |Zeichnen |Mag Karikaturen | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|David |Tennant |40 |München |Schauspiel|Freiberufler |Lesen |Doktor gewesen | +| | | | |er | | | | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Emma |Watson |33 |Frankfurt |Schauspiel|Independent |Yoga |Bekannt aus Filmen | +| | | | |erin | | | | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Frank |Herbert |45 |Stuttgart |Autor |Ein Verlag |Schreiben |Bücher geschrieben | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Grace |Hopper |50 |Berlin |Programmie|Tech Corp |Informatik|Pionierin | +| | | | |rerin | | | | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Hugo |Strange |60 |Leipzig |Psychiater|Gesundheits Gmb|Philosophi|Ruhestand | +| | | | | |H |e | | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|Irene |Adler |29 |Dresden |Detektivin|Privat |Abenteuer |Scharfsinnig | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ +|John |Doe |49 |Bremen |Buchhalter|Kontorechner |Radfahren |Gewissenhaft | ++----------+---------------+-----+----------+----------+---------------+----------+--------------------+ ``` -cd existing_repo -git remote add origin https://git-ce.rwth-aachen.de/thk_libs/microcontrollers/thk_serialtable.git -git branch -M main -git push -uf origin main -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://git-ce.rwth-aachen.de/thk_libs/microcontrollers/thk_serialtable/-/settings/integrations) - -## Collaborate with your team -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) +## Hauptfunktionen -## Test and Deploy +- **UTF-8 Unterstützung:** Die Klasse verarbeitet UTF-8-kodierte Zeichen korrekt und passt die Spaltenbreite entsprechend an, sodass mehrbyteige Zeichen wie Umlaute nicht den Zeilenumbruch oder die Formatierung stören. +- **Spaltenbreitenmanagement:** Texte können automatisch abgeschnitten oder umgebrochen werden, um die definierten Spaltenbreiten beizubehalten. +- **Tabellarische Darstellung:** Ausgabe von Kopfzeilen und Datenzeilen in einem leicht lesbaren, tabellarisierten Format. -Use the built-in continuous integration in GitLab. +## Installation -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +Stellen Sie sicher, dass die Bibliothek innerhalb der Arduino-Umgebung verfügbar ist. Fügen Sie den Inhalt von `SerialTable` in einer `SerialTable.h` Datei ein, und binden Sie sie in Ihr Arduino-Projekt ein. -*** +## Anwendungsbeispiel -# Editing this README +```cpp +#include <Arduino.h> +#include "SerialTable.h" -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. +void setup() { + Serial.begin(115200); + + const char *headers[] = {"Name", "Alter", "Stadt"}; + const int columnWidths[] = {10, 5, 10}; + SerialTable table(headers, columnWidths, 3); -## Suggestions for a good README + table.printHeader(); -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + char *row1[] = {"Müller", "30", "Köln"}; + table.printRow(row1); -## Name -Choose a self-explaining name for your project. + char *row2[] = {"Schmidt", "44", "Berlin"}; + table.printRow(row2); +} -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. +void loop() { + // Der Haupt-Loop kann leer bleiben, sofern nicht benötigte Funktionen hinzugefügt werden. +} +``` -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. +Verwendung -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. +Konstruktor -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +```cpp +SerialTable(const char *headers[], const int columnWidths[], size_t size); +``` -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. +- headers: Array von C-Strings, die die Spaltennamen darstellen. +- columnWidths: Array von Ganzzahlen, die die Breite jeder Spalte definieren. +- size: Anzahl der Spalten. -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +Methoden -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. +- `void printHeader()`: Gibt den Header der Tabelle über die serielle Schnittstelle aus. +- `void printRow(char trow)`: Gibt eine Zeile mit Daten über die serielle Schnittstelle aus. `trow` ist ein Array von C-Strings. +- `void setTruncateText(bool value)`: Legt fest, ob der Text in einer Spalte abgeschnitten werden soll, wenn er die definierte Breite überschreitet. -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. +Utility-Methoden -## License -For open source projects, say how it is licensed. -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +- `static int displayLength(const char *text)`: Bestimmt die tatsächliche Anzeigelänge eines Strings, der UTF-8-kodierte Zeichen enthält. +- `static void replaceUmlauts(char *text)`: Ersetzt Umlaute im Text durch ASCII-ähnliche Zeichenfolgen. +- `static void splitStringByLength(const char input, int L, char output)`: Teilt einen String in Segmente auf, die die angegebene Länge nicht überschreiten. \ No newline at end of file diff --git a/serialTable.ino b/examples/serialTable/serialTable.ino similarity index 100% rename from serialTable.ino rename to examples/serialTable/serialTable.ino diff --git a/examples/unitTests/unitTests.ino b/examples/unitTests/unitTests.ino new file mode 100644 index 0000000000000000000000000000000000000000..bcff75524a8ce08ca2d243a7b82d26e661f613d1 --- /dev/null +++ b/examples/unitTests/unitTests.ino @@ -0,0 +1,11 @@ +#include "UnitTests.h" + +void setup() +{ + Serial.begin(115200); +} + +void loop() +{ + TestRunner::run(); +} \ No newline at end of file diff --git a/output.txt b/output.txt index d9207f8797def018532d7b7f9a40c9e68fc9d020..28fae9e76d5e3d917dacbf8c6be9cd0a606d5f75 100644 --- a/output.txt +++ b/output.txt @@ -1,3 +1,5 @@ +Eine Tabelle: + +---------------+--------------------+----------+ |Header 1 |Header 2 |Header 3 | +===============+====================+==========+ @@ -9,18 +11,8 @@ |Text | |Text2 | +---------------+--------------------+----------+ -|Alice |30 |Wonde| -| | |rland| -+----------+-----+-----+ - -|Alice |30 |Wonderland| -+----------+-----+-----+ - +Eine Zeile: |Alice |30 |Wonde| | | |rland| +----------+-----+-----+ - -|Alice |30 |Wonde -rland| -+----------+-----+-----+