Skip to content

Commit 5ce734b

Browse files
committed
Add DECLARE_FSTR_OBJECT macro, and rearrange custom object sample to use it
1 parent 0cb1ab7 commit 5ce734b

File tree

8 files changed

+142
-78
lines changed

8 files changed

+142
-78
lines changed

src/include/FlashString/Array.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* @param ElementType
3737
* @note Use `DEFINE_FSTR_ARRAY` to instantiate the global Object
3838
*/
39-
#define DECLARE_FSTR_ARRAY(name, ElementType) extern const FSTR::Array<ElementType>& name;
39+
#define DECLARE_FSTR_ARRAY(name, ElementType) DECLARE_FSTR_OBJECT(name, FSTR::Array<ElementType>)
4040

4141
/**
4242
* @brief Define an Array Object with global reference

src/include/FlashString/Map.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* @param ContentType Object type to declare for content
4040
* @note Use DEFINE_FSTR_MAP to instantiate the global object
4141
*/
42-
#define DECLARE_FSTR_MAP(name, KeyType, ContentType) extern const FSTR::Map<KeyType, ContentType>& name;
42+
#define DECLARE_FSTR_MAP(name, KeyType, ContentType) DECLARE_FSTR_OBJECT(name, DECL((FSTR::Map<KeyType, ContentType>)))
4343

4444
/**
4545
* @brief Define a Map Object with global reference

src/include/FlashString/Object.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333
* @{
3434
*/
3535

36+
/**
37+
* @brief Declare a global Object reference
38+
* @param name
39+
* @param ObjectType
40+
*/
41+
#define DECLARE_FSTR_OBJECT(name, ObjectType) extern const ObjectType& name;
42+
3643
/**
3744
* @brief Define a reference to an object
3845
* @param name Name for reference

src/include/FlashString/String.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ typedef const __FlashStringHelper* flash_string_t;
6060
* @param name
6161
* @note Define the FSTR::String object using DEFINE_STR()
6262
*/
63-
#define DECLARE_FSTR(name) extern const FSTR::String& name;
63+
#define DECLARE_FSTR(name) DECLARE_FSTR_OBJECT(name, FSTR::String)
6464

6565
/**
6666
* @brief Define a FSTR::String object with global reference

src/include/FlashString/Vector.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* @param ObjectType
3737
* @note Use `DEFINE_VECTOR` to instantiate the global Object
3838
*/
39-
#define DECLARE_FSTR_VECTOR(name, ObjectType) extern const FSTR::Vector<ObjectType>& name;
39+
#define DECLARE_FSTR_VECTOR(name, ObjectType) DECLARE_FSTR_OBJECT(name, FSTR::Vector<ObjectType>)
4040

4141
/**
4242
* @brief Define a Vector Object with global reference

test/app/custom.cpp

+4-71
Original file line numberDiff line numberDiff line change
@@ -20,80 +20,13 @@
2020
****/
2121

2222
#include <SmingTest.h>
23-
#include <FlashString/Array.hpp>
23+
#include "custom.h"
2424

2525
/*
26-
* This is the structure for our custom object, the contents of which will be
27-
* loaded from an external file.
26+
* Import the data and define a reference for it.
27+
* If we don't want `customObject` to be global, use `IMPORT_FSTR_OBJECT_LOCAL`.
2828
*/
29-
struct MyCustomStruct {
30-
FSTR::ObjectBase object;
31-
char name[12];
32-
char description[20];
33-
/*
34-
* A contained Object. This could be:
35-
*
36-
* - A String
37-
* - An Array
38-
* - Another MyCustomObject
39-
* - Another custom object
40-
*
41-
* Structures cannot contain pointers when loaded from a file,
42-
* so Vectors and Maps aren't possible.
43-
*/
44-
FSTR::ObjectBase dataArray;
45-
};
46-
47-
class CustomObject : public FSTR::Object<CustomObject, char>
48-
{
49-
};
50-
51-
class MyCustomObject : public CustomObject
52-
{
53-
public:
54-
String name() const
55-
{
56-
return readString(offsetof(MyCustomStruct, name), sizeof(MyCustomStruct::name));
57-
}
58-
59-
String description() const
60-
{
61-
return readString(offsetof(MyCustomStruct, description), sizeof(MyCustomStruct::description));
62-
}
63-
64-
/*
65-
* Access the contained object as uint8_t[]
66-
*/
67-
const FSTR::Array<uint8_t>& content() const
68-
{
69-
return data()->dataArray.as<FSTR::Array<uint8_t>>();
70-
}
71-
72-
/*
73-
* Provide a pointer to the raw data as defined by our structure
74-
*/
75-
const MyCustomStruct* data() const
76-
{
77-
return reinterpret_cast<const MyCustomStruct*>(CustomObject::data());
78-
}
79-
80-
private:
81-
// Helper method so we can pull out the text strings more easily
82-
String readString(size_t offset, size_t len) const
83-
{
84-
char buf[len + 1];
85-
read(offset, buf, len);
86-
buf[len] = '\0';
87-
return buf;
88-
}
89-
};
90-
91-
/*
92-
* Import the data and define a symbol for it.
93-
* Note that the symbol _is_ the data, it's not a pointer or a reference.
94-
*/
95-
IMPORT_FSTR_DATA(customObject, COMPONENT_PATH "/files/custom.bin");
96-
extern "C" const MyCustomObject customObject;
29+
IMPORT_FSTR_OBJECT(customObject, MyCustomObject, COMPONENT_PATH "/files/custom.bin");
9730

