pluie-yaml/src/c/yaml.c
2018-09-05 02:33:21 +02:00

129 lines
4.4 KiB
C

/*^* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* @software : pluie-yaml <https://git.pluie.org/pluie/lib-yaml>
* @version : 0.60
* @type : library
* @date : 2018
* @license : GPLv3.0 <http://www.gnu.org/licenses/>
* @author : a-Sansara <[dev]at[pluie]dot[org]>
* @copyright : pluie.org <http://www.pluie.org>
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* This file is part of pluie-yaml.
*
* pluie-yaml is free software (free as in speech) : you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* pluie-yaml is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with pluie-yaml. If not, see <http://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *^*/
#include <stdio.h>
#include <yaml.h>
/* return a new string with every instance of ch replaced by repl */
char *replace_char(const char *s, char ch, const char *repl) {
int count = 0;
const char *t;
for(t=s; *t; t++)count += (*t == ch);
size_t rlen = strlen(repl);
char *res = malloc(strlen(s) + (rlen-1)*count + 1);
char *ptr = res;
for(t=s; *t; t++) {
if(*t == ch) {
memcpy(ptr, repl, rlen);
ptr += rlen;
} else {
*ptr++ = *t;
}
}
*ptr = 0;
return res;
}
char *escape_string(const char *s) {
char *t;
t = replace_char(s, '\"', "\\\"");
t = replace_char(t, '\n', "\\n");
return t;
}
void yaml_parse_file(const char *srcPath, const char *destPath)
{
FILE *rh = fopen(srcPath, "r");
FILE *wh = fopen(destPath, "w");
yaml_parser_t parser;
yaml_token_t token;
if(!yaml_parser_initialize(&parser))
fputs("Failed to initialize parser!\n", stderr);
if(rh == NULL || wh == NULL)
fputs("Failed to open file!\n", stderr);
yaml_parser_set_input_file(&parser, rh);
int stop = 0;
do {
yaml_parser_scan(&parser, &token);
long int line = parser.mark.line + 1;
switch(token.type)
{
case YAML_SCALAR_TOKEN :
fprintf(wh, "%lu, %d, %d, \"%s\"\n", line, token.type, token.data.scalar.style, escape_string((char *)token.data.scalar.value));
break;
case YAML_ALIAS_TOKEN :
fprintf(wh, "%lu, %d, \"%s\"\n", line, token.type, token.data.alias.value);
break;
case YAML_ANCHOR_TOKEN :
fprintf(wh, "%lu, %d, \"%s\"\n", line, token.type, token.data.anchor.value);
break;
case YAML_DOCUMENT_START_TOKEN :
fprintf(wh, "%lu, %d, %d\n", line, token.type, parser.encoding);
break;
case YAML_TAG_TOKEN :
fprintf(wh, "%lu, %d, \"%s\", \"%s\"\n", line, token.type, token.data.tag.handle, token.data.tag.suffix);
break;
case YAML_VERSION_DIRECTIVE_TOKEN :
fprintf(wh, "%lu, %d, %d, %d\n", line, token.type, token.data.version_directive.major, token.data.version_directive.minor);
break;
case YAML_TAG_DIRECTIVE_TOKEN :
fprintf(wh, "%lu, %d, \"%s\", \"%s\"\n", line, token.type, token.data.tag_directive.handle, token.data.tag_directive.prefix);
break;
case YAML_NO_TOKEN :
fprintf(wh, "%lu, %d, \"%s\"\n", line, token.type, escape_string((char *)parser.problem));
stop = 1;
break;
/* Others */
default:
fprintf(wh, "%lu, %d\n", line, token.type);
}
if(token.type != YAML_STREAM_END_TOKEN)
yaml_token_delete(&token);
if (stop == 1) break;
}
while(token.type != YAML_STREAM_END_TOKEN);
yaml_token_delete(&token);
yaml_parser_delete(&parser);
fclose(rh);
fclose(wh);
}