diff --git a/CHANGES.md b/CHANGES.md index 2316625..13df064 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## Version 1.04 +- revart: https://github.com/suzukiplan/vgs-mml-compiler/pull/6 +- added: `vgsmml_compile_from_memory2` as a function without memory destruction + ## Version 1.03 - ensures duplicate memory of MML string: https://github.com/AmamiyaRinyuki/vgs-bgm-plugins/issues/1 diff --git a/src/vgsmml.c b/src/vgsmml.c index a25cc7f..b970503 100644 --- a/src/vgsmml.c +++ b/src/vgsmml.c @@ -144,13 +144,14 @@ struct VgsBgmData* __stdcall vgsmml_compile_from_file(const char* path, struct V return result; } +/* NOTE: YOU MUST SPECIFY THE NULL TERMINATED STRING TO THE DATA ARGUMENT */ struct VgsBgmData* __stdcall vgsmml_compile_from_memory(void* data, size_t size, struct VgsMmlErrorInfo* err) { struct VgsBgmData* result; int nLine, cLine; int i; int* pos; - char* buf; + char* buf = (char*)data; if (NULL == err) { return NULL; @@ -161,15 +162,12 @@ struct VgsBgmData* __stdcall vgsmml_compile_from_memory(void* data, size_t size, return NULL; } - /* ensures duplicate memory */ - buf = (char*)malloc(size + 1); - if (NULL == buf) { - strcpy(err->message, "no memory"); - err->code = VGSMML_ERR_NO_MEMORY; + /* memory check */ + if ('\0' != buf[size - 1]) { + strcpy(err->message, "needed specify the \'\\0\' terminated string to the data argument."); + err->code = VGSMML_ERR_INVALID; return NULL; } - memcpy(buf, data, size); - buf[size] = '\0'; /* count line */ for (nLine = 1, i = 0; buf[i]; i++) { @@ -180,7 +178,6 @@ struct VgsBgmData* __stdcall vgsmml_compile_from_memory(void* data, size_t size, if (NULL == (pos = (int*)malloc((nLine + 1) * sizeof(int)))) { strcpy(err->message, "no memory"); err->code = VGSMML_ERR_NO_MEMORY; - free(buf); return NULL; } @@ -207,6 +204,34 @@ struct VgsBgmData* __stdcall vgsmml_compile_from_memory(void* data, size_t size, /* execute next phase */ result = phase3(buf, pos, err); free(pos); + return result; +} + +/* compiles without memory destruction */ +struct VgsBgmData* __stdcall vgsmml_compile_from_memory2(const void* data, size_t size, struct VgsMmlErrorInfo* err) +{ + struct VgsBgmData* result; + char* buf; + + if (NULL == err) { + return NULL; + } + if (NULL == data || size < 1) { + strcpy(err->message, "invalid data size"); + err->code = VGSMML_ERR_INVALID; + return NULL; + } + + buf = (char*)malloc(size + 1); + if (NULL == buf) { + strcpy(err->message, "no memory"); + err->code = VGSMML_ERR_NO_MEMORY; + return NULL; + } + memcpy(buf, data, size); + buf[size] = '\0'; + + result = vgsmml_compile_from_memory(buf, size + 1, err); free(buf); return result; } diff --git a/src/vgsmml.h b/src/vgsmml.h index 0cc318d..1abde24 100644 --- a/src/vgsmml.h +++ b/src/vgsmml.h @@ -27,10 +27,12 @@ struct VgsMmlErrorInfo { #ifdef _WIN32 struct VgsBgmData* __stdcall vgsmml_compile_from_file(const char* path, struct VgsMmlErrorInfo* err); struct VgsBgmData* __stdcall vgsmml_compile_from_memory(void* data, size_t size, struct VgsMmlErrorInfo* err); +struct VgsBgmData* __stdcall vgsmml_compile_from_memory2(const void* data, size_t size, struct VgsMmlErrorInfo* err); void __stdcall vgsmml_free_bgm_data(struct VgsBgmData* data); #else struct VgsBgmData* vgsmml_compile_from_file(const char* path, struct VgsMmlErrorInfo* err); struct VgsBgmData* vgsmml_compile_from_memory(void* data, size_t size, struct VgsMmlErrorInfo* err); +struct VgsBgmData* vgsmml_compile_from_memory2(const void* data, size_t size, struct VgsMmlErrorInfo* err); void vgsmml_free_bgm_data(struct VgsBgmData* data); #endif diff --git a/test/test_memchk.c b/test/test_memchk.c index e3ec26a..65a8769 100644 --- a/test/test_memchk.c +++ b/test/test_memchk.c @@ -7,8 +7,9 @@ int main(int argc, char* argv[]) struct VgsMmlErrorInfo err; char foo[4]; strcpy(foo, "foo"); - if (NULL == vgsmml_compile_from_memory(foo, 3, &err) && VGSMML_ERR_SYNTAX_UNKNOWN == err.code && 1 == err.line) { - printf("%s (code=%d, line=%d)\n", err.message, err.code, err.line); + if (NULL == vgsmml_compile_from_memory(foo, 3, &err) && VGSMML_ERR_INVALID == err.code) { + puts(err.message); + puts("test succeed"); return 0; } puts("test failed");