gmio_stl: add read/write option stla_dont_check_lc_numeric

gmio_stla_read() and gmio_stla_write() now checks LC_NUMERIC is
either "C" or "POSIX", if not then GMIO_ERROR_BAD_LC_NUMERIC is returned.
This option is controlled with:
    * gmio_stl_read_options.stla_dont_check_lc_numeric
    * gmio_write_read_options.stla_dont_check_lc_numeric
This commit is contained in:
Hugues Delorme 2016-07-05 11:28:44 +02:00
parent 61e4fd5066
commit 89d268f052
10 changed files with 220 additions and 11 deletions

View File

@ -31,6 +31,9 @@ enum gmio_error
/*! No error occurred, success */
GMIO_ERROR_OK = 0,
/*! Unknown error */
GMIO_ERROR_UNKNOWN,
/*! Pointer on argument memory block is NULL */
GMIO_ERROR_NULL_MEMBLOCK,
@ -50,8 +53,8 @@ enum gmio_error
*/
GMIO_ERROR_STDIO,
/*! Unknown error */
GMIO_ERROR_UNKNOWN
/*! Checking of \c LC_NUMERIC failed(should be "C" or "POSIX") */
GMIO_ERROR_BAD_LC_NUMERIC
};
/*! Returns true if <tt>code == GMIO_NO_ERROR</tt> */

View File

@ -0,0 +1,62 @@
/****************************************************************************
** gmio
** Copyright Fougue (24 Jun. 2016)
** contact@fougue.pro
**
** This software is a reusable library whose purpose is to provide complete
** I/O support for various CAD file formats (eg. STL)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#include "locale_utils.h"
#include "../error.h"
#include "string_ascii_utils.h"
#include <locale.h>
#include <stddef.h>
#include <string.h>
const char *gmio_lc_numeric()
{
const char* lcnum = setlocale(LC_NUMERIC, NULL);
return lcnum != NULL ? lcnum : "";
}
bool gmio_lc_numeric_is_C()
{
const char* lc = gmio_lc_numeric();
return (gmio_ascii_stricmp(lc, "C") == 0
|| gmio_ascii_stricmp(lc, "POSIX") == 0);
}
bool gmio_check_lc_numeric(int *error)
{
if (!gmio_lc_numeric_is_C())
*error = GMIO_ERROR_BAD_LC_NUMERIC;
return gmio_no_error(*error);
}
static char global_lc_numeric[64] = {0};
void gmio_lc_numeric_save()
{
/* Save LC_NUMERIC
* POSIX specifies that the pointer returned by setlocale(), not just the
* contents of the pointed-to string, may be invalidated by subsequent calls
* to setlocale */
strncpy(global_lc_numeric,
setlocale(LC_NUMERIC, NULL),
GMIO_ARRAY_SIZE(global_lc_numeric));
}
void gmio_lc_numeric_restore()
{
if (global_lc_numeric[0] != '\0')
setlocale(LC_NUMERIC, global_lc_numeric);
}

View File

@ -0,0 +1,28 @@
/****************************************************************************
** gmio
** Copyright Fougue (24 Jun. 2016)
** contact@fougue.pro
**
** This software is a reusable library whose purpose is to provide complete
** I/O support for various CAD file formats (eg. STL)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#include "../global.h"
const char* gmio_lc_numeric();
/*! Returns result of case-insensitive test <tt>LC_NUMERIC == "C|POSIX"</tt> */
bool gmio_lc_numeric_is_C();
/*! Checks gmio_lc_numeric_is_C(), if false sets \p *error to
* \c GMIO_ERROR_BAD_LC_NUMERIC*/
bool gmio_check_lc_numeric(int* error);
void gmio_lc_numeric_save();
void gmio_lc_numeric_restore();

View File

