How to connect the content of any files for use in C / C ++ code

Hello, Khabrovites!





This is my first article and I have something to share. Perhaps my bike is not new and everyone uses this method, but once upon a time I was looking for a solution, I could not find it right away.





What are we talking about?

The task was to include files: HTML , JS , CSS ; without special training. It is also inconvenient to connect binary files (for example, pictures ) by converting them to HEX . Since I didn't want to convert to HEX or split into lines, I was looking for a way to connect the file to the program address space .





How it usually looks

Example, with line splitting:





const char text[] =
    "<html>"            "\r\n"
    "<body>Text</body>" "\r\n"
    "</html>";
      
      



Example, with HEX (more suitable for binary data):





const char text[] =
    {
        0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C,
        0x62, 0x6F, 0x64, 0x79, 0x3E, 0x54, 0x65, 0x78,
        0x74, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E,
        0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E,
        0
    };
      
      



I even saw this:





#define TEXT "<html>\r\n<body>Text</body>\r\n</html>"
const char text[] = TEXT;
      
      



#define .h Python. , \ . .





, , , :





extern const char text[];
      
      



, Assembler.





Arduino IDE

text.S, text.htm.





text.htm:





<html>
<body>Text</body>
</html>
      
      



text.S:





.global text
.section .rodata.myfiles
text:
    .incbin "text.htm"
    .byte 0
      
      



\0 , .





:





extern const char text[] PROGMEM;

void setup()
{
    Serial.begin(115200);
    Serial.println(text);
}

void loop() { }
      
      



, :





, - , .





AVR8, ESP8266 . , Flash 32 32 . , , :





.global text
.section .rodata.myfiles

.align 4
text:
    .incbin "text.htm"
    .byte 0
      
      



: .irom.text, .rodata.





STM32 32 , .





? , . :





.global text, text_size

.section .rodata.myfiles

text:
    .incbin "text.htm"
    text_end:
    .byte 0

text_size:
	.word (text_end - text)
      
      



:





extern const char text[] PROGMEM;
extern const uint16_t text_size PROGMEM;
      
      



, :





.macro addFile name file
    .global \name, \name\()_size
//  .align 4
    \name:
        .incbin "\file"
        \name\()_end:
        .byte 0
//  .align 4
    \name\()_size:
        .word (\name\()_end - \name)
.endm

.section .rodata.myfiles

addFile text1   1.txt
addFile text2   2.txt
addFile text3   3.txt
      
      



:





#define ADD_FILE(name) \
    extern const char name[] PROGMEM; \
    extern const uint16_t name##_size PROGMEM;

ADD_FILE(text1);
ADD_FILE(text2);
ADD_FILE(text3);

void setup()
{
    Serial.begin(115200);
    Serial.println(text1);
    Serial.println(text1_size);
    Serial.println(text2);
    Serial.println(text2_size);
    Serial.println(text3);
    Serial.println(text3_size);
}

void loop() { }
      
      



:





, .





, GNU toolchain

, Arduino. Arduino toolchain Atmel.





Makefile - .





STM32, . WEB- LWIP / HTTPD.





version.sh:





#!/bin/bash
# Version generator
# running script from pre-build

MAJOR=1
MINOR=0

cd "$(dirname $0)" &>/dev/null

FILE_VERSION="version.txt"
FILE_ASM="version.S"

BUILD=$(head -n1 "$FILE_VERSION" 2>/dev/null)
if [ -z "$BUILD" ]; then
	BUILD=0
else
	BUILD=$(expr $BUILD + 1)
fi
echo -n "$BUILD" >"$FILE_VERSION"

cat <<EOF >"$FILE_ASM"
/**
* no editing, automatically generated from version.sh
*/

.section .rodata
.global __version_major
.global __version_minor
.global __version_build
__version_major: .word $MAJOR
__version_minor: .word $MINOR
__version_build: .word $BUILD
.end
EOF

cd - &>/dev/null
exit 0
      
      



version.S version.txt .





Makefile pre-build:





#######################################
# pre-build script
#######################################
pre-build:
	bash version.sh
      
      



all pre-build:





all: pre-build $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
      
      



printf macro.h:





extern const uint16_t __version_major;
extern const uint16_t __version_minor;
extern const uint16_t __version_build;
#define FMT_VER             "%u.%u.%u"
#define FMT_VER_VAL         __version_major, __version_minor, __version_build
      
      



HTTPD LWIP , HTTP. , fsdata.c. fsdata_custom.c, HTTPD_USE_CUSTOM_FSDATA.





fsdata_custom.c:





#include "lwip/apps/fs.h"
#include "lwip/def.h"
#include "fsdata.h"
#include "macro.h"

extern const struct fsdata_file __fs_root;

#define FS_ROOT &__fs_root
      
      



fsdata_make.S:





.macro addData name file mime
	\name\():
	.string "/\file\()"
	\name\()_data:
	.incbin "mime/\mime\().txt"
	.incbin "\file\()"
	\name\()_end:
.endm

.macro addFile name next
	\name\()_file:
	.word \next\()
	.word \name\()
	.word \name\()_data
	.word \name\()_end - \name\()_data
	.word 1
.endm

.section .rodata.fsdata
.global __fs_root

/* Load files */
addData __index_htm         index.htm           html
addData __styles_css        styles.css          css
addData __lib_js            lib.js              js
addData __ui_js             ui.js               js
addData __404_htm           404.htm             404
addData __favicon_ico       img/favicon.ico     ico
addData __logo_png          img/logo.png        png

/* FSDATA Table */
addFile __logo_png          0
addFile __favicon_ico       __logo_png_file
addFile __404_htm           __favicon_ico_file
addFile __ui_js             __404_htm_file
addFile __lib_js            __ui_js_file
addFile __styles_css        __lib_js_file
__fs_root:
addFile __index_htm         __styles_css_file

.end

      
      



, mime.





html.txt:





HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Connection: close


      
      



404.txt:





HTTP/1.1 404 Not found
Content-Type: text/plain; charset=UTF-8
Connection: close


      
      



Note the blank line, which is required by the HTTP specification to mark the end of the header. Each line must end with CRLF (\ r \ n).





PS The project code is from a dilapidated chest, so the implementation could forget something to clarify.





At the end

I was looking for something useful in the article for a long time. I hope my experience is useful for a beginner and a guru.





Thank you for your attention, happy developments!








All Articles