12 Commits

Author SHA1 Message Date
red0124
f8fdb97151 Merge pull request #33 from red0124/improvement/getline_update
Improvement/getline update
2024-02-23 01:53:47 +01:00
ado
c0ee100f99 Update ssp.hpp 2024-02-23 01:04:40 +01:00
ado
09e628020d Fix typo in common.hpp 2024-02-23 01:01:31 +01:00
ado
ea21b9ba04 Fix get_line possible leak 2024-02-23 00:59:58 +01:00
ado
230da6a3f2 Update getline implementation for non-POSIX systems 2024-02-22 23:59:58 +01:00
ado
42d618ed64 Make CI unit tests run sequentially 2024-02-18 14:12:10 +01:00
red0124
fdd153b63e Merge pull request #32 from red0124/bugfix/header_usage_on_empty_file
Bugfix/header usage on empty file
2024-02-17 03:27:17 +01:00
ado
c05ab35a33 [skip ci] Update version 2024-02-17 02:41:02 +01:00
ado
8d1637cad1 Update single-header.yml 2024-02-17 02:34:51 +01:00
ado
7530be1c44 Fix undefined behavior when trying to fetch header information on an empty file 2024-02-17 02:26:19 +01:00
ado
4bedc32b63 [skip ci] Update README 2023-08-08 17:26:48 +02:00
ado
7822351a0b [skip ci] Update coverage badge 2023-08-08 17:23:36 +02:00
13 changed files with 91 additions and 76 deletions

View File

@@ -56,7 +56,7 @@ jobs:
- name: Run
working-directory: build
run: ctest --output-on-failure -j ${{steps.cores.outputs.count}}
run: ctest --output-on-failure
- name: Generate coverage report
run: |

View File

@@ -66,4 +66,4 @@ jobs:
- name: Run
working-directory: build
run: ctest --output-on-failure -j ${{steps.cores.outputs.count}}
run: ctest --output-on-failure

View File

@@ -56,4 +56,4 @@ jobs:
- name: Run
working-directory: build
run: ctest --output-on-failure -j ${{steps.cores.outputs.count}}
run: ctest --output-on-failure

View File

@@ -74,4 +74,4 @@ jobs:
- name: Run
working-directory: build
run: ctest --output-on-failure -j ${{steps.cores.outputs.count}}
run: ctest --output-on-failure

View File

@@ -62,4 +62,4 @@ jobs:
- name: Run
working-directory: build
run: >-
ctest -C Debug --output-on-failure -j ${{steps.cores.outputs.count}}
ctest -C Debug --output-on-failure

View File

@@ -73,4 +73,4 @@ jobs:
- name: Run
working-directory: build
run: ctest --output-on-failure -j ${{steps.cores.outputs.count}}
run: ctest --output-on-failure

View File

