From 23044a347d8d569c617da202976bd138c9ae7264 Mon Sep 17 00:00:00 2001 From: Thomas Beutlich Date: Fri, 3 Nov 2023 20:49:42 +0100 Subject: [PATCH] Enable csv2shp build with MSVC by removing regex dependency --- cmake/contrib.cmake | 39 ++++++--------- contrib/csv2shp.c | 117 ++++++++++++++++++++++++-------------------- 2 files changed, 80 insertions(+), 76 deletions(-) diff --git a/cmake/contrib.cmake b/cmake/contrib.cmake index 221003a..d834761 100644 --- a/cmake/contrib.cmake +++ b/cmake/contrib.cmake @@ -1,18 +1,8 @@ if(BUILD_SHAPELIB_CONTRIB) - if(NOT MSVC) - add_executable(csv2shp ${PROJECT_SOURCE_DIR}/contrib/csv2shp.c) - target_link_libraries(csv2shp shp) - set_target_properties(csv2shp PROPERTIES FOLDER "contrib") + add_executable(csv2shp ${PROJECT_SOURCE_DIR}/contrib/csv2shp.c) + target_link_libraries(csv2shp shp) + set_target_properties(csv2shp PROPERTIES FOLDER "contrib") - install( - TARGETS csv2shp - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) - endif() - add_executable(dbfcat ${PROJECT_SOURCE_DIR}/contrib/dbfcat.c) target_link_libraries(dbfcat shp) set_target_properties(dbfcat PROPERTIES FOLDER "contrib") @@ -59,17 +49,18 @@ if(BUILD_SHAPELIB_CONTRIB) install( TARGETS - dbfcat - dbfinfo - shpcat - shpdxf - shpfix - shpsort - Shape_PointInPoly - shpcentrd - shpdata - shpinfo - shpwkb + csv2shp + dbfcat + dbfinfo + shpcat + shpdxf + shpfix + shpsort + Shape_PointInPoly + shpcentrd + shpdata + shpinfo + shpwkb PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/contrib/csv2shp.c b/contrib/csv2shp.c index 218c775..a6fead0 100644 --- a/contrib/csv2shp.c +++ b/contrib/csv2shp.c @@ -60,15 +60,24 @@ Email: */ +#include #include #include #include #include "shapefil.h" -#include "regex.h" #define MAX_COLUMNS 30 +#if defined(_MSC_VER) +#define STRCASECMP(a, b) (_stricmp(a, b)) +#elif defined(WIN32) || defined(_WIN32) +#define STRCASECMP(a, b) (stricmp(a, b)) +#else +#include +#define STRCASECMP(a, b) (strcasecmp(a, b)) +#endif + typedef struct column_t { DBFFieldType eType; @@ -81,7 +90,7 @@ int strnchr(const char *s, char c) { int n = 0; - for (int x = 0; x < strlen(s); x++) + for (size_t x = 0; x < strlen(s); x++) { if (c == s[x]) { @@ -127,41 +136,65 @@ char *delimited_column(char *s, char delim, int n) return szreturn; } -/* Determines the most specific column type. - The most specific types from most to least are integer, float, string. */ -DBFFieldType str_to_fieldtype(const char *s) +/* returns the number of decimals in a real number given as a string s */ +int str_to_ndecimals(const char *s) { - regex_t regex_i; - if (0 != regcomp(®ex_i, "^[0-9]+$", REG_NOSUB | REG_EXTENDED)) + if (s == NULL) { - fprintf(stderr, "integer regex complication failed\n"); - exit(EXIT_FAILURE); + return -1; } - if (0 == regexec(®ex_i, s, 0, NULL, 0)) + /* Check for float: ^-?[0-9]+\.[0-9]+$ */ + if (!isdigit(s[0]) && s[0] != '-') { - regfree(®ex_i); - return FTInteger; + return -1; } - regfree(®ex_i); + size_t len = strlen(s); + if (!isdigit(s[len - 1])) + { + return -1; + } - regex_t regex_d; - if (0 != regcomp(®ex_d, "^-?[0-9]+\\.[0-9]+$", REG_NOSUB | REG_EXTENDED)) + const char* decimalPoint = strchr(s, '.'); + if ((decimalPoint == NULL) || (strchr(decimalPoint + 1, '.') != NULL)) { - fprintf(stderr, "integer regex complication failed\n"); - exit(EXIT_FAILURE); + return -1; } - if (0 == regexec(®ex_d, s, 0, NULL, 0)) + for (size_t x = 1; x < len - 1; x++) { - regfree(®ex_d); - return FTDouble; + if (!isdigit(s[x]) && s[x] != '.') + { + return -1; + } } - regfree(®ex_d); + return (int)strlen(decimalPoint + 1); +} + +/* Determines the most specific column type. + The most specific types from most to least are integer, float, string. */ +DBFFieldType str_to_fieldtype(const char *s) +{ + size_t len = strlen(s); - return FTString; + /* Check for integer: ^[0-9]+$ */ + int isInteger = 1; + for (size_t x = 0; x < len; x++) + { + if (!isdigit(s[x])) + { + isInteger = 0; + break; + } + } + if (isInteger) + { + return FTInteger; + } + + return str_to_ndecimals(s) > 0 ? FTDouble : FTString; } /* returns the field width */ @@ -172,7 +205,7 @@ int str_to_nwidth(const char *s, DBFFieldType eType) case FTString: case FTInteger: case FTDouble: - return strlen(s); + return (int)strlen(s); default: fprintf(stderr, "str_to_nwidth: unexpected type\n"); @@ -180,31 +213,6 @@ int str_to_nwidth(const char *s, DBFFieldType eType) } } -/* returns the number of decimals in a real number given as a string s */ -int str_to_ndecimals(const char *s) -{ - regex_t regex_d; - if (0 != regcomp(®ex_d, "^-?[0-9]+\\.([0-9]+)$", REG_EXTENDED)) - { - fprintf(stderr, "integer regex complication failed\n"); - exit(EXIT_FAILURE); - } - - regmatch_t pmatch[2]; - if (0 != regexec(®ex_d, s, 2, &pmatch[0], 0)) - { - return -1; - } - - char szbuffer[4096]; - strncpy(szbuffer, &s[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); - szbuffer[pmatch[1].rm_eo - pmatch[1].rm_so] = '\0'; - - regfree(®ex_d); - - return strlen(szbuffer); -} - /* returns true if f1 is more general than f2, otherwise false */ int more_general_field_type(DBFFieldType t1, DBFFieldType t2) { @@ -329,13 +337,13 @@ int main(int argc, char **argv) for (int x = 0; x <= n_columns; x++) { if (0 == - strcasecmp("Longitude", delimited_column(sbuffer, delimiter, x))) + STRCASECMP("Longitude", delimited_column(sbuffer, delimiter, x))) { n_longitude = x; } - + else if (0 == - strcasecmp("Latitude", delimited_column(sbuffer, delimiter, x))) + STRCASECMP("Latitude", delimited_column(sbuffer, delimiter, x))) { n_latitude = x; } @@ -354,7 +362,7 @@ int main(int argc, char **argv) /* determine best fit for each column */ - printf("Anaylzing column types...\n"); + printf("Analyzing column types...\n"); #ifdef DEBUG printf("debug: string type = %i\n", FTString); @@ -374,6 +382,7 @@ int main(int argc, char **argv) fseek(csv_f, 0, SEEK_SET); fgets(sbuffer, 4000, csv_f); + strip_crlf(sbuffer); while (!feof(csv_f)) { @@ -389,6 +398,7 @@ int main(int argc, char **argv) } continue; } + strip_crlf(sbuffer); char szfield[4096]; strcpy(szfield, delimited_column(sbuffer, delimiter, x)); @@ -400,6 +410,7 @@ int main(int argc, char **argv) columns[x].nDecimals = 0; fseek(csv_f, 0, SEEK_SET); fgets(sbuffer, 4000, csv_f); + strip_crlf(sbuffer); continue; } if (columns[x].nWidth < str_to_nwidth(szfield, columns[x].eType)) @@ -450,6 +461,7 @@ int main(int argc, char **argv) fseek(csv_f, 0, SEEK_SET); fgets(sbuffer, 4000, csv_f); /* skip header */ + strip_crlf(sbuffer); n_columns = strnchr(sbuffer, delimiter); n_line = 1; @@ -458,6 +470,7 @@ int main(int argc, char **argv) { n_line++; fgets(sbuffer, 4000, csv_f); + strip_crlf(sbuffer); /* write to shape file */ double x_pt = atof(delimited_column(sbuffer, delimiter, n_longitude));