9831
class CustomTest : public TestGroup
9932
{

test/app/custom.h

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* custom.h - Test creation of custom objects
3+
*
4+
* Copyright 2019 mikee47 <[email protected]>
5+
*
6+
* This file is part of the FlashString Library
7+
*
8+
* This library is free software: you can redistribute it and/or modify it under the terms of the
9+
* GNU General Public License as published by the Free Software Foundation, version 3 or later.
10+
*
11+
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+
* See the GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License along with FlashString.
16+
* If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* @author: Nov 2019 - mikee47 <[email protected]>
19+
*
20+
****/
21+
22+
#include <WString.h>
23+
#include <FlashString/Array.hpp>
24+
25+
/*
26+
* This is the structure for our custom object, the contents of which will be
27+
* loaded from an external file.
28+
*/
29+
struct MyCustomStruct {
30+
FSTR::ObjectBase object;
31+
char name[12];
32+
char description[20];
33+
/*
34+
* A contained Object. This could be:
35+
*
36+
* - A String
37+
* - An Array
38+
* - Another MyCustomObject
39+
* - Another custom object
40+
*
41+
* Structures cannot contain pointers when loaded from a file,
42+
* so Vectors and Maps aren't possible.
43+
*/
44+
FSTR::ObjectBase dataArray;
45+
};
46+
47+
/*
48+
* Define a base object type using char[]
49+
*/
50+
class CustomObject : public FSTR::Object<CustomObject, char>
51+
{
52+
protected:
53+
// Helper method so we can pull out text strings more easily
54+
String readString(size_t offset, size_t len) const
55+
{
56+
char buf[len + 1];
57+
len = read(offset, buf, len);
58+
buf[len] = '\0';
59+
return buf;
60+
}
61+
};
62+
63+
/*
64+
* Now derive our custom object with appropriate accessor methods
65+
*/
66+
class MyCustomObject : public CustomObject
67+
{
68+
public:
69+
String name() const
70+
{
71+
return readString(offsetof(MyCustomStruct, name), sizeof(MyCustomStruct::name));
72+
}
73+
74+
String description() const
75+
{
76+
return readString(offsetof(MyCustomStruct, description), sizeof(MyCustomStruct::description));
77+
}
78+
79+
/*
80+
* Access the contained object as uint8_t[]
81+
*/
82+
const FSTR::Array<uint8_t>& content() const
83+
{
84+
return data()->dataArray.as<FSTR::Array<uint8_t>>();
85+
}
86+
87+
/*
88+
* Provide a pointer to the raw data as defined by our structure
89+
*/
90+
const MyCustomStruct* data() const
91+
{
92+
return reinterpret_cast<const MyCustomStruct*>(CustomObject::data());
93+
}
94+
};
95+
96+
/*
97+
* Declare the global object (imported and defined in custom.cpp).
98+
*/
99+
DECLARE_FSTR_OBJECT(customObject, MyCustomObject);

utility.rst

+28-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ You'll need to define an appropriate symbol::
5353
struct MyCustomStruct {
5454
uint32_t length;
5555
char name[12];
56-
char description[256];
56+
char description[20];
5757
uint8_t data[1024];
5858
};
5959

@@ -65,8 +65,33 @@ you can just copy it into RAM::
6565
MyCustomStruct buf;
6666
memcpy_P(&buf, &myCustomData, sizeof(buf));
6767

68-
However, a better way is to define a custom Object to handle it.
69-
You can find an example of how to do this in ``test/app/custom.cpp``.
68+
69+
Custom Objects
70+
--------------
71+
72+
A better way to handle large, complex structures is to define a custom Object to handle it.
73+
You can find an example of how to do this in ``test/app/custom.cpp``, which does this:
74+
75+
1. Define ``MyCustomStruct``::
76+
77+
struct MyCustomStruct {
78+
FSTR::ObjectBase object;
79+
char name[12];
80+
char description[20];
81+
FSTR::ObjectBase dataArray;
82+
};
83+
84+
2. Define a base object type (``CustomObject``) using the :cpp:class:`FSTR::Object` class template.
85+
This determines the underlying element type, generally ``char`` or ``uint8_t`` are most useful.
86+
87+
3. Derive an Object class (``MyCustomObject``) to encapsulate access to ``MyCustomStruct``.
88+
89+
4. Use the :c:func:`IMPORT_FSTR_OBJECT` macro to import the custom data and define a global
90+
reference (``customObject``) of type ``MyCustomObject&``.
91+
92+
5. Use :c:func:`DECLARE_FSTR_OBJECT` macro to declare the reference in a header.
93+
94+
More complex examples may involve multiple custom Object types.
7095

7196

7297
API Reference

0 commit comments

Comments
 (0)