@ -25,6 +25,7 @@
#include "../../gmio_core/internal/helper_memblock.h"
#include "../../gmio_core/internal/helper_stream.h"
#include "../../gmio_core/internal/helper_task_iface.h"
#include "../../gmio_core/internal/locale_utils.h"
#include "../../gmio_core/internal/min_max.h"
#include "../../gmio_core/internal/safe_cast.h"
@ -180,6 +181,8 @@ int gmio_stla_write(
const struct gmio_stl_write_options* opts)
{
/* Constants */
const bool check_lcnum =
opts != NULL ? !opts->stla_dont_check_lc_numeric : true;
const struct gmio_task_iface* task = opts != NULL ? &opts->task_iface : NULL;
struct gmio_memblock_helper mblock_helper =
gmio_memblock_helper(opts != NULL ? &opts->stream_memblock : NULL);
@ -225,6 +228,8 @@ int gmio_stla_write(
}
/* Check validity of input parameters */
if (check_lcnum && !gmio_check_lc_numeric(&error))
goto label_end;
if (!gmio_check_memblock_size(&error, mblock, GMIO_STLA_FACET_SIZE_P2))
goto label_end;
if (!gmio_stl_check_mesh(&error, mesh))

View File

@ -30,7 +30,12 @@
#include "../gmio_core/task_iface.h"
#include "../gmio_core/text_format.h"
/*! Options of function gmio_stl_read() */
/*! Options of function gmio_stl_read()
*
* Initialising gmio_stl_read_options with \c {0} (or \c {} in C++) is the
* convenient way to set default values(passing \c NULL to gmio_stl_read() has
* the same effect).
*/
struct gmio_stl_read_options
{
/*! Used by the stream to bufferize I/O operations
@ -59,9 +64,27 @@ struct gmio_stl_read_options
gmio_streamsize_t (*func_stla_get_streamsize)(
struct gmio_stream* stream,
struct gmio_memblock* stream_memblock);
/*! Flag allowing to disable checking of the current locale's numeric
* formatting category
*
* If \c false then \c LC_NUMERIC is checked to be "C" or "POSIX". If check
* fails then the function returns \c GMIO_ERROR_BAD_LC_NUMERIC
*
* This applies only for STL ascii, where it affects text-related standard
* C functions(snprintf(), strtod(), ...)
*
* \c LC_NUMERIC checking is enabled by default.
*/
bool stla_dont_check_lc_numeric;
};
/*! Options of function gmio_stl_write() */
/*! Options of function gmio_stl_write()
*
* Initialising gmio_stl_write_options with \c {0} (or \c {} in C++) is the
* convenient way to set default values(passing \c NULL to gmio_stl_write() has
* the same effect).
*/
struct gmio_stl_write_options
{
/*! See gmio_stl_read_options::stream_memblock */
@ -70,6 +93,9 @@ struct gmio_stl_write_options
/*! See gmio_stl_read_options::task_iface */
struct gmio_task_iface task_iface;
/*! See gmio_stl_read_options::stla_dont_check_lc_numeric */
bool stla_dont_check_lc_numeric;
/*! Flag allowing to skip writting of any header/footer data, but just
* triangles
*

View File

@ -26,6 +26,7 @@
#include "../gmio_core/internal/helper_memblock.h"
#include "../gmio_core/internal/helper_stream.h"
#include "../gmio_core/internal/helper_task_iface.h"
#include "../gmio_core/internal/locale_utils.h"
#include "../gmio_core/internal/min_max.h"
#include "../gmio_core/internal/safe_cast.h"
#include "../gmio_core/internal/stringstream.h"
@ -114,11 +115,17 @@ int gmio_stla_read(
struct gmio_stl_mesh_creator* mesh_creator,
const struct gmio_stl_read_options* opts)
{
const bool check_lcnum =
opts != NULL ? !opts->stla_dont_check_lc_numeric : true;
struct gmio_memblock_helper mblock_helper =
gmio_memblock_helper(opts != NULL ? &opts->stream_memblock : NULL);
struct gmio_memblock* const mblock = &mblock_helper.memblock;
char fixed_buffer[GMIO_STLA_READ_STRING_MAX_LEN];
struct gmio_stla_parse_data parse_data;
int error = GMIO_ERROR_OK;
if (check_lcnum && !gmio_check_lc_numeric(&error))
goto label_end;
parse_data.token = unknown_token;
parse_data.error = false;
@ -145,13 +152,14 @@ int gmio_stla_read(
parse_solid(&parse_data);
gmio_memblock_helper_release(&mblock_helper);
if (parse_data.error)
return GMIO_STL_ERROR_PARSING;
error = GMIO_STL_ERROR_PARSING;
if (parse_data.strstream_cookie.is_stop_requested)
return GMIO_ERROR_TRANSFER_STOPPED;
return GMIO_ERROR_OK;
error = GMIO_ERROR_TRANSFER_STOPPED;
label_end:
gmio_memblock_helper_release(&mblock_helper);
return error;
}

View File

@ -35,9 +35,10 @@ const char* all_tests()
UTEST_RUN(test_internal__byte_swap);
UTEST_RUN(test_internal__byte_codec);
UTEST_RUN(test_internal__fast_atof);
UTEST_RUN(test_internal__locale_utils);
UTEST_RUN(test_internal__safe_cast);
UTEST_RUN(test_internal__stringstream);
UTEST_RUN(test_internal__string_utils);
UTEST_RUN(test_internal__string_ascii_utils);
UTEST_RUN(test_internal__benchmark_gmio_fast_atof);
return NULL;

View File

@ -46,6 +46,7 @@ const char* all_tests()
UTEST_RUN(test_stl_read);
UTEST_RUN(test_stl_read_multi_solid);
UTEST_RUN(test_stla_lc_numeric);
UTEST_RUN(test_stla_write);
UTEST_RUN(test_stlb_read);
UTEST_RUN(test_stlb_write);

View File

@ -17,16 +17,19 @@
#include "stream_buffer.h"
#include "../src/gmio_core/error.h"
#include "../src/gmio_core/internal/byte_codec.h"
#include "../src/gmio_core/internal/byte_swap.h"
#include "../src/gmio_core/internal/convert.h"
#include "../src/gmio_core/internal/fast_atof.h"
#include "../src/gmio_core/internal/locale_utils.h"
#include "../src/gmio_core/internal/numeric_utils.h"
#include "../src/gmio_core/internal/safe_cast.h"
#include "../src/gmio_core/internal/stringstream.h"
#include "../src/gmio_core/internal/stringstream_fast_atof.h"
#include "../src/gmio_core/internal/string_ascii_utils.h"
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -264,7 +267,7 @@ static const char* test_internal__stringstream()
return NULL;
}
static const char* test_internal__string_utils()
static const char* test_internal__string_ascii_utils()
{
char c; /* for loop counter */
@ -328,3 +331,40 @@ static const char* test_internal__string_utils()
return NULL;
}
static const char* __tc__test_internal__locale_utils()
{
const char* lc = setlocale(LC_NUMERIC, "");
if (lc != NULL
&& gmio_ascii_stricmp(lc, "C") != 0
&& gmio_ascii_stricmp(lc, "POSIX") != 0)
{
int error = GMIO_ERROR_OK;
UTEST_ASSERT(!gmio_lc_numeric_is_C());
UTEST_ASSERT(!gmio_check_lc_numeric(&error));
UTEST_COMPARE_INT(GMIO_ERROR_BAD_LC_NUMERIC, error);
}
else {
fprintf(stderr, "\nskip: default locale is NULL or already C/POSIX");
}
lc = setlocale(LC_NUMERIC, "C");
if (lc != NULL) {
int error = GMIO_ERROR_OK;
UTEST_ASSERT(gmio_lc_numeric_is_C());
UTEST_ASSERT(gmio_check_lc_numeric(&error));
UTEST_COMPARE_INT(GMIO_ERROR_OK, error);
}
return NULL;
}
static const char* test_internal__locale_utils()
{
const char* error_str = NULL;
gmio_lc_numeric_save();
printf("\ninfo: current locale is \"%s\"", gmio_lc_numeric());
error_str = __tc__test_internal__locale_utils();
gmio_lc_numeric_restore();
return error_str;
}

View File

@ -22,11 +22,13 @@
#include "../src/gmio_core/error.h"
#include "../src/gmio_core/internal/min_max.h"
#include "../src/gmio_core/internal/string.h"
#include "../src/gmio_core/internal/locale_utils.h"
#include "../src/gmio_stl/stl_error.h"
#include "../src/gmio_stl/stl_infos.h"
#include "../src/gmio_stl/stl_io.h"
#include "../src/gmio_stl/stl_io_options.h"
#include <locale.h>
#include <stddef.h>
#include <stdlib.h>
@ -342,6 +344,39 @@ static const char* test_stl_read_multi_solid()
return res;
}
static const char* test_stla_lc_numeric()
{
struct gmio_stream null_stream = {0};
const struct gmio_stl_mesh null_mesh = {0};
struct gmio_stl_mesh_creator null_meshcreator = {0};
int error[4] = {0};
gmio_lc_numeric_save();
setlocale(LC_NUMERIC, "");
if (!gmio_lc_numeric_is_C()) {
struct gmio_stl_read_options read_opts = {0};
struct gmio_stl_write_options write_opts = {0};
/* By default, check LC_NUMERIC */
error[0] = gmio_stla_read(&null_stream, &null_meshcreator, NULL);
error[1] = gmio_stl_write(
GMIO_STL_FORMAT_ASCII, &null_stream, &null_mesh, NULL);
error[2] = gmio_stla_read(&null_stream, &null_meshcreator, &read_opts);
error[3] = gmio_stl_write(
GMIO_STL_FORMAT_ASCII, &null_stream, &null_mesh, &write_opts);
}
else {
fprintf(stderr, "\nskip: default locale is NULL or already C/POSIX");
}
gmio_lc_numeric_restore();
for (size_t i = 0; i < GMIO_ARRAY_SIZE(error); ++i) {
UTEST_COMPARE_INT(GMIO_ERROR_BAD_LC_NUMERIC, error[i]);
}
return NULL;
}
static void generate_stlb_tests_models()
{
{