@@ -71,4 +71,4 @@ jobs:
- name: Run
working-directory: build
run: ctest --output-on-failure -j ${{steps.cores.outputs.count}}
run: ctest --output-on-failure

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14)
project(
ssp
VERSION 1.6.1
VERSION 1.6.2
DESCRIPTION "csv parser"
HOMEPAGE_URL "https://github.com/red0124/ssp"
LANGUAGES CXX

View File

@@ -8,14 +8,14 @@
```
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![coverage](https://coveralls.io/repos/github/red0124/ssp/badge.svg?branch=master)](https://coveralls.io/github/red0124/ssp?branch=master)
[![single-header](https://github.com/red0124/ssp/workflows/single-header-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/single-header.yml)
[![ubuntu-latest-gcc](https://github.com/red0124/ssp/workflows/ubuntu-latest-gcc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/ubuntu-latest-gcc.yml)
[![ubuntu-latest-clang](https://github.com/red0124/ssp/workflows/ubuntu-latest-clang-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/ubuntu-latest-clang.yml)
[![ubuntu-latest-icc](https://github.com/red0124/ssp/workflows/ubuntu-latest-icc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/ubuntu-latest-icc.yml)
[![windows-msys2-gcc](https://github.com/red0124/ssp/workflows/win-msys2-gcc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msys2-gcc.yml)
[![windows-msys2-clang](https://github.com/red0124/ssp/workflows/win-msys2-clang-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msys2-clang.yml)
[![win-msvc-ci](https://github.com/red0124/ssp/workflows/win-msvc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msvc.yml)
[![single-header-ci](https://github.com/red0124/ssp/workflows/single-header-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/single-header.yml)
[![coverage](https://coveralls.io/repos/github/red0124/ssp/badge.svg?branch=master/coverage_ci)](https://coveralls.io/github/red0124/ssp?branch=master/coverage_ci)
[![windows-msvc](https://github.com/red0124/ssp/workflows/win-msvc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msvc.yml)
A header only "csv" parser which is fast and versatile with modern C++ api. Requires compiler with C++17 support. [Can also be used to convert strings to specific types.](#the-converter)

View File

@@ -1,7 +1,9 @@
#pragma once
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
namespace ss {
@@ -12,6 +14,7 @@ using string_range = std::pair<const char*, const char*>;
using split_data = std::vector<string_range>;
constexpr inline auto default_delimiter = ",";
constexpr inline auto get_line_initial_buffer_size = 128;
template <bool StringError>
inline void assert_string_error_defined() {
@@ -30,55 +33,60 @@ inline ssize_t get_line(char** lineptr, size_t* n, FILE* stream) {
return getline(lineptr, n, stream);
}
#else
using ssize_t = int64_t;
inline ssize_t get_line(char** lineptr, size_t* n, FILE* stream) {
size_t pos;
int c;
if (lineptr == nullptr || stream == nullptr || n == nullptr) {
using ssize_t = int64_t;
ssize_t get_line(char** lineptr, size_t* n, FILE* fp) {
if (lineptr == nullptr || n == nullptr || fp == nullptr) {
errno = EINVAL;
return -1;
}
c = getc(stream);
if (c == EOF) {
return -1;
}
char buff[get_line_initial_buffer_size];
if (*lineptr == nullptr) {
*lineptr = static_cast<char*>(malloc(128));
if (*lineptr == nullptr) {
if (*lineptr == nullptr || *n < sizeof(buff)) {
size_t new_n = sizeof(buff);
auto new_lineptr = static_cast<char*>(realloc(*lineptr, new_n));
if (new_lineptr == nullptr) {
errno = ENOMEM;
return -1;
}
*n = 128;
*lineptr = new_lineptr;
*n = new_n;
}
pos = 0;
while (c != EOF) {
if (pos + 1 >= *n) {
size_t new_size = *n + (*n >> 2);
if (new_size < 128) {
new_size = 128;
}
char* new_ptr = static_cast<char*>(
realloc(static_cast<void*>(*lineptr), new_size));
if (new_ptr == nullptr) {
(*lineptr)[0] = '\0';
while (fgets(buff, sizeof(buff), fp) != nullptr) {
size_t line_used = strlen(*lineptr);
size_t buff_used = strlen(buff);
if (*n < buff_used + line_used) {
size_t new_n = *n * 2;
auto new_lineptr = static_cast<char*>(realloc(*lineptr, *n));
if (new_lineptr == nullptr) {
errno = ENOMEM;
return -1;
}
*n = new_size;
*lineptr = new_ptr;
*lineptr = new_lineptr;
*n = new_n;
}
(*lineptr)[pos++] = c;
if (c == '\n') {
break;
memcpy(*lineptr + line_used, buff, buff_used);
line_used += buff_used;
(*lineptr)[line_used] = '\0';
if ((*lineptr)[line_used - 1] == '\n') {
return line_used;
}
c = getc(stream);
}
(*lineptr)[pos] = '\0';
return pos;
return -1;
}
#endif
} /* ss */

View File

@@ -155,7 +155,7 @@ public:
return;
}
if (header_.empty()) {
if (header_.empty() && !eof()) {
split_header_data();
}

View File

@@ -6,7 +6,7 @@ project(
'cpp_std=c++17',
'buildtype=debugoptimized',
'wrap_mode=forcefallback'],
version: '1.6.1',
version: '1.6.2',
meson_version:'>=0.54.0')
fast_float_dep = dependency('fast_float')

71
ssp.hpp
View File

@@ -1,5 +1,6 @@
#include <algorithm>
#include <array>
#include <cerrno>
#include <charconv>
#include <cstdint>
#include <cstdio>
@@ -625,6 +626,7 @@ using string_range = std::pair<const char*, const char*>;
using split_data = std::vector<string_range>;
constexpr inline auto default_delimiter = ",";
constexpr inline auto get_line_initial_buffer_size = 128;
template <bool StringError>
inline void assert_string_error_defined() {
@@ -643,55 +645,60 @@ inline ssize_t get_line(char** lineptr, size_t* n, FILE* stream) {
return getline(lineptr, n, stream);
}
#else
using ssize_t = int64_t;
inline ssize_t get_line(char** lineptr, size_t* n, FILE* stream) {
size_t pos;
int c;
if (lineptr == nullptr || stream == nullptr || n == nullptr) {
using ssize_t = int64_t;
ssize_t get_line(char** lineptr, size_t* n, FILE* fp) {
if (lineptr == nullptr || n == nullptr || fp == nullptr) {
errno = EINVAL;
return -1;
}
c = getc(stream);
if (c == EOF) {
return -1;
}
char buff[get_line_initial_buffer_size];
if (*lineptr == nullptr) {
*lineptr = static_cast<char*>(malloc(128));
if (*lineptr == nullptr) {
if (*lineptr == nullptr || *n < sizeof(buff)) {
size_t new_n = sizeof(buff);
auto new_lineptr = static_cast<char*>(realloc(*lineptr, new_n));
if (new_lineptr == nullptr) {
errno = ENOMEM;
return -1;
}
*n = 128;
*lineptr = new_lineptr;
*n = new_n;
}
pos = 0;
while (c != EOF) {
if (pos + 1 >= *n) {
size_t new_size = *n + (*n >> 2);
if (new_size < 128) {
new_size = 128;
}
char* new_ptr = static_cast<char*>(
realloc(static_cast<void*>(*lineptr), new_size));
if (new_ptr == nullptr) {
(*lineptr)[0] = '\0';
while (fgets(buff, sizeof(buff), fp) != nullptr) {
size_t line_used = strlen(*lineptr);
size_t buff_used = strlen(buff);
if (*n < buff_used + line_used) {
size_t new_n = *n * 2;
auto new_lineptr = static_cast<char*>(realloc(*lineptr, *n));
if (new_lineptr == nullptr) {
errno = ENOMEM;
return -1;
}
*n = new_size;
*lineptr = new_ptr;
*lineptr = new_lineptr;
*n = new_n;
}
(*lineptr)[pos++] = c;
if (c == '\n') {
break;
memcpy(*lineptr + line_used, buff, buff_used);
line_used += buff_used;
(*lineptr)[line_used] = '\0';
if ((*lineptr)[line_used - 1] == '\n') {
return line_used;
}
c = getc(stream);
}
(*lineptr)[pos] = '\0';
return pos;
return -1;
}
#endif
} /* ss */
@@ -2281,7 +2288,7 @@ public:
return;
}
if (header_.empty()) {
if (header_.empty() && !eof()) {
split_header_data();
}