Последнее обновление 4/4/2019
Я недавно слышал о Cog и думаю, что это может быть лучшее решение, чем m4. Он использует python для предварительной обработки, делая код более читабельным, как показано ниже (легко поддерживает кавычки внутри строки):
#include <cstdio>
/*[[[cog
import cog, re
def escape_raw(s):
s = re.sub(r'\\', r'\\\\', s) # escape backslash first
s = re.sub(r'"', r'\"', s) # escape quotes
return re.sub(r'\n', r'\\n\n', s) # escape newline last
def cog_define(name, val):
cog.outl("#define {name} {val}".format(name=name, val=val))
STR_test = r"""{
"AAA": "a",
"BBB": "b",
"contain \" quote": "c"
}"""
cog_define("STR_test", escape_raw(STR_test))
]]]*/
//[[[end]]]
int main()
{
const char *s = STR_test;
printf("%s\n", s);
return 0;
}
выход: * +1010 *
#include <cstdio>
/*[[[cog
import cog, re
def escape_raw(s):
s = re.sub(r'\\', r'\\\\', s) # escape backslash first
s = re.sub(r'"', r'\"', s) # escape quotes
return re.sub(r'\n', r'\\n\n', s) # escape newline last
def cog_define(name, val):
cog.outl("#define {name} {val}".format(name=name, val=val))
STR_test = r"""{
"AAA": "a",
"BBB": "b",
"contain \" quote": "c"
}"""
cog_define("STR_test", escape_raw(STR_test))
]]]*/
#define STR_test {\n
\"AAA\": \"a\",\n
\"BBB\": \"b\",\n
\"contain \\\" quote\": \"c\"\n
}
//[[[end]]]
int main()
{
const char *s = STR_test;
printf("%s\n", s);
return 0;
}
=============================================== ===============
Вы пробовали GNU m4 ?
Это довольно странно, но идея состоит в том, чтобы предварительно обработать более привлекательную версию до уродливой (без использования необработанной строки).
Ваш код будет таким:
#include <cstdio>
m4_changecom(`/*', `*/')
m4_define(`ESCAPE_RAW', `"m4_patsubst(`m4_patsubst($1, `"', `\\"')', `
', `\\n\\
')'") /* substitute newline and double quote with escaped version */
#define STR_test ESCAPE_RAW(`{
"AAA": "a",
"BBB": "b"
}')
int main()
{
const char *s = STR_test;
printf("%s\n", s);
return 0;
}
Уродливый макрос ESCAPE_RAW
должен быть определен только один раз, и все последующие "необработанные строки" могут использовать ESCAPE_RAW
для генерации уродливых версий, которые распознает gcc.
Для предварительной обработки с помощью m4 используйте команду m4 -P test.cpp
, где -P
принудительно устанавливает префикс m4_
в операторах define. Команда производит это:
#include <cstdio>
#define STR_test "{\n\
\"AAA\": \"a\",\n\
\"BBB\": \"b\"\n\
}"
int main()
{
const char *s = STR_test;
printf("%s\n", s);
return 0;
}
Возможно, назовите ваш файл m4 с расширением .m4
и используйте m4 для создания уродливых заголовочных файлов.