2015-03-03 00:38:33 +08:00
|
|
|
/****************************************************************************
|
|
|
|
** GeomIO Library
|
2015-05-01 00:19:45 +08:00
|
|
|
** Copyright Fougue (2 Mar. 2015)
|
2015-03-03 00:38:33 +08:00
|
|
|
** contact@fougsys.fr
|
|
|
|
**
|
|
|
|
** 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
|
2015-03-30 15:05:25 +08:00
|
|
|
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
|
2015-03-03 00:38:33 +08:00
|
|
|
****************************************************************************/
|
|
|
|
|
2015-03-03 00:54:57 +08:00
|
|
|
#include "string_parse.h"
|
2014-01-27 22:28:12 +08:00
|
|
|
|
2015-03-13 18:04:14 +08:00
|
|
|
#include "helper_stream.h"
|
2015-03-31 22:16:04 +08:00
|
|
|
#include "string_utils.h"
|
2015-04-02 22:09:49 +08:00
|
|
|
#define GMIO_USE_FAST_ATOF
|
2015-03-31 16:10:26 +08:00
|
|
|
#ifdef GMIO_USE_FAST_ATOF
|
|
|
|
# include "fast_atof.h"
|
|
|
|
#endif
|
2015-03-13 18:04:14 +08:00
|
|
|
|
2014-01-27 22:28:12 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2015-03-03 00:54:57 +08:00
|
|
|
void gmio_string_stream_fwd_iterator_init(gmio_string_stream_fwd_iterator_t *it)
|
2014-01-28 05:57:10 +08:00
|
|
|
{
|
2015-03-03 23:44:14 +08:00
|
|
|
/* Trick: declaring the buffer exhausted will actually trigger the first
|
|
|
|
* call to gmio_stream_read() inside gmio_next_char()
|
|
|
|
*/
|
2015-03-03 17:35:36 +08:00
|
|
|
it->buffer.len = 0;
|
|
|
|
it->buffer_pos = it->buffer.max_len;
|
|
|
|
gmio_next_char(it);
|
2014-01-28 05:57:10 +08:00
|
|
|
}
|
|
|
|
|
2015-03-03 23:44:14 +08:00
|
|
|
const char *gmio_current_char(const gmio_string_stream_fwd_iterator_t *it)
|
2014-01-27 22:28:12 +08:00
|
|
|
{
|
2015-03-31 21:53:58 +08:00
|
|
|
if (it->buffer_pos < it->buffer.len)
|
2015-03-03 17:35:36 +08:00
|
|
|
return it->buffer.ptr + it->buffer_pos;
|
|
|
|
return NULL;
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
|
|
|
|
2015-03-31 23:09:36 +08:00
|
|
|
GMIO_INLINE gmio_bool_t gmio_is_next_char_buffered(
|
|
|
|
const gmio_string_stream_fwd_iterator_t *it)
|
2014-01-27 22:28:12 +08:00
|
|
|
{
|
2015-03-31 23:09:36 +08:00
|
|
|
return (it->buffer_pos + 1) < it->buffer.len ? GMIO_TRUE : GMIO_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
GMIO_INLINE const char* gmio_next_char_from_buffer(
|
|
|
|
gmio_string_stream_fwd_iterator_t *it)
|
|
|
|
{
|
|
|
|
++(it->buffer_pos);
|
|
|
|
return it->buffer.ptr + it->buffer_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
GMIO_INLINE const char* gmio_next_char_from_stream(
|
|
|
|
gmio_string_stream_fwd_iterator_t *it)
|
|
|
|
{
|
|
|
|
/* Read next chunk of data */
|
|
|
|
it->buffer_pos = 0;
|
2015-04-02 21:38:06 +08:00
|
|
|
it->buffer.len = gmio_stream_read(
|
|
|
|
it->stream, it->buffer.ptr, sizeof(char), it->buffer.max_len);
|
|
|
|
if (it->buffer.len > 0) {
|
2015-03-31 23:09:36 +08:00
|
|
|
if (it->stream_read_hook != NULL)
|
|
|
|
it->stream_read_hook(it->cookie, &it->buffer);
|
|
|
|
return it->buffer.ptr;
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
return NULL;
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
|
|
|
|
2015-03-31 23:09:36 +08:00
|
|
|
const char *gmio_next_char(gmio_string_stream_fwd_iterator_t *it)
|
|
|
|
{
|
|
|
|
if (gmio_is_next_char_buffered(it) == GMIO_TRUE)
|
|
|
|
return gmio_next_char_from_buffer(it);
|
|
|
|
return gmio_next_char_from_stream(it);
|
|
|
|
}
|
|
|
|
|
2015-03-03 00:54:57 +08:00
|
|
|
void gmio_skip_spaces(gmio_string_stream_fwd_iterator_t *it)
|
2014-01-27 22:28:12 +08:00
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
const char* curr_char = gmio_current_char(it);
|
2015-03-31 21:53:58 +08:00
|
|
|
while (curr_char != NULL && gmio_clocale_isspace(*curr_char))
|
2015-03-03 17:35:36 +08:00
|
|
|
curr_char = gmio_next_char(it);
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
|
|
|
|
2015-03-20 00:31:08 +08:00
|
|
|
int gmio_eat_word(
|
|
|
|
gmio_string_stream_fwd_iterator_t *it, gmio_string_buffer_t *buffer)
|
2014-01-27 22:28:12 +08:00
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
const char* stream_curr_char = NULL;
|
|
|
|
int isspace_res = 0;
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
if (buffer == NULL || buffer->ptr == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
buffer->len = 0;
|
|
|
|
gmio_skip_spaces(it);
|
|
|
|
stream_curr_char = gmio_current_char(it);
|
2015-03-31 21:53:58 +08:00
|
|
|
if (stream_curr_char == NULL) { /* Empty word */
|
|
|
|
buffer->ptr[0] = 0;
|
|
|
|
buffer->len = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
2015-03-20 00:31:08 +08:00
|
|
|
while (i < buffer->max_len
|
|
|
|
&& stream_curr_char != NULL
|
|
|
|
&& isspace_res == 0)
|
|
|
|
{
|
2015-03-31 21:53:58 +08:00
|
|
|
isspace_res = gmio_clocale_isspace(*stream_curr_char);
|
2015-03-03 17:35:36 +08:00
|
|
|
if (isspace_res == 0) {
|
|
|
|
buffer->ptr[i] = *stream_curr_char;
|
|
|
|
stream_curr_char = gmio_next_char(it);
|
|
|
|
++i;
|
|
|
|
}
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
2015-03-03 17:35:36 +08:00
|
|
|
|
|
|
|
if (i < buffer->max_len) {
|
|
|
|
buffer->ptr[i] = 0; /* End string with terminating null byte */
|
|
|
|
buffer->len = i;
|
2015-03-31 23:09:36 +08:00
|
|
|
if (stream_curr_char != NULL
|
|
|
|
|| gmio_stream_at_end(it->stream) == GMIO_TRUE)
|
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
return 0;
|
2015-03-31 23:09:36 +08:00
|
|
|
}
|
2015-03-31 21:53:58 +08:00
|
|
|
return -3;
|
2015-03-03 17:35:36 +08:00
|
|
|
}
|
2015-03-31 21:53:58 +08:00
|
|
|
return -4;
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
|
|
|
|
2015-03-03 17:44:45 +08:00
|
|
|
int gmio_get_float32(const char *str, gmio_float32_t *value_ptr)
|
2014-01-27 22:28:12 +08:00
|
|
|
{
|
2015-03-31 16:10:26 +08:00
|
|
|
#if defined(GMIO_USE_FAST_ATOF)
|
2015-03-31 21:53:58 +08:00
|
|
|
const char* end_ptr = NULL;
|
2015-03-31 16:10:26 +08:00
|
|
|
*value_ptr = fast_atof(str, &end_ptr);
|
|
|
|
#elif defined(GMIO_HAVE_STRTOF_FUNC) /* Requires C99 */
|
2015-03-31 21:53:58 +08:00
|
|
|
char* end_ptr = NULL;
|
2015-03-31 16:10:26 +08:00
|
|
|
*value_ptr = strtof(str, &end_ptr);
|
2014-01-27 22:28:12 +08:00
|
|
|
#else
|
2015-03-31 21:53:58 +08:00
|
|
|
char* end_ptr = NULL;
|
2015-03-03 17:44:45 +08:00
|
|
|
*value_ptr = (gmio_float32_t)strtod(str, &end_ptr);
|
2014-01-27 22:28:12 +08:00
|
|
|
#endif
|
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
if (end_ptr == str || errno == ERANGE)
|
|
|
|
return -1;
|
2014-01-27 22:28:12 +08:00
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
return 0;
|
2014-01-27 22:28:12 +08:00
|
|
|
}
|
2014-01-28 17:11:26 +08:00
|
|
|
|
2015-03-20 00:31:08 +08:00
|
|
|
gmio_bool_t gmio_checked_next_chars(
|
|
|
|
gmio_string_stream_fwd_iterator_t *it, const char *str)
|
2014-01-28 17:11:26 +08:00
|
|
|
{
|
2015-03-03 17:35:36 +08:00
|
|
|
size_t pos = 0;
|
|
|
|
const char* curr_char = gmio_current_char(it);
|
|
|
|
gmio_bool_t same = curr_char != NULL && *curr_char == *str;
|
2014-01-28 17:11:26 +08:00
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
while (same) {
|
|
|
|
curr_char = gmio_next_char(it);
|
|
|
|
same = curr_char != NULL && *curr_char == str[++pos];
|
|
|
|
}
|
2014-01-28 17:11:26 +08:00
|
|
|
|
2015-03-03 17:35:36 +08:00
|
|
|
return same;
|
2014-01-28 17:11:26 +08:00
|
|
|
}
|