Skip to content

Commit

Permalink
Move CsvReader into separate library
Browse files Browse the repository at this point in the history
  • Loading branch information
mikee47 committed Jun 17, 2024
1 parent c8bf72f commit 2847b41
Show file tree
Hide file tree
Showing 9 changed files with 20 additions and 284 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@
path = Sming/Libraries/CS5460/CS5460
url = https://github.com/xxzl0130/CS5460.git
ignore = dirty
[submodule "Libraries.CsvReader"]
path = Sming/Libraries/CsvReader
url = https://github.com/mikee47/CsvReader
ignore = dirty
[submodule "Libraries.DFRobotDFPlayerMini"]
path = Sming/Libraries/DFRobotDFPlayerMini
url = https://github.com/DFRobot/DFRobotDFPlayerMini.git
Expand Down
124 changes: 0 additions & 124 deletions Sming/Core/Data/CsvReader.cpp

This file was deleted.

130 changes: 1 addition & 129 deletions Sming/Core/Data/CsvReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,132 +12,4 @@

#pragma once

#include "Stream/DataSourceStream.h"
#include "CStringArray.h"
#include <memory>

/**
* @brief Class to parse a CSV file
*
* Spec: https://www.ietf.org/rfc/rfc4180.txt
*
* 1. Each record is located on a separate line
* 2. Line ending for last record in the file is optional
* 3. Field headings are provided either in the source data or in constructor (but not both)
* 4. Fields separated with ',' and whitespace considered part of field content
* 5. Fields may or may not be quoted - if present, will be removed during parsing
* 6. Fields may contain line breaks, quotes or commas
* 7. Quotes may be escaped thus "" if field itself is quoted
*
* Additional features:
*
* - Line breaks can be \n or \r\n
* - Escapes codes within fields will be converted: \n \r \t \", \\
* - Field separator can be changed in constructor
*/
class CsvReader
{
public:
/**
* @brief Construct a CSV reader
* @param source Stream to read CSV text from
* @param fieldSeparator
* @param headings Required if source data does not contain field headings as first row
* @param maxLineLength Limit size of buffer to guard against malformed data
*/
CsvReader(IDataSourceStream* source, char fieldSeparator = ',', const CStringArray& headings = nullptr,
size_t maxLineLength = 2048)
: source(source), fieldSeparator(fieldSeparator), userHeadingsProvided(headings), maxLineLength(maxLineLength),
headings(headings)
{
reset();
}

/**
* @brief Reset reader to start of CSV file
*
* Cursor is set to 'before start'.
* Call 'next()' to fetch first record.
*/
void reset();

/**
* @brief Seek to next record
*/
bool next()
{
return readRow();
}

/**
* @brief Get number of columns
*/
unsigned count() const
{
return headings.count();
}

/**
* @brief Get a value from the current row
* @param index Column index, starts at 0
* @retval const char* nullptr if index is not valid
*/
const char* getValue(unsigned index)
{
return row[index];
}

/**
* @brief Get a value from the current row
* @param index Column name
* @retval const char* nullptr if name is not found
*/
const char* getValue(const char* name)
{
return getValue(getColumn(name));
}

/**
* @brief Get index of column given its name
* @param name Column name to find
* @retval int -1 if name is not found
*/
int getColumn(const char* name)
{
return headings.indexOf(name);
}

/**
* @brief Determine if row is valid
*/
explicit operator bool() const
{
return bool(row);
}

/**
* @brief Get headings
*/
const CStringArray& getHeadings() const
{
return headings;
}

/**
* @brief Get current row
*/
const CStringArray& getRow() const
{
return row;
}

private:
bool readRow();

std::unique_ptr<IDataSourceStream> source;
char fieldSeparator;
bool userHeadingsProvided;
size_t maxLineLength;
CStringArray headings;
CStringArray row;
};
static_assert(false, "CsvReader class has been moved to the CsvReader library.");
1 change: 1 addition & 0 deletions Sming/Libraries/CsvReader
Submodule CsvReader added at 8f4d41
10 changes: 10 additions & 0 deletions docs/source/upgrading/5.1-5.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,13 @@ These will now fail to compile.
Copy construction and assignment has been explicitly deleted so avoid unintentional side-effects.

