* Add length param for seralization write_string

to increase a little bit the performance for big strings.
* Change the format of storing strings for serial-bin.
This commit is contained in:
Patrick Pelissier committed 2020-06-13 17:26:07 +02:00
1 parent 89b6e1aac0
commit cb4b43e2e8
6 files changed
+108 -24

No files matched your search

+2 -2
View File
@@ -5869,7 +5869,7 @@ the following fields with the following definition:
Write the float 'data' of 'size_of_type' bytes into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_string:
Write the null-terminated string 'data'into the serial stream 'serial'.
Write the null-terminated string 'data' of 'length' characters into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_start:
Start writing an array of 'number_of_elements' objects into the serial stream 'serial'.
@@ -5981,7 +5981,7 @@ The full C definition are:
m_serial_return_code_t (*write_boolean)(m_serial_write_t serial, const bool b);
m_serial_return_code_t (*write_integer)(m_serial_write_t serial, const long long i, const size_t size_of_type);
m_serial_return_code_t (*write_float)(m_serial_write_t serial, const long double f, const size_t size_of_type);
m_serial_return_code_t (*write_string)(m_serial_write_t serial, const char s[]);
m_serial_return_code_t (*write_string)(m_serial_write_t serial, const char s[], size_t length);
m_serial_return_code_t (*write_array_start)(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements);
m_serial_return_code_t (*write_array_next)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_array_end)(m_serial_local_t local, m_serial_write_t serial);
+1 -1
View File
@@ -50,4 +50,4 @@ V0.4.*: * The order of a list initialized using M_LET is reversed
to match what is done for ARRAY (and the C++ forward_list).
* Rename M_SKIP, M_KEEP & M_MID into M_SKIP_ARGS, M_KEEP_ARGS & M_MID_ARGS
due to conflict with glibc malloc.h (that defines M_KEEP for compatibility).
* Method write_string of m_serial expects a new argument (number of characters)
+14 -3
View File
@@ -2995,7 +2995,7 @@ typedef struct m_serial_write_interface_s {
m_serial_return_code_t (*write_boolean)(m_serial_write_t,const bool data);
m_serial_return_code_t (*write_integer)(m_serial_write_t,const long long data, const size_t size_of_type);
m_serial_return_code_t (*write_float)(m_serial_write_t, const long double data, const size_t size_of_type);
m_serial_return_code_t (*write_string)(m_serial_write_t,const char data[]);
m_serial_return_code_t (*write_string)(m_serial_write_t,const char data[], size_t len);
m_serial_return_code_t (*write_array_start)(m_serial_local_t, m_serial_write_t, const size_t number_of_elements);
m_serial_return_code_t (*write_array_next)(m_serial_local_t, m_serial_write_t);
m_serial_return_code_t (*write_array_end)(m_serial_local_t, m_serial_write_t);
@@ -3031,8 +3031,8 @@ typedef struct m_serial_write_interface_s {
float: (serial)->m_interface->write_float(serial, M_AS_TYPE(float,(x)), sizeof (x)), \
double: (serial)->m_interface->write_float(serial, M_AS_TYPE(double,(x)), sizeof (x)), \
long double: (serial)->m_interface->write_float(serial, M_AS_TYPE(long double,(x)), sizeof (x)), \
const char *: (serial)->m_interface->write_string(serial, M_AS_TYPE(const char *,(x))), \
char *: (serial)->m_interface->write_string(serial, M_AS_TYPE(char *,(x))), \
const char *: (serial)->m_interface->write_string(serial, M_AS_TYPE(const char *,(x)), m_core_out_serial_strlen(M_AS_TYPE(const char *,(x))) ), \
char *: (serial)->m_interface->write_string(serial, M_AS_TYPE(char *,(x)), m_core_out_serial_strlen(M_AS_TYPE(const char *,(x))) ), \
const void *: M_SERIAL_FAIL /* unsupported */, \
void *: M_SERIAL_FAIL /* unsupported */)
@@ -3089,4 +3089,15 @@ M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_float, float, read_float, long dou
M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_double, double, read_float, long double)
M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_ldouble, long double, read_float, long double)
/* Encapsulation of strlen to avoid warnings in M_OUT_SERIAL_DEFAULT_ARG
* because of expanded code will call strlen with NULL (which is illegal)
* However, the branch where it is called is unreachable, so the warning
* is not justified. */
static size_t
m_core_out_serial_strlen(const char s[])
{
assert(s != NULL);
return strlen(s);
}
#endif
+83 -12
View File
@@ -30,6 +30,66 @@
#include "m-core.h"
#include "m-string.h"
/* Internal service:
* Write size_t in the stream in a compact form to reduce consumption
* (and I/O bandwidth)
*/
static inline bool
m_serial_bin_write_size(FILE *f, const size_t size)
{
bool b;
if (M_LIKELY(size < 253))
{
b = EOF != fputc((unsigned char) size, f);
} else if (size < 1ULL << 16) {
b = EOF != fputc(253, f); // Save 16 bits encoding
b &= EOF != fputc((unsigned char) (size >> 8), f);
b &= EOF != fputc((unsigned char) size, f);
} else if (size < 1ULL<< 32) {
b = EOF != fputc(254, f); // Save 32 bits encoding
b &= EOF != fputc((unsigned char) (size >> 24), f);
b &= EOF != fputc((unsigned char) (size >> 16), f);
b &= EOF != fputc((unsigned char) (size >> 8), f);
b &= EOF != fputc((unsigned char) size, f);
} else {
b = EOF != fputc(255, f); // Save 64 bits encoding
b &= EOF != fputc((unsigned char) (size >> 56), f);
b &= EOF != fputc((unsigned char) (size >> 48), f);
b &= EOF != fputc((unsigned char) (size >> 40), f);
b &= EOF != fputc((unsigned char) (size >> 32), f);
b &= EOF != fputc((unsigned char) (size >> 24), f);
b &= EOF != fputc((unsigned char) (size >> 16), f);
b &= EOF != fputc((unsigned char) (size >> 8), f);
b &= EOF != fputc((unsigned char) size, f);
}
return b;
}
/* Internal service:
* Read size_t in the stream from a compact form to reduce consumption
* (and I/O bandwidth)
*/
static inline bool
m_serial_bin_read_size(FILE *f, size_t *size)
{
int c;
c = fgetc(f);
if (M_UNLIKELY(c == EOF)) return false;
if (M_LIKELY(c < 253)) {
*size = (size_t) c;
return true;
}
size_t s = 0;
int l = (c = 255) ? 8 : (c == 254) ? 4 : 2;
for(int i = 0; i < l; i++) {
c = fgetc(f);
if (M_UNLIKELY(c == EOF)) return false;
s = (s << 8) | (size_t) c;
}
*size = s;
return true;
}
/* Write the boolean 'data' into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
@@ -105,12 +165,17 @@ m_serial_bin_write_float(m_serial_write_t serial, const long double data, const
/* Write the null-terminated string 'data'into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
m_serial_bin_write_string(m_serial_write_t serial, const char data[])
m_serial_bin_write_string(m_serial_write_t serial, const char data[], size_t length)
{
STRINGI_ASSUME(length == strlen(data) );
FILE *f = (FILE *)serial->data[0].p;
size_t l = strlen(data);
size_t n = fwrite (M_ASSIGN_CAST(const void*, data), 1, l+1, f);
return n == l+1 ? M_SERIAL_OK_DONE : M_SERIAL_FAIL;
assert(f != NULL && data != NULL);
// Write first the number of (non null) characters
if (m_serial_bin_write_size(f, length) != true) return M_SERIAL_FAIL;
// Write the characters (excluding the final null char)
// NOTE: fwrite supports length == 0.
size_t n = fwrite (M_ASSIGN_CAST(const void*, data), 1, length, f);
return (n == length) ? M_SERIAL_OK_DONE : M_SERIAL_FAIL;
}
/* Start writing an array of 'number_of_elements' objects into the serial stream 'serial'.
@@ -345,14 +410,20 @@ m_serial_bin_read_float(m_serial_read_t serial, long double *r, const size_t siz
static inline m_serial_return_code_t
m_serial_bin_read_string(m_serial_read_t serial, struct string_s *s){
FILE *f = (FILE*) serial->data[0].p;
string_clean(s);
int c;
c = fgetc(f);
while (c != 0 && c != EOF) {
string_push_back(s, c);
c = fgetc(f);
}
return c != EOF ? M_SERIAL_OK_DONE : M_SERIAL_FAIL;
assert(f != NULL && s != NULL);
// First read the number of non null characters
size_t length;
if (m_serial_bin_read_size(f, &length) != true) return M_SERIAL_FAIL;
// Use of internal string interface to dimension the string
string_reserve(s, length + 1);
char *p = stringi_get_str(s);
stringi_set_size(s, length);
// Read the characters excluding the final null one.
// NOTE: fread supports length == 0.
size_t n = fread(M_ASSIGN_CAST(void*, p), 1, length, f);
// Force the final null character
p[length] = 0;
return (n == length) ? M_SERIAL_OK_DONE : M_SERIAL_FAIL;
}
/* Start reading from the stream 'serial' an array.
+6 -4
View File
@@ -63,14 +63,16 @@ m_serial_json_write_float(m_serial_write_t serial, const long double data, const
/* Write the null-terminated string 'data'into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
m_serial_json_write_string(m_serial_write_t serial, const char data[])
m_serial_json_write_string(m_serial_write_t serial, const char data[], size_t length)
{
STRINGI_ASSUME(length == strlen(data) );
FILE *f = (FILE *)serial->data[0].p;
/* Build dummy string to reuse string_out_str */
assert(f != NULL && data != NULL);
/* HACK: Build dummy string to reuse string_out_str */
string_t v2;
uintptr_t ptr = (uintptr_t) data;
v2->u.heap.size = strlen(data);
v2->u.heap.alloc = v2->u.heap.size + 1;
v2->u.heap.size = length;
v2->u.heap.alloc = length + 1;
v2->ptr = (char*)ptr;
string_out_str(f, v2);
return M_SERIAL_OK_DONE;
+2 -2
View File
@@ -1241,7 +1241,7 @@ static inline m_serial_return_code_t
string_out_serial(m_serial_write_t serial, const string_t v)
{
assert (serial != NULL && serial->m_interface != NULL);
return serial->m_interface->write_string(serial, string_get_cstr(v));
return serial->m_interface->write_string(serial, string_get_cstr(v), string_size(v) );
}
/* Read the formatted string from the serializer
@@ -2047,7 +2047,7 @@ namespace m_string {
{ \
BOUNDED_STRINGI_CONTRACT(v, max_size); \
assert (serial != NULL && serial->m_interface != NULL); \
return serial->m_interface->write_string(serial, v->s); \
return serial->m_interface->write_string(serial, v->s, strlen(v->s) ); \
} \
\
static inline m_serial_return_code_t \