Objects should always be passed by reference.


**CsvReader library**

The :cpp:type:`CsvReader` class has been moved out of ``Core/Data`` and into :library:`CsvReader`
which has additional capabilities. Changes to existing code:

- Add ``CsvReader`` to your project's :cpp:envvar:`COMPONENT_DEPENDS`
- Change ``#include <Data/CsvReader>`` to ``#include <CSV/Reader.h>``
- Change ``CsvReader`` class to :cpp:class:`CSV::Reader`
4 changes: 2 additions & 2 deletions samples/Basic_Templates/app/CsvTemplate.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <Data/CsvReader.h>
#include <CSV/Reader.h>
#include <Data/Stream/SectionTemplate.h>

/**
Expand Down Expand Up @@ -35,5 +35,5 @@ class CsvTemplate : public SectionTemplate
}

private:
CsvReader csv;
CSV::Reader csv;
};
3 changes: 1 addition & 2 deletions samples/Basic_Templates/app/application.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <SmingCore.h>
#include <Data/Stream/SectionTemplate.h>
#include <FlashString/Stream.hpp>
#include <Data/CsvReader.h>
#include "CsvTemplate.h"

namespace
Expand Down Expand Up @@ -51,7 +50,7 @@ void printCars()
void printClassics(const FlashString& templateSource, Format::Formatter& formatter)
{
// The CSV data source
CsvReader csv(new FileStream(Filename::classics_csv));
CSV::Reader csv(new FileStream(Filename::classics_csv));

// Use a regular SectionTemplate class to process the template
SectionTemplate tmpl(new FSTR::Stream(templateSource));
Expand Down
1 change: 1 addition & 0 deletions samples/Basic_Templates/component.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
COMPONENT_DEPENDS := CsvReader
HWCONFIG := basic_templates
DISABLE_NETWORK := 1

27 changes: 0 additions & 27 deletions tests/HostTests/modules/TemplateStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <Data/Stream/MemoryDataStream.h>
#include <Data/Stream/LimitedMemoryStream.h>
#include <Data/Stream/SectionTemplate.h>
#include <Data/CsvReader.h>

#ifdef ARCH_HOST
#include <IFS/Host/FileSystem.h>
Expand All @@ -23,12 +22,6 @@ DEFINE_FSTR_LOCAL(template3_1, "<html><head><title>Document Title</title><style>
DEFINE_FSTR_LOCAL(template4, "{\"value\":12,\"var1\":\"{var1}\"}")
DEFINE_FSTR_LOCAL(template4_1, "{\"value\":12,\"var1\":\"quoted variable\"}")

DEFINE_FSTR_LOCAL(
test1_csv, "\"field1\",field2,field3,\"field four\"\n"
"Something \"awry\",\"datavalue 2\",\"where,are,\"\"the,bananas\",sausages abound,\"never surrender\"")
DEFINE_FSTR_LOCAL(csv_headings, "field1;field2;field3;field four;")
DEFINE_FSTR_LOCAL(csv_row1, "Something \"awry\";datavalue 2;where,are,\"the,bananas;sausages abound;never surrender;")

class TemplateStreamTest : public TestGroup
{
public:
Expand Down Expand Up @@ -189,26 +182,6 @@ class TemplateStreamTest : public TestGroup
}
REQUIRE(expected.equals(output, outlen));
}

TEST_CASE("CSV Reader")
{
auto str = [](const CStringArray& cs) {
String s = reinterpret_cast<const String&>(cs);
s.replace('\0', ';');
return s;
};

CsvReader reader(new FSTR::Stream(test1_csv));
String headings = str(reader.getHeadings());
Serial.println(headings);
CHECK(reader.next());
String row1 = str(reader.getRow());
Serial.println(row1);
CHECK(!reader.next());

CHECK(csv_headings == headings);
CHECK(csv_row1 == row1);
}
}

private:
Expand Down

0 comments on commit 2847b41

Please sign in to comment.