├── wbUtils.cpp ├── wbExit.h ├── .gitignore ├── wbInit.h ├── wbPPM.h ├── wb_test.cpp ├── wbDirectory.h ├── wbThrust.h ├── wbSparse.h ├── wbUtils.h ├── README.md ├── wbCUDA.cpp ├── wbCast.h ├── .clang-format ├── wbDataset_test.cpp ├── sources.cmake ├── wbAssert.h ├── wbMPI.h ├── wbDataset.h ├── wbPath.h ├── appveyor.yml ├── wbImage.h ├── CMakeLists.txt ├── wbPath.cpp ├── wbTypes.h ├── wbArg.h ├── Makefile ├── .travis.yml ├── LICENSE.TXT ├── wbMPI.cpp ├── wbSolution.h ├── wbSort.h ├── wbInit.cpp ├── wbCUDA.h ├── wbSparse.cpp ├── wbFile.h ├── wbDirectory.cpp ├── wbExit.cpp ├── wbLogger.h ├── wbImport.h ├── wbMalloc.h ├── wbExport.h ├── wbArg.cpp ├── wbImage.cpp ├── wbComparator.h ├── wb.h ├── wbPPM.cpp ├── wbDataset.cpp ├── wbTimer.h ├── wbFile.cpp ├── wbLogger.cpp ├── vendor └── json11.hpp ├── wbMD5.h ├── wbSolution.cpp ├── wbString.h ├── wbExport.cpp ├── wbTimer.cpp └── wbImport.cpp /wbUtils.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" -------------------------------------------------------------------------------- /wbExit.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_EXIT_H__ 3 | #define __WB_EXIT_H__ 4 | 5 | void wb_atExit(void); 6 | 7 | #endif /* __WB_EXIT_H__ */ 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.i 2 | *.ii 3 | *.gpu 4 | *.ptx 5 | *.cubin 6 | *.fatbin 7 | build 8 | build-* 9 | 10 | .srclib-cache/ 11 | .srclib-store/ 12 | *.swp 13 | *.log 14 | *.o 15 | lib/ 16 | test-dataset/ 17 | test 18 | test.dSYM/ 19 | Linux-x86_64 20 | -------------------------------------------------------------------------------- /wbInit.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_INIT_H__ 4 | #define __WB_INIT_H__ 5 | 6 | #ifndef _MSC_VER 7 | __attribute__((__constructor__)) 8 | #endif /* _MSC_VER */ 9 | void wb_init(int *argc, char ***argv); 10 | 11 | #endif /* __WB_INIT_H__ */ 12 | -------------------------------------------------------------------------------- /wbPPM.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __wbPPM_H__ 4 | #define __wbPPM_H__ 5 | 6 | START_EXTERN_C 7 | wbImage_t wbPPM_import(const char *filename); 8 | void wbPPM_export(const char *filename, wbImage_t img); 9 | END_EXTERN_C 10 | 11 | #endif /* __wbPPM_H__ */ 12 | -------------------------------------------------------------------------------- /wb_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | 3 | #include "wb.h" 4 | #include "vendor/catch.hpp" 5 | 6 | 7 | 8 | TEST_CASE("Can use basic functions", "[WB]") { 9 | wbTime_start(GPU, "timer."); //@@ start a timer 10 | wbTime_stop(GPU, "timer."); //@@ stop the timer 11 | 12 | } 13 | -------------------------------------------------------------------------------- /wbDirectory.h: -------------------------------------------------------------------------------- 1 | #ifndef __WB_DIRECTORY__ 2 | #define __WB_DIRECTORY__ 3 | 4 | extern const char wbDirectorySeperator; 5 | EXTERN_C char *wbDirectory_name(const char *pth); 6 | EXTERN_C const char *wbDirectory_create(const char *dir); 7 | EXTERN_C char *wbDirectory_current(); 8 | 9 | #endif /* __WB_DIRECTORY__ */ 10 | -------------------------------------------------------------------------------- /wbThrust.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_THRUST_H__ 3 | #define __WB_THRUST_H__ 4 | 5 | #ifdef WB_USE_CUDA 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #endif /* WB_USE_CUDA */ 14 | 15 | #endif /* __WB_THRUST_H__ */ 16 | -------------------------------------------------------------------------------- /wbSparse.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_SPARSE_H__ 3 | #define __WB_SPARSE_H__ 4 | 5 | EXTERN_C void CSRToJDS(int dim, int *csrRowPtr, int *csrColIdx, 6 | float *csrData, int **jdsRowPerm, int **jdsRowNNZ, 7 | int **jdsColStartIdx, int **jdsColIdx, 8 | float **jdsData); 9 | 10 | #endif /* __WB_SPARSE_H__ */ 11 | -------------------------------------------------------------------------------- /wbUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef __WB_UTILS_H__ 2 | #define __WB_UTILS_H__ 3 | 4 | #include "wbString.h" 5 | #include "vendor/sole.hpp" 6 | 7 | #ifdef WB_DEBUG 8 | #define DEBUG(...) __VA_ARGS__ 9 | #else /* WB_DEBUG */ 10 | #define DEBUG(...) 11 | #endif /* WB_DEBUG */ 12 | 13 | static char* uuid() { 14 | auto u4 = sole::uuid4(); 15 | return wbString_duplicate(u4.str()); 16 | } 17 | 18 | #endif /* __WB_UTILS_H__ */ 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # libWB 3 | 4 | [![Travis Build Status](https://travis-ci.org/abduld/libwb.svg?branch=master)](https://travis-ci.org/abduld/libwb) 5 | [![AppVeyor status](https://ci.appveyor.com/api/projects/status/0nx5ie7gn5c0e6ai/branch/master?svg=true)](https://ci.appveyor.com/project/abduld/libwb/branch/master) 6 | -------------------------------------------------------------------------------- /wbCUDA.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | #ifdef WB_USE_CUDA 4 | 5 | int _cudaMemoryListIdx = 0; 6 | 7 | size_t _cudaMallocSize = 0; 8 | 9 | wbCUDAMemory_t _cudaMemoryList[_cudaMemoryListSize]; 10 | 11 | char *wbRandom_list(size_t sz) { 12 | size_t ii; 13 | char *rands = wbNewArray(char, sz); 14 | int *irands = (int *)rands; 15 | for (ii = 0; ii < sz / sizeof(int); ii++) { 16 | irands[ii] = rand(); 17 | } 18 | while (ii < sz) { 19 | rands[ii] = (char)(rand() % 255); 20 | ii++; 21 | } 22 | return rands; 23 | } 24 | 25 | #endif /* WB_USE_CUDA */ 26 | -------------------------------------------------------------------------------- /wbCast.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_CAST_H__ 4 | #define __WB_CAST_H__ 5 | 6 | template 7 | static inline void wbCast(X &x, const Y &y, size_t len) { 8 | size_t ii; 9 | 10 | for (ii = 0; ii < len; ii++) { 11 | x[ii] = (X)y[ii]; 12 | } 13 | 14 | return; 15 | } 16 | 17 | template 18 | static inline X *wbCast(const Y &y, size_t len) { 19 | size_t ii; 20 | X *x = wbNewArray(X, len); 21 | 22 | for (ii = 0; ii < len; ii++) { 23 | x[ii] = (X)y[ii]; 24 | } 25 | 26 | return x; 27 | } 28 | 29 | #endif /* __WB_CAST_H__ */ 30 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: LLVM 4 | ColumnLimit: 75 5 | AccessModifierOffset: -2 6 | BreakBeforeBraces: Attach 7 | AlignTrailingComments: true 8 | AlignEscapedNewlinesLeft: false 9 | AlignConsecutiveAssignments: true 10 | AlignOperands: true 11 | AllowShortFunctionsOnASingleLine: false 12 | AllowShortIfStatementsOnASingleLine: false 13 | AllowShortLoopsOnASingleLine: false 14 | AlwaysBreakTemplateDeclarations: true 15 | IndentCaseLabels: true 16 | SpacesBeforeTrailingComments: 1 17 | Standard: Cpp11 18 | TabWidth: 4 19 | UseTab: Never 20 | SortIncludes: false 21 | ... 22 | -------------------------------------------------------------------------------- /wbDataset_test.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | #include "vendor/catch.hpp" 4 | 5 | TEST_CASE("Can create Raw dataset", "[DataGenerator]") { 6 | wbGenerateParams_t params; 7 | params.raw.rows = 2; 8 | params.raw.cols = 300; 9 | params.raw.minVal = 0; 10 | params.raw.maxVal = 30; 11 | params.raw.type = wbType_integer; 12 | wbDataset_generate( 13 | wbPath_join(wbDirectory_current(), "test-dataset", "test.raw"), 14 | wbExportKind_raw, params); 15 | } 16 | 17 | TEST_CASE("Can create Text dataset", "[DataGenerator]") { 18 | wbGenerateParams_t params; 19 | params.text.length = 2000; 20 | wbDataset_generate( 21 | wbPath_join(wbDirectory_current(), "test-dataset", "test.txt"), 22 | wbExportKind_text, params); 23 | } 24 | -------------------------------------------------------------------------------- /sources.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(WBLIB "wb") 3 | 4 | include_directories(${CMAKE_CURRENT_LIST_DIR}) 5 | 6 | if (UNIX) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-dollar-in-identifier-extension") 8 | endif () 9 | 10 | file(GLOB THESE_CPP_FILES 11 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp 12 | ) 13 | 14 | file(GLOB THESE_TEST_FILES 15 | ${CMAKE_CURRENT_LIST_DIR}/*_test.cpp 16 | ) 17 | 18 | list(REMOVE_ITEM THESE_CPP_FILES ${THESE_TEST_FILES}) 19 | 20 | file(GLOB THESE_HEADER_FILES 21 | ${CMAKE_CURRENT_LIST_DIR}/*.h 22 | ) 23 | 24 | list(APPEND LIBWB_HEADER_FILES 25 | ${THESE_HEADER_FILES} 26 | ) 27 | 28 | list(APPEND LIBWB_SOURCE_FILES 29 | ${THESE_CPP_FILES} 30 | ${CMAKE_CURRENT_LIST_DIR}/vendor/json11.cpp 31 | ) 32 | 33 | list(APPEND LIBWB_TEST_FILES 34 | ${THESE_TEST_FILES} 35 | ) 36 | -------------------------------------------------------------------------------- /wbAssert.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_ASSERT_H__ 4 | #define __WB_ASSERT_H__ 5 | 6 | #include 7 | 8 | #ifdef WB_DEBUG 9 | #define wbAssert(cond) assert(cond) 10 | #define wbAssertMessage(msg, cond) \ 11 | do { \ 12 | if (!(cond)) { \ 13 | wbPrint(msg); \ 14 | wbAssert(cond); \ 15 | } \ 16 | } while (0) 17 | #else /* WB_DEBUG */ 18 | #define wbAssert(...) 19 | #define wbAssertMessage(...) 20 | #endif /* WB_DEBUG */ 21 | 22 | #define wbTodo(msg) wbAssertMessage(msg, false) 23 | 24 | #endif /* __WB_ASSERT_H__ */ 25 | -------------------------------------------------------------------------------- /wbMPI.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_MPI_H__ 3 | #define __WB_MPI_H__ 4 | 5 | #ifdef WB_USE_MPI 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define isMasterQ ((wbMPI_getRank()) == 0) 12 | 13 | extern int wbMPI_getRank(); 14 | 15 | extern int rankCount(); 16 | 17 | extern const char *wbMPI_getStringFromRank(int rank, int tag); 18 | extern void wbMPI_sendStringToMaster(const char *str, int tag); 19 | 20 | extern int wbMPI_Init(int *argc, char ***argv); 21 | 22 | extern bool finalizedQ; 23 | 24 | extern "C" int wbMPI_Finalize(void); 25 | extern "C" void wbMPI_Exit(void); 26 | 27 | #define MPI_Finalize wbMPI_Finalize 28 | 29 | #else /* WB_USE_MPI */ 30 | static inline int rankCount() { 31 | return 1; 32 | } 33 | static inline int wbMPI_getRank() { 34 | return 0; 35 | } 36 | #endif /* WB_USE_MPI */ 37 | #endif /* __WB_MPI_H__ */ 38 | -------------------------------------------------------------------------------- /wbDataset.h: -------------------------------------------------------------------------------- 1 | #ifndef __WB_DATASET_H__ 2 | #define __WB_DATASET_H__ 3 | 4 | #include "wbImport.h" 5 | #include "wbTypes.h" 6 | 7 | typedef struct { 8 | int rows; 9 | int cols; 10 | wbType_t type; 11 | double minVal; 12 | double maxVal; 13 | } wbCSV_GenerateParams_t; 14 | 15 | typedef struct { 16 | int rows; 17 | int cols; 18 | wbType_t type; 19 | double minVal; 20 | double maxVal; 21 | } wbTSV_GenerateParams_t; 22 | 23 | typedef struct { 24 | int rows; 25 | int cols; 26 | double minVal; 27 | double maxVal; 28 | wbType_t type; 29 | } wbRaw_GenerateParams_t; 30 | 31 | typedef struct { 32 | int width; 33 | int height; 34 | int channels; 35 | double minVal; 36 | double maxVal; 37 | } wbPPM_GenerateParams_t; 38 | 39 | typedef struct { int length; } wbText_GenerateParams_t; 40 | 41 | typedef union { 42 | wbCSV_GenerateParams_t csv; 43 | wbRaw_GenerateParams_t raw; 44 | wbTSV_GenerateParams_t tsv; 45 | wbPPM_GenerateParams_t ppm; 46 | wbText_GenerateParams_t text; 47 | } wbGenerateParams_t; 48 | 49 | EXTERN_C void wbDataset_generate(const char *path, wbExportKind_t kind, 50 | wbGenerateParams_t params); 51 | 52 | #endif /* __WB_DATASET_H__ */ 53 | -------------------------------------------------------------------------------- /wbPath.h: -------------------------------------------------------------------------------- 1 | #ifndef __WB_PATH_H__ 2 | #define __WB_PATH_H__ 3 | 4 | char *wbPath_join(const char *p1, const char *p2); 5 | char *wbPath_join(const char *p1, const char *p2, const char *p3); 6 | char *wbPath_join(const char *p1, const char *p2, const char *p3, 7 | const char *p4); 8 | 9 | char *wbPath_join(const std::string &p1, const std::string &p2); 10 | char *wbPath_join(const std::string &p1, const std::string &p2, 11 | const std::string &p3); 12 | char *wbPath_join(const std::string &p1, const std::string &p2, 13 | const std::string &p3, const std::string &p4); 14 | 15 | template 16 | static char *wbPath_join(const T1 &p1, const T2 &p2) { 17 | return wbPath_join(wbString(p1), wbString(p2)); 18 | } 19 | template 20 | static char *wbPath_join(const T1 &p1, const T2 &p2, const T3 &p3) { 21 | return wbPath_join(wbString(p1), wbString(p2), wbString(p3)); 22 | } 23 | template 24 | static char *wbPath_join(const T1 &p1, const T2 &p2, const T3 &p3, 25 | const T4 &p4) { 26 | return wbPath_join(wbString(p1), wbString(p2), wbString(p3), 27 | wbString(p4)); 28 | } 29 | 30 | #endif /* __WB_PATH_H__ */ 31 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | 4 | # scripts that are called at very beginning, before repo cloning 5 | init: 6 | - echo init step 7 | - git config --global core.autocrlf input 8 | - cmd: cmake --version 9 | - cmd: msbuild /version 10 | 11 | # clone directory 12 | clone_folder: c:\projects\libwb 13 | # fetch repository as zip archive 14 | shallow_clone: true # default is "false" 15 | 16 | # branches to build 17 | branches: 18 | # whitelist 19 | only: 20 | - master 21 | 22 | platform: 23 | - x64 24 | configuration: 25 | - Release 26 | 27 | environment: 28 | P: "c:/projects/libs" 29 | matrix: 30 | - CMAKE_GENERATOR: "Visual Studio 12 2013 Win64" 31 | - CMAKE_GENERATOR: "Visual Studio 14 2015 Win64" 32 | 33 | 34 | install: 35 | # by default, all script lines are interpreted as batch 36 | 37 | build: 38 | project: ALL_BUILD.vcxproj # path to Visual Studio solution or project 39 | 40 | # scripts to run before build 41 | before_build: 42 | - echo Running cmake... 43 | - cd c:\projects\libwb 44 | - cmake -G "%CMAKE_GENERATOR%" -DCMAKE_INSTALL_PREFIX=%P% 45 | 46 | # after_build: 47 | # - echo after_build step 48 | 49 | 50 | # on_finish always executes regardless of passed or failed builds 51 | # on_finish: 52 | # - echo on_finish step 53 | # - ps: ls 54 | -------------------------------------------------------------------------------- /wbImage.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __IMAGE_H__ 4 | #define __IMAGE_H__ 5 | 6 | #include "wbTypes.h" 7 | 8 | struct st_wbImage_t { 9 | int width; 10 | int height; 11 | int channels; 12 | int pitch; 13 | float *data; 14 | }; 15 | 16 | #define wbImage_channels 3 17 | 18 | #define wbImage_getWidth(img) ((img)->width) 19 | #define wbImage_getHeight(img) ((img)->height) 20 | #define wbImage_getChannels(img) ((img)->channels) 21 | #define wbImage_getPitch(img) ((img)->pitch) 22 | #define wbImage_getData(img) ((img)->data) 23 | 24 | #define wbImage_setWidth(img, val) (wbImage_getWidth(img) = val) 25 | #define wbImage_setHeight(img, val) (wbImage_getHeight(img) = val) 26 | #define wbImage_setChannels(img, val) (wbImage_getChannels(img) = val) 27 | #define wbImage_setPitch(img, val) (wbImage_getPitch(img) = val) 28 | #define wbImage_setData(img, val) (wbImage_getData(img) = val) 29 | 30 | typedef void (*wbImage_onSameFunction_t)(string str); 31 | 32 | wbImage_t wbImage_new(int width, int height, int channels, float *data); 33 | wbImage_t wbImage_new(int width, int height, int channels); 34 | wbImage_t wbImage_new(int width, int height); 35 | void wbImage_delete(wbImage_t img); 36 | wbBool wbImage_sameQ(wbImage_t a, wbImage_t b, 37 | wbImage_onSameFunction_t onUnSame); 38 | wbBool wbImage_sameQ(wbImage_t a, wbImage_t b); 39 | 40 | #endif /* __IMAGE_H__ */ 41 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 2 | 3 | set(CMAKE_BUILD_TYPE Release) 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 5 | set(CMAKE_COLOR_MAKEFILE ON) 6 | set(VERBOSE_BUILD ON) 7 | set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 8 | set(CMAKE_MACOSX_RPATH TRUE) 9 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 10 | 11 | 12 | project(wb) 13 | 14 | set(current_dir "${CMAKE_CURRENT_SOURCE_DIR}") 15 | 16 | 17 | include(${current_dir}/sources.cmake) 18 | include(CheckCXXCompilerFlag) 19 | 20 | set(CMAKE_CXX_STANDARD 11) 21 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 22 | 23 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 24 | if(COMPILER_SUPPORTS_CXX11) 25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 26 | else() 27 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 28 | endif() 29 | 30 | set(WBLIB_STATIC ${WBLIB}) 31 | set(WBLIB_SHARED lib${WBLIB}) 32 | 33 | add_library(${WBLIB_STATIC} STATIC ${LIBWB_SOURCE_FILES} ) 34 | add_library(${WBLIB_SHARED} SHARED ${LIBWB_SOURCE_FILES} ) 35 | set_property(TARGET ${WBLIB_STATIC} PROPERTY CXX_STANDARD 11) 36 | set_property(TARGET ${WBLIB_SHARED} PROPERTY CXX_STANDARD 11) 37 | if (UNIX) 38 | set_target_properties(${WBLIB_SHARED} PROPERTIES OUTPUT_NAME ${WBLIB_STATIC}) 39 | endif (UNIX) 40 | set_property(TARGET ${WBLIB} PROPERTY CXX_STANDARD 11) 41 | -------------------------------------------------------------------------------- /wbPath.cpp: -------------------------------------------------------------------------------- 1 | #include "wb.h" 2 | 3 | char *wbPath_join(const char *p1, const char *p2) { 4 | size_t s1 = strlen(p1); 5 | size_t s2 = strlen(p2); 6 | char *res = 7 | wbNewArray(char, s1 + 1 /* seperator */ + s2 + 1 /* terminator */); 8 | memcpy(res, p1, s1); 9 | char *iter = res + s1; 10 | *iter++ = wbDirectorySeperator; 11 | memcpy(iter, p2, s2); 12 | iter += s2; 13 | *iter = '\0'; 14 | return res; 15 | } 16 | 17 | char *wbPath_join(const char *p1, const char *p2, const char *p3) { 18 | char *p12 = wbPath_join(p1, p2); 19 | char *res = wbPath_join(p12, p3); 20 | wbDelete(p12); 21 | return res; 22 | } 23 | 24 | char *wbPath_join(const char *p1, const char *p2, const char *p3, 25 | const char *p4) { 26 | char *p123 = wbPath_join(p1, p2, p3); 27 | char *res = wbPath_join(p123, p4); 28 | wbDelete(p123); 29 | return res; 30 | } 31 | 32 | char *wbPath_join(const std::string &p1, const std::string &p2) { 33 | return wbPath_join(p1.c_str(), p2.c_str()); 34 | } 35 | char *wbPath_join(const std::string &p1, const std::string &p2, 36 | const std::string &p3) { 37 | return wbPath_join(p1.c_str(), p2.c_str(), p3.c_str()); 38 | } 39 | char *wbPath_join(const std::string &p1, const std::string &p2, 40 | const std::string &p3, const std::string &p4) { 41 | return wbPath_join(p1.c_str(), p2.c_str(), p3.c_str(), p4.c_str()); 42 | } -------------------------------------------------------------------------------- /wbTypes.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_TYPES_H__ 4 | #define __WB_TYPES_H__ 5 | 6 | #include "wbAssert.h" 7 | 8 | typedef bool wbBool; 9 | typedef float wbReal_t; 10 | typedef char wbChar_t; 11 | 12 | typedef struct st_wbTimerNode_t *wbTimerNode_t; 13 | typedef struct st_wbTimer_t *wbTimer_t; 14 | typedef struct st_wbLogEntry_t *wbLogEntry_t; 15 | typedef struct st_wbLogger_t *wbLogger_t; 16 | typedef struct st_wbArg_t wbArg_t; 17 | typedef struct st_wbImage_t *wbImage_t; 18 | typedef struct st_wbFile_t *wbFile_t; 19 | 20 | #define wbTrue true 21 | #define wbFalse false 22 | 23 | typedef enum en_wbType_t { 24 | wbType_unknown = -1, 25 | wbType_ascii = 1, 26 | wbType_bit8, 27 | wbType_ubit8, 28 | wbType_integer, 29 | wbType_float, 30 | wbType_double 31 | } wbType_t; 32 | 33 | static inline size_t wbType_size(wbType_t ty) { 34 | switch (ty) { 35 | case wbType_unknown: 36 | wbAssert(false && "Invalid wbType_unknown"); 37 | return 0; 38 | case wbType_ascii: 39 | return sizeof(char); 40 | case wbType_bit8: 41 | return sizeof(char); 42 | case wbType_ubit8: 43 | return sizeof(unsigned char); 44 | case wbType_integer: 45 | return sizeof(int); 46 | case wbType_float: 47 | return sizeof(float); 48 | case wbType_double: 49 | return sizeof(double); 50 | } 51 | wbAssert(false && "Invalid type"); 52 | return 0; 53 | } 54 | 55 | #endif /* __WB_TYPES_H__ */ 56 | -------------------------------------------------------------------------------- /wbArg.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_ARG_H__ 4 | #define __WB_ARG_H__ 5 | 6 | struct st_wbArg_t { 7 | char * sessionId; 8 | int inputCount; 9 | char **inputFiles; 10 | char *outputFile; 11 | char *expectedOutput; 12 | char *type; 13 | }; 14 | 15 | #define wbArg_getInputCount(wa) ((wa).inputCount) 16 | #define wbArg_getInputFiles(wa) ((wa).inputFiles) 17 | #define wbArg_getInputFile(wa, ii) (wbArg_getInputFiles(wa)[ii]) 18 | #define wbArg_getOutputFile(wa) ((wa).outputFile) 19 | #define wbArg_getSessionId(wa) ((wa).sessionId) 20 | #define wbArg_getExpectedOutputFile(wa) ((wa).expectedOutput) 21 | #define wbArg_getType(wa) ((wa).type) 22 | 23 | #define wbArg_setSessionId(wa, val) (wbArg_getSessionId(wa) = val) 24 | #define wbArg_setInputCount(wa, val) (wbArg_getInputCount(wa) = val) 25 | #define wbArg_setInputFiles(wa, val) (wbArg_getInputFiles(wa) = val) 26 | #define wbArg_setInputFile(wa, ii, val) (wbArg_getInputFile(wa, ii) = val) 27 | #define wbArg_setOutputFile(wa, val) (wbArg_getOutputFile(wa) = val) 28 | #define wbArg_setExpectedOutputFile(wa, val) \ 29 | (wbArg_getExpectedOutputFile(wa) = val) 30 | #define wbArg_setType(wa, val) (wbArg_getType(wa) = val) 31 | 32 | EXTERN_C wbArg_t wbArg_new(int *argc, char ***argv); 33 | EXTERN_C void wbArg_delete(wbArg_t arg); 34 | EXTERN_C wbArg_t wbArg_read(int argc, char **argv); 35 | 36 | char* sessionId(); 37 | char * _envSessionId(); 38 | 39 | #endif /* __WB_ARG_H__ */ 40 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ########################################## 2 | # Options 3 | ########################################## 4 | WB_LIB_PATH=$(CURDIR)/lib 5 | WB_SRC_PATH=$(CURDIR) 6 | CXX=g++ 7 | 8 | ########################################## 9 | ########################################## 10 | 11 | DEFINES=-DWB_USE_COURSERA -DWB_USE_JSON11=0 12 | CXX_FLAGS=-fpic -O3 -g -std=c++11 -I . -I $(WB_SRC_PATH) # -I /usr/local/cuda/include -L /usr/local/cuda/lib64 13 | LIBS=-lm -std=c++11 -L $(WB_LIB_PATH) # -lcuda 14 | 15 | ########################################## 16 | ########################################## 17 | 18 | UNAME_S := $(shell uname -s) 19 | ifeq ($(UNAME_S),Linux) 20 | LIBS += -lrt 21 | endif 22 | 23 | ########################################## 24 | ########################################## 25 | 26 | SOURCES := $(shell find $(WB_SRC_PATH) ! -name "*_test.cpp" -name "*.cpp") 27 | TESTS := $(shell find $(WB_SRC_PATH) -name "*_test.cpp") 28 | 29 | OBJECTS = $(SOURCES:.cpp=.o) 30 | 31 | ############################################## 32 | # OUTPUT 33 | ############################################## 34 | 35 | .PHONY: all 36 | .SUFFIXES: .o .cpp 37 | all: libwb.so 38 | 39 | .cpp.o: 40 | $(CXX) $(DEFINES) $(CXX_FLAGS) -c -o $@ $< 41 | 42 | libwb.so: $(OBJECTS) 43 | mkdir -p $(WB_LIB_PATH) 44 | $(CXX) -shared -o $(WB_LIB_PATH)/$@ $(OBJECTS) $(LIBS) 45 | 46 | libwb.a: $(OBJECTS) 47 | mkdir -p $(WB_LIB_PATH) 48 | ar rcs -o $(WB_LIB_PATH)/$@ $(OBJECTS) 49 | 50 | test: libwb.so 51 | $(CXX) $(DEFINES) $(CXX_FLAGS) -o $@ $(TESTS) -lwb $(LIBS) 52 | 53 | 54 | clean: 55 | rm -fr lib test 56 | -rm -f $(EXES) *.o *~ 57 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Use new trusty images, should yield newer compilers and packages 2 | sudo: required 3 | dist: precise 4 | language: cpp 5 | 6 | matrix: 7 | include: 8 | - compiler: gcc 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - g++-4.9 15 | env: COMPILER=g++-4.9 16 | - compiler: gcc 17 | addons: 18 | apt: 19 | sources: 20 | - ubuntu-toolchain-r-test 21 | packages: 22 | - g++-5 23 | env: COMPILER=g++-5 24 | - compiler: clang 25 | addons: 26 | apt: 27 | sources: 28 | - ubuntu-toolchain-r-test 29 | - llvm-toolchain-precise-3.6 30 | packages: 31 | - clang-3.6 32 | env: COMPILER=clang++-3.6 33 | - compiler: clang 34 | addons: 35 | apt: 36 | sources: 37 | - ubuntu-toolchain-r-test 38 | - llvm-toolchain-precise-3.7 39 | packages: 40 | - clang-3.7 41 | env: COMPILER=clang++-3.7 42 | # - compiler: gcc 43 | # addons: 44 | # apt: 45 | # sources: 46 | # - ubuntu-toolchain-r-test 47 | # packages: 48 | # - g++-6 49 | # env: COMPILER=g++-6 50 | # - compiler: clang 51 | # addons: 52 | # apt: 53 | # sources: 54 | # - ubuntu-toolchain-r-test 55 | # - llvm-toolchain-precise-3.8 56 | # packages: 57 | # - clang-3.8 58 | # env: COMPILER=clang++-3.8 59 | 60 | before_install: 61 | - sudo apt-get update -qq 62 | script: 63 | - $COMPILER --version 64 | - make CXX=$COMPILER test 65 | # - cp lib/libwb.so . 66 | # - ./test -s -d yes 67 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Abdul Dakkak All rights reserved. 2 | 3 | Developed by: Abdul Dakkak 4 | IMPACT Group 5 | University of Illinois, Urbana-Champaign 6 | impact.crhc.illinois.edu 7 | 8 | Permission is hereby granted, free of charge, to any 9 | person obtaining a copy of this software and associated 10 | documentation files (the "Software"), to deal with the 11 | Software without restriction, including without limitation 12 | the rights to use, copy, modify, merge, publish, distribute, 13 | sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, 15 | subject to the following conditions: 16 | 17 | Redistributions of source code must retain the above 18 | copyright notice, this list of conditions and the following 19 | disclaimers. 20 | Redistributions in binary form must reproduce the above 21 | copyright notice, this list of conditions and the following 22 | disclaimers in the documentation and/or other materials 23 | provided with the distribution. 24 | Neither the names of Abdul Dakkak, Impact Group, nor the 25 | names of its contributors may be used to endorse or promote 26 | products derived from this Software without specific prior 27 | written permission. 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 29 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 30 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 31 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 32 | THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 33 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 34 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 35 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 36 | WITH THE SOFTWARE. 37 | -------------------------------------------------------------------------------- /wbMPI.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifdef WB_USE_MPI 3 | 4 | #include 5 | #include 6 | #include 7 | #include "wb.h" 8 | 9 | static int rank = -1; 10 | 11 | int wbMPI_getRank() { 12 | if (rank != -1) { 13 | return rank; 14 | } 15 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 16 | return rank; 17 | } 18 | 19 | int rankCount() { 20 | int nRanks; 21 | MPI_Comm_size(MPI_COMM_WORLD, &nRanks); 22 | return nRanks; 23 | } 24 | 25 | const char *wbMPI_getStringFromRank(int rank, int tag) { 26 | if (isMasterQ) { 27 | char *buf; 28 | int bufSize; 29 | MPI_Recv(&bufSize, 1, MPI_INT, rank, tag, MPI_COMM_WORLD, 30 | MPI_STATUS_IGNORE); 31 | buf = (char *)calloc(bufSize, sizeof(char)); 32 | MPI_Recv(buf, bufSize, MPI_CHAR, rank, tag, MPI_COMM_WORLD, 33 | MPI_STATUS_IGNORE); 34 | return buf; 35 | } 36 | 37 | return NULL; 38 | } 39 | void wbMPI_sendStringToMaster(const char *str, int tag) { 40 | if (!isMasterQ) { 41 | // we are going to send the string to the master 42 | int len = (int)strlen(str) + 1; 43 | MPI_Send(&len, 1, MPI_INT, 0, tag, MPI_COMM_WORLD); 44 | MPI_Send((void *)str, len, MPI_CHAR, 0, tag, MPI_COMM_WORLD); 45 | } 46 | 47 | return; 48 | } 49 | 50 | int wbMPI_Init(int *argc, char ***argv) { 51 | int err = MPI_SUCCESS; 52 | err = MPI_Init(argc, argv); 53 | // printf("argc = %d\n", *argc); 54 | // err = MPI_Init(NULL, NULL); 55 | // printf("rank = %d is master = %d\n", wbMPI_getRank(), isMasterQ); 56 | // MPI_Barrier(MPI_COMM_WORLD); 57 | return err; 58 | } 59 | 60 | bool finalizedQ = false; 61 | 62 | extern "C" int wbMPI_Finalize(void) { 63 | if (finalizedQ) { 64 | return MPI_SUCCESS; 65 | } 66 | finalizedQ = true; 67 | wb_atExit(); 68 | return MPI_Finalize(); 69 | } 70 | extern "C" void wbMPI_Exit(void) { 71 | wbMPI_Finalize(); 72 | return; 73 | } 74 | 75 | #endif /* WB_USE_MPI */ 76 | -------------------------------------------------------------------------------- /wbSolution.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_SOLUTION_H__ 4 | #define __WB_SOLUTION_H__ 5 | 6 | typedef struct st_wbSolution_t { 7 | char * id; 8 | char * session_id; 9 | char *type; 10 | char *outputFile; 11 | void *data; 12 | int rows; 13 | int columns; 14 | int depth; 15 | } wbSolution_t; 16 | 17 | #define wbSolution_getId(sol) ((sol).id) 18 | #define wbSolution_getSessionId(sol) ((sol).session_id) 19 | #define wbSolution_getType(sol) ((sol).type) 20 | #define wbSolution_getOutputFile(sol) ((sol).outputFile) 21 | #define wbSolution_getData(sol) ((sol).data) 22 | #define wbSolution_getRows(sol) ((sol).rows) 23 | #define wbSolution_getColumns(sol) ((sol).columns) 24 | #define wbSolution_getDepth(sol) ((sol).depth) 25 | 26 | #define wbSolution_getHeight wbSolution_getRows 27 | #define wbSolution_getWidth wbSolution_getColumns 28 | #define wbSolution_getChannels wbSolution_getDepth 29 | 30 | #define wbSolution_setId(sol, val) (wbSolution_getId(sol) = val) 31 | #define wbSolution_setSessionId(sol, val) \ 32 | (wbSolution_getSessionId(sol) = val) 33 | #define wbSolution_setType(sol, val) (wbSolution_getType(sol) = val) 34 | #define wbSolution_setOutputFile(sol, val) \ 35 | (wbSolution_getOutputFile(sol) = val) 36 | #define wbSolution_setData(sol, val) (wbSolution_getData(sol) = val) 37 | #define wbSolution_setRows(sol, val) (wbSolution_getRows(sol) = val) 38 | #define wbSolution_setColumns(sol, val) (wbSolution_getColumns(sol) = val) 39 | #define wbSolution_setDepth(sol, val) (wbSolution_getDepth(sol) = val) 40 | 41 | wbBool wbSolution(char *expectedOutputFile, char *outputFile, char *type0, 42 | void *data, int rows, int columns); 43 | wbBool wbSolution(wbArg_t arg, void *data, int rows, int columns); 44 | EXTERN_C wbBool wbSolution(wbArg_t arg, void *data, int rows); 45 | wbBool wbSolution(wbArg_t arg, wbImage_t img); 46 | 47 | #endif /* __WB_SOLUTION_H__ */ 48 | -------------------------------------------------------------------------------- /wbSort.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_SORT_H__ 3 | #define __WB_SORT_H__ 4 | 5 | 6 | template 7 | static void wbSort(T *data, int start, int end) { 8 | if ((end - start + 1) > 1) { 9 | int left = start, right = end; 10 | int pivot = data[right]; 11 | while (left <= right) { 12 | while (data[left] > pivot) { 13 | left = left + 1; 14 | } 15 | while (data[right] < pivot) { 16 | right = right - 1; 17 | } 18 | if (left <= right) { 19 | int tmp = data[left]; 20 | data[left] = data[right]; 21 | data[right] = tmp; 22 | left = left + 1; 23 | right = right - 1; 24 | } 25 | } 26 | wbSort(data, start, right); 27 | wbSort(data, left, end); 28 | } 29 | } 30 | 31 | template 32 | static void wbSort(T *data, int len) { 33 | return wbSort(data, 0, len); 34 | } 35 | 36 | template 37 | static void wbSortByKey(T *data, K *key, int start, int end) { 38 | if ((end - start + 1) > 1) { 39 | int left = start, right = end; 40 | int pivot = key[right]; 41 | while (left <= right) { 42 | while (key[left] > pivot) { 43 | left = left + 1; 44 | } 45 | while (key[right] < pivot) { 46 | right = right - 1; 47 | } 48 | if (left <= right) { 49 | int tmp = key[left]; 50 | key[left] = key[right]; 51 | key[right] = tmp; 52 | tmp = data[left]; 53 | data[left] = data[right]; 54 | data[right] = tmp; 55 | left = left + 1; 56 | right = right - 1; 57 | } 58 | } 59 | wbSortByKey(data, key, start, right); 60 | wbSortByKey(data, key, left, end); 61 | } 62 | } 63 | 64 | template 65 | static void wbSortByKey(T *data, K *key, int len) { 66 | return wbSortByKey(data, key, len); 67 | } 68 | 69 | 70 | #endif // __WB_SORT_H__ 71 | -------------------------------------------------------------------------------- /wbInit.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | #define MB (1 << 20) 5 | #ifndef WB_DEFAULT_HEAP_SIZE 6 | #define WB_DEFAULT_HEAP_SIZE (1024 * MB) 7 | #endif /* WB_DEFAULT_HEAP_SIZE */ 8 | 9 | static bool _initializedQ = wbFalse; 10 | 11 | #ifndef WB_USE_WINDOWS 12 | //__attribute__((__constructor__)) 13 | #endif /* WB_USE_WINDOWS */ 14 | void wb_init(int * 15 | #ifdef WB_USE_MPI 16 | argc 17 | #endif /* WB_USE_MPI */ 18 | , 19 | char *** 20 | #ifdef WB_USE_MPI 21 | argv 22 | #endif /* WB_USE_MPI */ 23 | ) { 24 | if (_initializedQ == wbTrue) { 25 | return; 26 | } 27 | #ifdef WB_USE_MPI 28 | wbMPI_Init(argc, argv); 29 | #endif /* WB_USE_MPI */ 30 | 31 | _envSessionId(); 32 | #ifdef WB_USE_CUDA 33 | CUresult err = cuInit(0); 34 | 35 | /* Select a random GPU */ 36 | 37 | #ifdef WB_USE_MPI 38 | if (rankCount() > 1) { 39 | int deviceCount; 40 | cudaGetDeviceCount(&deviceCount); 41 | srand(time(NULL)); 42 | cudaSetDevice(wbMPI_getRank() % deviceCount); 43 | } else { 44 | int deviceCount; 45 | cudaGetDeviceCount(&deviceCount); 46 | 47 | srand(time(NULL)); 48 | cudaSetDevice(rand() % deviceCount); 49 | } 50 | #else 51 | { 52 | int deviceCount; 53 | cudaGetDeviceCount(&deviceCount); 54 | 55 | srand(time(NULL)); 56 | cudaSetDevice(rand() % deviceCount); 57 | } 58 | #endif /* WB_USE_MPI */ 59 | 60 | cudaDeviceSetLimit(cudaLimitPrintfFifoSize, 1 * MB); 61 | cudaDeviceSetLimit(cudaLimitMallocHeapSize, WB_DEFAULT_HEAP_SIZE); 62 | 63 | cudaDeviceSynchronize(); 64 | 65 | #endif /* WB_USE_CUDA */ 66 | 67 | #ifdef WB_USE_WINDOWS 68 | QueryPerformanceFrequency((LARGE_INTEGER *)&_hrtime_frequency); 69 | #endif /* _MSC_VER */ 70 | 71 | _hrtime(); 72 | 73 | _timer = wbTimer_new(); 74 | _logger = wbLogger_new(); 75 | _initializedQ = wbTrue; 76 | 77 | wbFile_init(); 78 | 79 | solutionJSON = nullptr; 80 | 81 | #ifdef WB_USE_MPI 82 | atexit(wbMPI_Exit); 83 | #else /* WB_USE_MPI */ 84 | atexit(wb_atExit); 85 | #endif /* WB_USE_MPI */ 86 | } 87 | -------------------------------------------------------------------------------- /wbCUDA.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_CUDA_H__ 3 | #define __WB_CUDA_H__ 4 | 5 | #ifdef WB_USE_CUDA 6 | #ifdef __PGI 7 | #define __GNUC__ 4 8 | #endif /* __PGI */ 9 | #include 10 | #include 11 | 12 | typedef struct st_wbCUDAMemory_t { 13 | void *mem; 14 | size_t sz; 15 | } wbCUDAMemory_t; 16 | 17 | #define _cudaMemoryListSize 1024 18 | 19 | extern size_t _cudaMallocSize; 20 | extern wbCUDAMemory_t _cudaMemoryList[]; 21 | extern int _cudaMemoryListIdx; 22 | 23 | char *wbRandom_list(size_t sz); 24 | 25 | static inline cudaError_t wbCUDAMalloc(void **devPtr, size_t sz) { 26 | int idx = _cudaMemoryListIdx; 27 | 28 | cudaError_t err = cudaMalloc(devPtr, sz); 29 | 30 | if (idx == 0) { 31 | srand(time(NULL)); 32 | memset(_cudaMemoryList, 0, 33 | sizeof(wbCUDAMemory_t) * _cudaMemoryListSize); 34 | } 35 | 36 | if (err == cudaSuccess) { 37 | #if 0 38 | char * rands = wbRandom_list(sz); 39 | // can use curand here, but do not want to invoke a kernel 40 | err = cudaMemcpy(*devPtr, rands, sz, cudaMemcpyHostToDevice); 41 | wbFree(rands); 42 | #else 43 | err = cudaMemset(*devPtr, 0, sz); 44 | #endif 45 | } 46 | 47 | _cudaMallocSize += sz; 48 | _cudaMemoryList[idx].mem = *devPtr; 49 | _cudaMemoryList[idx].sz = sz; 50 | _cudaMemoryListIdx++; 51 | return err; 52 | } 53 | 54 | static inline cudaError_t wbCUDAFree(void *mem) { 55 | int idx = _cudaMemoryListIdx; 56 | if (idx == 0) { 57 | memset(_cudaMemoryList, 0, 58 | sizeof(wbCUDAMemory_t) * _cudaMemoryListSize); 59 | } 60 | for (int ii = 0; ii < idx; ii++) { 61 | if (_cudaMemoryList[ii].mem != nullptr && 62 | _cudaMemoryList[ii].mem == mem) { 63 | cudaError_t err = cudaFree(mem); 64 | _cudaMallocSize -= _cudaMemoryList[ii].sz; 65 | _cudaMemoryList[ii].mem = nullptr; 66 | return err; 67 | } 68 | } 69 | return cudaErrorMemoryAllocation; 70 | } 71 | 72 | #define cudaMalloc(elem, err) wbCUDAMalloc((void **)elem, err) 73 | #define cudaFree wbCUDAFree 74 | 75 | #endif /* WB_USE_CUDA */ 76 | 77 | #endif /* __WB_CUDA_H__ */ 78 | -------------------------------------------------------------------------------- /wbSparse.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | EXTERN_C void CSRToJDS(int dim, int *csrRowPtr, int *csrColIdx, 5 | float *csrData, int **jdsRowPerm, int **jdsRowNNZ, 6 | int **jdsColStartIdx, int **jdsColIdx, 7 | float **jdsData) { 8 | // Row Permutation Vector 9 | *jdsRowPerm = (int *)malloc(sizeof(int) * dim); 10 | for (int rowIdx = 0; rowIdx < dim; ++rowIdx) { 11 | (*jdsRowPerm)[rowIdx] = rowIdx; 12 | } 13 | 14 | // Number of non-zeros per row 15 | *jdsRowNNZ = (int *)malloc(sizeof(int) * dim); 16 | for (int rowIdx = 0; rowIdx < dim; ++rowIdx) { 17 | (*jdsRowNNZ)[rowIdx] = csrRowPtr[rowIdx + 1] - csrRowPtr[rowIdx]; 18 | } 19 | 20 | // Sort rows by number of non-zeros 21 | wbSortByKey(*jdsRowPerm, *jdsRowNNZ, 0, dim - 1); 22 | 23 | // Starting point of each compressed column 24 | int maxRowNNZ = (*jdsRowNNZ)[0]; // Largest number of non-zeros per row 25 | 26 | *jdsColStartIdx = (int *)malloc(sizeof(int) * maxRowNNZ); 27 | (*jdsColStartIdx)[0] = 0; // First column starts at 0 28 | for (int col = 0; col < maxRowNNZ - 1; ++col) { 29 | // Count the number of rows with entries in this column 30 | int count = 0; 31 | for (int idx = 0; idx < dim; ++idx) { 32 | if ((*jdsRowNNZ)[idx] > col) { 33 | ++count; 34 | } 35 | } 36 | (*jdsColStartIdx)[col + 1] = (*jdsColStartIdx)[col] + count; 37 | } 38 | 39 | // Sort the column indexes and data 40 | const int NNZ = csrRowPtr[dim]; 41 | DEBUG(printf("NNZ = %d\n", NNZ)); 42 | *jdsColIdx = (int *)malloc(sizeof(int) * NNZ); 43 | DEBUG(printf("dim = %d\n", dim)); 44 | *jdsData = (float *)malloc(sizeof(float) * NNZ); 45 | for (int idx = 0; idx < dim; ++idx) { // For every row 46 | int row = (*jdsRowPerm)[idx]; 47 | int rowNNZ = (*jdsRowNNZ)[idx]; 48 | for (int nnzIdx = 0; nnzIdx < rowNNZ; ++nnzIdx) { 49 | int jdsPos = (*jdsColStartIdx)[nnzIdx] + idx; 50 | int csrPos = csrRowPtr[row] + nnzIdx; 51 | (*jdsColIdx)[jdsPos] = csrColIdx[csrPos]; 52 | (*jdsData)[jdsPos] = csrData[csrPos]; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /wbFile.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_FILE_H__ 4 | #define __WB_FILE_H__ 5 | 6 | struct st_wbFile_t { 7 | int index; 8 | char *file; 9 | char *mode; 10 | char *data; 11 | FILE *handle; 12 | size_t len; 13 | size_t offset; 14 | }; 15 | 16 | #define wbFile_getIndex(file) ((file)->index) 17 | #define wbFile_getFileName(file) ((file)->file) 18 | #define wbFile_getMode(file) ((file)->mode) 19 | #define wbFile_getData(file) ((file)->data) 20 | #define wbFile_getLength(file) ((file)->len) 21 | #define wbFile_getDataOffset(file) ((file)->offset) 22 | #define wbFile_getFileHandle(file) ((file)->handle) 23 | 24 | #define wbFile_setIndex(file, val) (wbFile_getIndex(file) = val) 25 | #define wbFile_setFileName(file, val) (wbFile_getFileName(file) = val) 26 | #define wbFile_setMode(file, val) (wbFile_getMode(file) = val) 27 | #define wbFile_setData(file, val) (wbFile_getData(file) = val) 28 | #define wbFile_setLength(file, val) (wbFile_getLength(file) = val) 29 | #define wbFile_setDataOffset(file, val) (wbFile_getDataOffset(file) = val) 30 | #define wbFile_setFileHandle(file, val) (wbFile_getFileHandle(file) = val) 31 | 32 | wbFile_t wbFile_new(void); 33 | void wbFile_delete(wbFile_t file); 34 | void wbFile_close(wbFile_t file); 35 | void wbFile_init(void); 36 | void wbFile_atExit(void); 37 | int wbFile_count(void); 38 | wbFile_t wbFile_open(const char *fileName, const char *mode); 39 | wbFile_t wbFile_open(const char *fileName); 40 | char *wbFile_read(wbFile_t file, size_t size, size_t count); 41 | char *wbFile_read(wbFile_t file, size_t len); 42 | void wbFile_rewind(wbFile_t file); 43 | size_t wbFile_size(wbFile_t file); 44 | char *wbFile_read(wbFile_t file); 45 | char *wbFile_readLine(wbFile_t file); 46 | void wbFile_write(wbFile_t file, const void *buffer, size_t size, 47 | size_t count); 48 | void wbFile_write(wbFile_t file, const void *buffer, size_t len); 49 | void wbFile_write(wbFile_t file, const char *buffer); 50 | void wbFile_writeLine(wbFile_t file, const char *buffer0); 51 | void wbFile_write(wbFile_t file, string buffer); 52 | void wbFile_writeLine(wbFile_t file, string buffer0); 53 | wbBool wbFile_existsQ(const char *path); 54 | char *wbFile_extension(const char *file); 55 | 56 | #endif /* __WB_FILE_H__ */ 57 | -------------------------------------------------------------------------------- /wbDirectory.cpp: -------------------------------------------------------------------------------- 1 | #include "wb.h" 2 | 3 | #ifndef PATH_MAX 4 | #ifdef FILENAME_MAX 5 | #define PATH_MAX FILENAME_MAX 6 | #else /* FILENAME_MAX */ 7 | #define PATH_MAX 4096 8 | #endif /* FILENAME_MAX */ 9 | #endif /* PATH_MAX */ 10 | 11 | #ifdef WB_USE_UNIX 12 | const char wbDirectorySeperator = '/'; 13 | static char *getcwd_(char *buf, int maxLen) { 14 | return getcwd(buf, maxLen); 15 | } 16 | static void mkdir_(const char *dir) { 17 | mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 18 | } 19 | #else /* WB_USE_LINUX */ 20 | const char wbDirectorySeperator = '\\'; 21 | static char *getcwd_(char *buf, int maxLen) { 22 | return _getcwd(buf, maxLen); 23 | } 24 | static void mkdir_(const char *dir) { 25 | _mkdir(dir); 26 | } 27 | #endif /* WB_USE_LINUX */ 28 | 29 | EXTERN_C const char *wbDirectory_create(const char *dir) { 30 | char tmp[PATH_MAX]; 31 | char *p = nullptr; 32 | size_t len; 33 | 34 | #ifdef WB_USE_WINDOWS 35 | _snprintf(tmp, sizeof(tmp), "%s", dir); 36 | #else /* WB_USE_WINDOWS */ 37 | snprintf(tmp, sizeof(tmp), "%s", dir); 38 | #endif /* WB_USE_WINDOWS */ 39 | len = strlen(tmp); 40 | if (tmp[len - 1] == wbDirectorySeperator) { 41 | tmp[len - 1] = 0; 42 | } 43 | for (p = tmp + 1; *p; p++) { 44 | if (*p == wbDirectorySeperator) { 45 | *p = 0; 46 | mkdir_(tmp); 47 | *p = wbDirectorySeperator; 48 | } 49 | } 50 | mkdir_(tmp); 51 | return dir; 52 | } 53 | 54 | EXTERN_C char *wbDirectory_name(const char *pth0) { 55 | char *pth = wbString_duplicate(pth0); 56 | char *p = strrchr(pth, wbDirectorySeperator); 57 | if (p) { 58 | p[0] = 0; 59 | } 60 | return pth; 61 | } 62 | 63 | EXTERN_C char *wbDirectory_current() { 64 | char *tmp = wbNewArray(char, PATH_MAX + 1); 65 | if (getcwd_(tmp, PATH_MAX)) { 66 | return tmp; 67 | } 68 | 69 | wbDelete(tmp); 70 | 71 | int error = errno; 72 | switch (error) { 73 | case EACCES: 74 | std::cerr 75 | << "Cannot get current directory :: access denied. exiting..." 76 | << std::endl; 77 | exit(-1); 78 | case ENOMEM: 79 | std::cerr << "Cannot get current directory :: insufficient storage. " 80 | "exiting..." 81 | << std::endl; 82 | exit(-1); 83 | default: 84 | std::cerr << "Cannot get current directory :: unrecognised error " 85 | << error << std::endl; 86 | exit(-1); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /wbExit.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | enum { 5 | wbMPI_timerTag = 2, 6 | wbMPI_loggerTag = 4, 7 | wbMPI_solutionExistsTag = 8, 8 | wbMPI_solutionTag = 16 9 | }; 10 | 11 | void wb_atExit(void) { 12 | using std::cout; 13 | using std::endl; 14 | 15 | #ifdef WB_USE_CUDA 16 | // cudaDeviceSynchronize(); 17 | #endif /* WB_USE_CUDA */ 18 | 19 | int nranks = rankCount(); 20 | if (nranks > 1) { 21 | #ifdef WB_USE_MPI 22 | if (isMasterQ) { 23 | #ifdef wbLogger_printOnExit 24 | cout << "==$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl; 25 | 26 | cout << "{\n"; 27 | cout << wbString_quote("timer") << ":"; 28 | cout << "[\n"; 29 | for (int ii = 0; ii < nranks; ii++) { 30 | if (ii == 0) { 31 | cout << wbTimer_toJSON(); 32 | } else { 33 | const char *msg = wbMPI_getStringFromRank(ii, wbMPI_timerTag); 34 | if (msg != nullptr && strlen(msg) != 0) { 35 | cout << ",\n"; 36 | cout << msg; 37 | // free(msg); 38 | } 39 | } 40 | } 41 | cout << "]" << endl; // close timer 42 | 43 | cout << "," << endl; // start logger 44 | cout << wbString_quote("logger") << ":"; 45 | cout << "[\n"; 46 | for (int ii = 0; ii < nranks; ii++) { 47 | if (ii == 0) { 48 | cout << wbLogger_toJSON(); 49 | } else { 50 | const char *msg = wbMPI_getStringFromRank(ii, wbMPI_loggerTag); 51 | if (msg != nullptr && strlen(msg) != 0) { 52 | cout << ",\n"; 53 | cout << msg; 54 | // free(msg); 55 | } 56 | } 57 | } 58 | cout << "]" << endl; // close logger 59 | 60 | cout << "," << endl; // start solutionExists 61 | cout << wbString_quote("cuda_memory") << ":" << _cudaMallocSize 62 | << ",\n"; 63 | 64 | if (solutionJSON) { 65 | cout << wbString_quote("solution_exists") << ": true,\n"; 66 | cout << wbString_quote("solution") << ":" << solutionJSON << "\n"; 67 | } else { 68 | cout << wbString_quote("solution_exists") << ": false\n"; 69 | } 70 | cout << "}" << endl; // close json 71 | 72 | } else { 73 | wbMPI_sendStringToMaster(wbTimer_toJSON().c_str(), wbMPI_timerTag); 74 | wbMPI_sendStringToMaster(wbLogger_toJSON().c_str(), wbMPI_loggerTag); 75 | } 76 | #endif /* wbLogger_printOnExit */ 77 | 78 | #endif /* WB_USE_MPI */ 79 | } else { 80 | #ifdef wbLogger_printOnExit 81 | cout << "==$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl; 82 | 83 | cout << "{\n" << wbString_quote("timer") << ":[" << wbTimer_toJSON() 84 | << "],\n" << wbString_quote("logger") << ":[" << wbLogger_toJSON() 85 | << "],\n"; 86 | 87 | #ifdef WB_USE_CUDA 88 | cout << wbString_quote("cuda_memory") << ":" << _cudaMallocSize 89 | << ",\n"; 90 | #endif /* WB_USE_CUDA */ 91 | 92 | if (solutionJSON) { 93 | cout << wbString_quote("solution_exists") << ": true,\n"; 94 | cout << wbString_quote("solution") << ":" << solutionJSON << "\n"; 95 | } else { 96 | cout << wbString_quote("solution_exists") << ": false\n"; 97 | } 98 | cout << "}" << endl; 99 | #endif /* wbLogger_printOnExit */ 100 | } 101 | 102 | // wbTimer_delete(_timer); 103 | // wbLogger_delete(_logger); 104 | 105 | _timer = nullptr; 106 | _logger = nullptr; 107 | 108 | // wbFile_atExit(); 109 | 110 | #ifdef WB_USE_CUDA 111 | cudaDeviceReset(); 112 | #endif 113 | 114 | exit(0); 115 | 116 | // assert(0); 117 | 118 | return; 119 | } 120 | -------------------------------------------------------------------------------- /wbLogger.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_LOGGER_H__ 3 | #define __WB_LOGGER_H__ 4 | 5 | #include 6 | 7 | typedef enum en_wbLogLevel_t { 8 | wbLogLevel_unknown = -1, 9 | wbLogLevel_OFF = 0, 10 | wbLogLevel_FATAL, 11 | wbLogLevel_ERROR, 12 | wbLogLevel_WARN, 13 | wbLogLevel_INFO, 14 | wbLogLevel_DEBUG, 15 | wbLogLevel_TRACE 16 | } wbLogLevel_t; 17 | 18 | struct st_wbLogEntry_t { 19 | char * id; 20 | char * session_id; 21 | int line; 22 | int mpiRank; 23 | char *msg; 24 | uint64_t time; 25 | const char *fun; 26 | const char *file; 27 | wbLogLevel_t level; 28 | wbLogEntry_t next; 29 | }; 30 | 31 | struct st_wbLogger_t { 32 | char * id; 33 | char * session_id; 34 | int length; 35 | wbLogEntry_t head; 36 | wbLogLevel_t level; 37 | }; 38 | 39 | #define wbLogEntry_getId(elem) ((elem)->id) 40 | #define wbLogEntry_getSessionId(elem) ((elem)->session_id) 41 | #define wbLogEntry_getMessage(elem) ((elem)->msg) 42 | #define wbLogEntry_getMPIRank(elem) ((elem)->mpiRank) 43 | #define wbLogEntry_getTime(elem) ((elem)->time) 44 | #define wbLogEntry_getLevel(elem) ((elem)->level) 45 | #define wbLogEntry_getNext(elem) ((elem)->next) 46 | #define wbLogEntry_getLine(elem) ((elem)->line) 47 | #define wbLogEntry_getFunction(elem) ((elem)->fun) 48 | #define wbLogEntry_getFile(elem) ((elem)->file) 49 | 50 | #define wbLogEntry_setId(elem, val) (wbLogEntry_getId(elem) = val) 51 | #define wbLogEntry_setSessionId(elem, val) \ 52 | (wbLogEntry_getSessionId(elem) = val) 53 | #define wbLogEntry_setMessage(elem, val) \ 54 | (wbLogEntry_getMessage(elem) = val) 55 | #define wbLogEntry_setMPIRank(elem, val) \ 56 | (wbLogEntry_getMPIRank(elem) = val) 57 | #define wbLogEntry_setTime(elem, val) (wbLogEntry_getTime(elem) = val) 58 | #define wbLogEntry_setLevel(elem, val) (wbLogEntry_getLevel(elem) = val) 59 | #define wbLogEntry_setNext(elem, val) (wbLogEntry_getNext(elem) = val) 60 | #define wbLogEntry_setLine(elem, val) (wbLogEntry_getLine(elem) = val) 61 | #define wbLogEntry_setFunction(elem, val) \ 62 | (wbLogEntry_getFunction(elem) = val) 63 | #define wbLogEntry_setFile(elem, val) (wbLogEntry_getFile(elem) = val) 64 | 65 | #define wbLogger_getId(log) ((log)->id) 66 | #define wbLogger_getSessionId(log) ((log)->session_id) 67 | #define wbLogger_getLength(log) ((log)->length) 68 | #define wbLogger_getHead(log) ((log)->head) 69 | #define wbLogger_getLevel(log) ((log)->level) 70 | 71 | #define wbLogger_setId(log, val) (wbLogger_getId(log) = val) 72 | #define wbLogger_setSessionId(log, val) (wbLogger_getSessionId(log) = val) 73 | #define wbLogger_setLength(log, val) (wbLogger_getLength(log) = val) 74 | #define wbLogger_setHead(log, val) (wbLogger_getHead(log) = val) 75 | 76 | #define wbLogger_incrementLength(log) (wbLogger_getLength(log)++) 77 | #define wbLogger_decrementLength(log) (wbLogger_getLength(log)--) 78 | 79 | #define wbLog(level, ...) \ 80 | wbLogger_append(wbLogLevel_##level, wbString(__VA_ARGS__), wbFile, \ 81 | wbFunction, wbLine) 82 | 83 | extern wbLogger_t _logger; 84 | 85 | wbLogger_t wbLogger_new(); 86 | 87 | void wbLogger_clear(wbLogger_t logger); 88 | 89 | void wbLogger_delete(wbLogger_t logger); 90 | 91 | void wbLogger_append(wbLogLevel_t level, string msg, const char *file, 92 | const char *fun, int line); 93 | 94 | string wbLogger_toXML(wbLogger_t logger); 95 | string wbLogger_toXML(); 96 | 97 | string wbLogger_toJSON(wbLogger_t logger); 98 | string wbLogger_toJSON(); 99 | 100 | #endif /* __WB_LOGGER_H__ */ 101 | -------------------------------------------------------------------------------- /wbImport.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __WB_IMPORT_H__ 3 | #define __WB_IMPORT_H__ 4 | 5 | #include "wbImage.h" 6 | 7 | typedef enum en_wbImportKind_t { 8 | wbImportKind_unknown = -1, 9 | wbImportKind_raw = 0x1000, 10 | wbImportKind_csv, 11 | wbImportKind_tsv, 12 | wbImportKind_ppm, 13 | wbImportKind_text 14 | } wbImportKind_t; 15 | 16 | #define wbType_real wbType_float 17 | 18 | typedef struct st_wbImportCSV_t { 19 | int rows; 20 | int columns; 21 | void *data; 22 | wbFile_t file; 23 | char seperator; 24 | } * wbImportCSV_t; 25 | 26 | #define wbImportCSV_getRowCount(csv) ((csv)->rows) 27 | #define wbImportCSV_getColumnCount(csv) ((csv)->columns) 28 | #define wbImportCSV_getData(csv) ((csv)->data) 29 | #define wbImportCSV_getFile(csv) ((csv)->file) 30 | #define wbImportCSV_getSeperator(csv) ((csv)->seperator) 31 | 32 | #define wbImportCSV_setRowCount(csv, val) \ 33 | (wbImportCSV_getRowCount(csv) = val) 34 | #define wbImportCSV_setColumnCount(csv, val) \ 35 | (wbImportCSV_getColumnCount(csv) = val) 36 | #define wbImportCSV_setData(csv, val) (wbImportCSV_getData(csv) = val) 37 | #define wbImportCSV_setSeperator(csv, val) \ 38 | (wbImportCSV_getSeperator(csv) = val) 39 | 40 | typedef struct st_wbImportRaw_t { 41 | int rows; 42 | int columns; 43 | void *data; 44 | wbFile_t file; 45 | } * wbImportRaw_t; 46 | 47 | #define wbImportRaw_getRowCount(raw) ((raw)->rows) 48 | #define wbImportRaw_getColumnCount(raw) ((raw)->columns) 49 | #define wbImportRaw_getData(raw) ((raw)->data) 50 | #define wbImportRaw_getFile(raw) ((raw)->file) 51 | 52 | #define wbImportRaw_setRowCount(raw, val) \ 53 | (wbImportRaw_getRowCount(raw) = val) 54 | #define wbImportRaw_setColumnCount(raw, val) \ 55 | (wbImportRaw_getColumnCount(raw) = val) 56 | #define wbImportRaw_setData(raw, val) (wbImportRaw_getData(raw) = val) 57 | 58 | typedef struct st_wbImportText_t { 59 | int length; 60 | char *data; 61 | wbFile_t file; 62 | } * wbImportText_t; 63 | 64 | #define wbImportText_getLength(txt) ((txt)->length) 65 | #define wbImportText_getData(txt) ((txt)->data) 66 | #define wbImportText_getFile(txt) ((txt)->file) 67 | 68 | #define wbImportText_setLength(txt, val) \ 69 | (wbImportText_getLength(txt) = val) 70 | #define wbImportText_setData(txt, val) (wbImportText_getData(txt) = val) 71 | 72 | typedef struct st_wbImport_t { 73 | wbImportKind_t kind; 74 | union { 75 | wbImportRaw_t raw; 76 | wbImportCSV_t csv; 77 | wbImportText_t text; 78 | wbImage_t img; 79 | } container; 80 | } wbImport_t; 81 | 82 | #define wbImport_getKind(imp) ((imp).kind) 83 | #define wbImport_getContainer(imp) ((imp).container) 84 | #define wbImport_getRaw(imp) (wbImport_getContainer(imp).raw) 85 | #define wbImport_getCSV(imp) (wbImport_getContainer(imp).csv) 86 | #define wbImport_getText(imp) (wbImport_getContainer(imp).text) 87 | #define wbImport_getImage(imp) (wbImport_getContainer(imp).img) 88 | 89 | #define wbImport_setKind(imp, val) (wbImport_getKind(imp) = val) 90 | #define wbImport_setRaw(imp, val) (wbImport_getRaw(imp) = val) 91 | #define wbImport_setCSV(imp, val) (wbImport_getCSV(imp) = val) 92 | #define wbImport_setText(imp, val) (wbImport_getText(imp) = val) 93 | #define wbImport_setImage(imp, val) (wbImport_getImage(imp) = val) 94 | 95 | EXTERN_C void *wbImport(const char *file, int *rows); 96 | void *wbImport(const char *file, int *rows, int *columns); 97 | void *wbImport(const char *file, int *rows, const char *type); 98 | void *wbImport(const char *file, int *resRows, int *resColumns, 99 | const char *type); 100 | wbImage_t wbImport(const char *file); 101 | int wbImport_flag(const char *file); 102 | 103 | #endif /* __WB_IMPORT_H__ */ 104 | -------------------------------------------------------------------------------- /wbMalloc.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_MALLOC_H__ 4 | #define __WB_MALLOC_H__ 5 | 6 | #ifdef WB_USE_CUSTOM_MALLOC 7 | #ifdef __linux__ 8 | #define THROW __THROW 9 | #else 10 | #define THROW 11 | #endif 12 | 13 | static inline void *_malloc(size_t size) THROW { 14 | if (size == 0) { 15 | return NULL; 16 | } else { 17 | int err; 18 | void *res = memmgr_alloc((ulong)size, &err); 19 | if (err) { 20 | fprintf(stderr, "<>:: Memory allocation failed\n"); 21 | exit(1); 22 | } else { 23 | size_t ii = 0; 24 | unsigned char *p = (unsigned char *)res; 25 | while (ii++ < size) { 26 | *p++ = 0; 27 | } 28 | return res; 29 | } 30 | } 31 | } 32 | 33 | static inline void _free(void *ptr) THROW { 34 | if (ptr != nullptr) { 35 | memmgr_free(ptr); 36 | } 37 | } 38 | 39 | static inline void *_calloc(size_t nmemb, size_t size) THROW { 40 | return _malloc(nmemb * size); 41 | } 42 | 43 | static inline void *_realloc(void *ptr, size_t size) THROW { 44 | if (size == 0) { 45 | free(ptr); 46 | return NULL; 47 | } else if (ptr == nullptr) { 48 | return malloc(size); 49 | } else { 50 | void *buf; 51 | unsigned char *dst; 52 | unsigned char *src; 53 | size_t alloc_size, to_copy, i = 0; 54 | 55 | // Allocate new buffer 56 | buf = malloc(size); 57 | 58 | if (buf != 0) { 59 | // Find original allocation size 60 | alloc_size = (size_t)memmgr_get_block_size(ptr); 61 | to_copy = alloc_size; 62 | if (to_copy > size) { 63 | to_copy = size; 64 | } 65 | 66 | // Copy data to new buffer 67 | dst = (unsigned char *)buf; 68 | src = (unsigned char *)ptr; 69 | while (i++ < to_copy) { 70 | *dst++ = *src++; 71 | } 72 | 73 | // Free the old buffer 74 | free(ptr); 75 | } 76 | 77 | return buf; 78 | } 79 | } 80 | 81 | #define wbNew(type) ((type *)_malloc(sizeof(type))) 82 | #define wbNewArray(type, len) ((type *)_malloc((len) * sizeof(type))) 83 | #define wbMalloc(sz) _malloc(sz) 84 | #define wbDelete(var) \ 85 | _free(var); \ 86 | var = nullptr 87 | #define wbFree(var) \ 88 | _free(var); \ 89 | var = nullptr 90 | #define wbRealloc(var, newSize) _realloc(var, newSize) 91 | #define wbReallocArray(t, m, n) ((t *)_realloc(m, n * sizeof(t))) 92 | 93 | #define free _free 94 | #define malloc _malloc 95 | #define calloc _calloc 96 | #define realloc _realloc 97 | 98 | #else /* WB_USE_CUSTOM_MALLOC */ 99 | 100 | static inline void *xMalloc(size_t sz) { 101 | void *mem = nullptr; 102 | if (sz != 0) { 103 | mem = malloc(sz); 104 | } 105 | return mem; 106 | } 107 | 108 | static inline void xFree(void *mem) { 109 | if (mem != nullptr) { 110 | free(mem); 111 | } 112 | return; 113 | } 114 | 115 | static inline void *xRealloc(void *mem, size_t sz) { 116 | if (mem == nullptr) { 117 | return NULL; 118 | } else if (sz == 0) { 119 | xFree(mem); 120 | return NULL; 121 | } else { 122 | void *res = realloc(mem, sz); 123 | wbAssert(res != nullptr); 124 | return res; 125 | } 126 | } 127 | 128 | #define wbNew(type) ((type *)wbMalloc(sizeof(type))) 129 | #define wbNewArray(type, len) ((type *)wbMalloc((len) * sizeof(type))) 130 | #define wbMalloc(sz) xMalloc(sz) 131 | #define wbDelete(var) wbFree(var) 132 | #define wbFree(var) \ 133 | xFree(var); \ 134 | var = nullptr 135 | #define wbRealloc(var, newSize) xRealloc(var, newSize) 136 | #define wbReallocArray(t, m, n) ((t *)xRealloc(m, n * sizeof(t))) 137 | 138 | #endif /* WB_USE_CUSTOM_MALLOC */ 139 | 140 | #endif /* __WB_MALLOC_H__ */ 141 | -------------------------------------------------------------------------------- /wbExport.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_EXPORT_H__ 4 | #define __WB_EXPORT_H__ 5 | 6 | #include "wb.h" 7 | #include "wbFile.h" 8 | #include "wbPPM.h" 9 | 10 | typedef enum en_wbExportKind_t { 11 | wbExportKind_unknown = -1, 12 | wbExportKind_raw = 0x1000, 13 | wbExportKind_csv, 14 | wbExportKind_tsv, 15 | wbExportKind_ppm, 16 | wbExportKind_text, 17 | } wbExportKind_t; 18 | 19 | typedef struct st_wbExportText_t { 20 | int length; 21 | wbFile_t file; 22 | } * wbExportText_t; 23 | 24 | #define wbExportText_getLength(txt) ((txt)->length) 25 | #define wbExportText_getFile(txt) ((txt)->file) 26 | 27 | #define wbExportText_setLength(txt, val) \ 28 | (wbExportText_getLength(txt) = val) 29 | 30 | typedef struct st_wbExportRaw_t { 31 | int rows; 32 | int columns; 33 | wbFile_t file; 34 | } * wbExportRaw_t; 35 | 36 | #define wbExportRaw_getColumnCount(raw) ((raw)->columns) 37 | #define wbExportRaw_getRowCount(raw) ((raw)->rows) 38 | #define wbExportRaw_getFile(raw) ((raw)->file) 39 | 40 | #define wbExportRaw_setRowCount(raw, val) \ 41 | (wbExportRaw_getRowCount(raw) = val) 42 | #define wbExportRaw_setColumnCount(raw, val) \ 43 | (wbExportRaw_getColumnCount(raw) = val) 44 | 45 | typedef struct st_wbExportCSV_t { 46 | int rows; 47 | int columns; 48 | wbFile_t file; 49 | char seperator; 50 | } * wbExportCSV_t; 51 | 52 | #define wbExportCSV_getRowCount(csv) ((csv)->rows) 53 | #define wbExportCSV_getColumnCount(csv) ((csv)->columns) 54 | #define wbExportCSV_getFile(csv) ((csv)->file) 55 | #define wbExportCSV_getSeperator(csv) ((csv)->seperator) 56 | 57 | #define wbExportCSV_setRowCount(csv, val) \ 58 | (wbExportCSV_getRowCount(csv) = val) 59 | #define wbExportCSV_setColumnCount(csv, val) \ 60 | (wbExportCSV_getColumnCount(csv) = val) 61 | #define wbExportCSV_setSeperator(csv, val) \ 62 | (wbExportCSV_getSeperator(csv) = val) 63 | 64 | typedef struct st_wbExport_t { 65 | wbExportKind_t kind; 66 | union { 67 | wbExportRaw_t raw; 68 | wbExportCSV_t csv; 69 | wbImage_t img; 70 | wbExportText_t text; 71 | } container; 72 | char *file; 73 | } wbExport_t; 74 | 75 | #define wbExport_getKind(exprt) ((exprt).kind) 76 | #define wbExport_getContainer(exprt) ((exprt).container) 77 | #define wbExport_getRaw(exprt) (wbExport_getContainer(exprt).raw) 78 | #define wbExport_getCSV(exprt) (wbExport_getContainer(exprt).csv) 79 | #define wbExport_getImage(exprt) (wbExport_getContainer(exprt).img) 80 | #define wbExport_getText(exprt) (wbExport_getContainer(exprt).text) 81 | #define wbExport_getFile(exprt) ((exprt).file) 82 | 83 | #define wbExport_setKind(exprt, val) (wbExport_getKind(exprt) = val) 84 | #define wbExport_setRaw(exprt, val) (wbExport_getRaw(exprt) = val) 85 | #define wbExport_setCSV(exprt, val) (wbExport_getCSV(exprt) = val) 86 | #define wbExport_setImage(exprt, val) (wbExport_getImage(exprt) = val) 87 | #define wbExport_setText(exprt, val) (wbExport_getText(exprt) = val) 88 | #define wbExport_setFile(exprt, val) (wbExport_getFile(exprt) = val) 89 | 90 | void wbExport(const char *file, int *data, int rows, int columns); 91 | void wbExport(const char *file, int *data, int rows); 92 | void wbExport(const char *file, unsigned char *data, int rows, 93 | int columns); 94 | void wbExport(const char *file, unsigned char *data, int rows); 95 | void wbExport(const char *file, int *data, int rows, int columns); 96 | void wbExport(const char *file, int *data, int rows); 97 | void wbExport(const char *file, wbReal_t *data, int rows, int columns); 98 | void wbExport(const char *file, wbReal_t *data, int rows); 99 | void wbExport(const char *file, wbImage_t img); 100 | 101 | void wbExport(const char *file, wbExportKind_t kind, void *data, int rows, 102 | int columns, wbType_t type); 103 | 104 | void wbExport_text(const char *file, void *data, int length); 105 | 106 | #endif /* __WB_EXPORT_H__ */ 107 | -------------------------------------------------------------------------------- /wbArg.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | #ifdef WB_USE_SESSION_ID 5 | static char * _sessionId = nullptr; 6 | char * _envSessionId() { 7 | #ifdef WB_USE_UNIX 8 | if (_sessionId != nullptr) { 9 | char *env = std::getenv("SESSION_ID"); 10 | if (env) { 11 | _sessionId = wbString_duplicate(env); 12 | } 13 | } 14 | #endif /* WB_USE_UNIX */ 15 | return wbString_duplicate(_sessionId); 16 | } 17 | char * sessionId() { 18 | if (_sessionId != "") { 19 | return wbString_duplicate(_sessionId); 20 | } 21 | return wbString_duplicate(_envSessionId()); 22 | } 23 | #else /* WB_USE_SESSION_ID */ 24 | char * _envSessionId() { 25 | return wbString_duplicate("session_id_disabled"); 26 | } 27 | char * sessionId() { 28 | return wbString_duplicate("session_id_disabled"); 29 | } 30 | #endif /* WB_USE_SESSION_ID */ 31 | 32 | wbArg_t wbArg_new(int *argc, char ***argv) { 33 | wbArg_t arg; 34 | 35 | wb_init(argc, argv); 36 | 37 | wbArg_setSessionId(arg, _envSessionId()); 38 | wbArg_setInputCount(arg, 0); 39 | wbArg_setInputFiles(arg, NULL); 40 | wbArg_setOutputFile(arg, NULL); 41 | wbArg_setType(arg, NULL); 42 | wbArg_setExpectedOutputFile(arg, NULL); 43 | return arg; 44 | } 45 | 46 | void wbArg_delete(wbArg_t arg) { 47 | if (wbArg_getInputCount(arg) > 0 && wbArg_getInputFiles(arg) != nullptr) { 48 | int ii; 49 | for (ii = 0; ii < wbArg_getInputCount(arg); ii++) { 50 | wbDelete(wbArg_getInputFile(arg, ii)); 51 | } 52 | wbDelete(wbArg_getInputFiles(arg)); 53 | wbArg_setInputCount(arg, 0); 54 | wbArg_setInputFiles(arg, NULL); 55 | } 56 | if (wbArg_getOutputFile(arg)) { 57 | wbDelete(wbArg_getOutputFile(arg)); 58 | wbArg_setOutputFile(arg, NULL); 59 | } 60 | if (wbArg_getExpectedOutputFile(arg)) { 61 | wbDelete(wbArg_getExpectedOutputFile(arg)); 62 | wbArg_setExpectedOutputFile(arg, NULL); 63 | } 64 | if (wbArg_getType(arg)) { 65 | wbDelete(wbArg_getType(arg)); 66 | wbArg_setType(arg, NULL); 67 | } 68 | return; 69 | } 70 | 71 | static int getInputFileCount(char *arg) { 72 | int count = 1; 73 | while (*arg != '\0' && *arg != '-') { 74 | if (*arg == ',') { 75 | count++; 76 | } 77 | arg++; 78 | } 79 | return count; 80 | } 81 | 82 | static char **parseInputFiles(char *arg, int *resCount) { 83 | int count; 84 | int ii = 0; 85 | char **files; 86 | char *token; 87 | 88 | count = getInputFileCount(arg); 89 | 90 | files = wbNewArray(char *, count); 91 | 92 | token = strtok(arg, ","); 93 | while (token != nullptr) { 94 | files[ii++] = wbString_duplicate(token); 95 | token = strtok(NULL, ","); 96 | } 97 | *resCount = ii; 98 | return files; 99 | } 100 | 101 | static char *parseString(char *arg) { 102 | return wbString_duplicate(arg); 103 | } 104 | 105 | static void parseSessionId(char *arg) { 106 | #ifdef WB_USE_SESSION_ID 107 | _sessionId = std::string(arg); 108 | #endif /* WB_USE_SESSION_ID */ 109 | } 110 | 111 | wbArg_t wbArg_read(int argc, char **argv) { 112 | int ii; 113 | wbArg_t arg; 114 | 115 | arg = wbArg_new(&argc, &argv); 116 | for (ii = 0; ii < argc; ii++) { 117 | if (wbString_startsWith(argv[ii], "-s")) { 118 | parseSessionId(argv[++ii]); 119 | wbArg_setSessionId(arg, sessionId()); 120 | } else if (wbString_startsWith(argv[ii], "-i")) { 121 | int fileCount; 122 | char **files; 123 | 124 | files = parseInputFiles(argv[++ii], &fileCount); 125 | 126 | wbArg_setInputCount(arg, fileCount); 127 | wbArg_setInputFiles(arg, files); 128 | } else if (wbString_startsWith(argv[ii], "-o")) { 129 | char *file = parseString(argv[++ii]); 130 | wbArg_setOutputFile(arg, file); 131 | } else if (wbString_startsWith(argv[ii], "-e")) { 132 | char *file = parseString(argv[++ii]); 133 | wbArg_setExpectedOutputFile(arg, file); 134 | } else if (wbString_startsWith(argv[ii], "-t")) { 135 | char *type = parseString(argv[++ii]); 136 | wbArg_setType(arg, type); 137 | } else if (argv[ii][0] == '-') { 138 | wbLog(ERROR, "Unexpected program option ", argv[ii]); 139 | } 140 | } 141 | 142 | return arg; 143 | } 144 | -------------------------------------------------------------------------------- /wbImage.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "wb.h" 4 | 5 | static inline float _min(float x, float y) { 6 | return x < y ? x : y; 7 | } 8 | 9 | static inline float _max(float x, float y) { 10 | return x > y ? x : y; 11 | } 12 | 13 | static inline float _clamp(float x, float start, float end) { 14 | return _min(_max(x, start), end); 15 | } 16 | 17 | wbImage_t wbImage_new(int width, int height, int channels, float *data) { 18 | wbImage_t img; 19 | 20 | img = wbNew(struct st_wbImage_t); 21 | 22 | wbImage_setWidth(img, width); 23 | wbImage_setHeight(img, height); 24 | wbImage_setChannels(img, channels); 25 | wbImage_setPitch(img, width * channels); 26 | 27 | wbImage_setData(img, data); 28 | return img; 29 | } 30 | 31 | wbImage_t wbImage_new(int width, int height, int channels) { 32 | float *data = wbNewArray(float, width *height *channels); 33 | return wbImage_new(width, height, channels, data); 34 | } 35 | 36 | wbImage_t wbImage_new(int width, int height) { 37 | return wbImage_new(width, height, wbImage_channels); 38 | } 39 | 40 | void wbImage_delete(wbImage_t img) { 41 | if (img != nullptr) { 42 | if (wbImage_getData(img) != nullptr) { 43 | wbDelete(wbImage_getData(img)); 44 | } 45 | wbDelete(img); 46 | } 47 | } 48 | 49 | static inline void wbImage_setPixel(wbImage_t img, int x, int y, int c, 50 | float val) { 51 | float *data = wbImage_getData(img); 52 | int channels = wbImage_getChannels(img); 53 | int pitch = wbImage_getPitch(img); 54 | 55 | data[y * pitch + x * channels + c] = val; 56 | 57 | return; 58 | } 59 | 60 | static inline float wbImage_getPixel(wbImage_t img, int x, int y, int c) { 61 | float *data = wbImage_getData(img); 62 | int channels = wbImage_getChannels(img); 63 | int pitch = wbImage_getPitch(img); 64 | 65 | return data[y * pitch + x * channels + c]; 66 | } 67 | 68 | wbBool wbImage_sameQ(wbImage_t a, wbImage_t b, 69 | wbImage_onSameFunction_t onUnSame) { 70 | if (a == nullptr || b == nullptr) { 71 | wbLog(ERROR, "Comparing null images."); 72 | return wbFalse; 73 | } else if (a == b) { 74 | return wbTrue; 75 | } else if (wbImage_getWidth(a) != wbImage_getWidth(b)) { 76 | wbLog(ERROR, "Image widths do not match."); 77 | return wbFalse; 78 | } else if (wbImage_getHeight(a) != wbImage_getHeight(b)) { 79 | wbLog(ERROR, "Image heights do not match."); 80 | return wbFalse; 81 | } else if (wbImage_getChannels(a) != wbImage_getChannels(b)) { 82 | wbLog(ERROR, "Image channels do not match."); 83 | return wbFalse; 84 | } else { 85 | float *aData, *bData; 86 | int width, height, channels; 87 | int ii, jj, kk; 88 | 89 | aData = wbImage_getData(a); 90 | bData = wbImage_getData(b); 91 | 92 | wbAssert(aData != nullptr); 93 | wbAssert(bData != nullptr); 94 | 95 | width = wbImage_getWidth(a); 96 | height = wbImage_getHeight(a); 97 | channels = wbImage_getChannels(a); 98 | 99 | for (ii = 0; ii < height; ii++) { 100 | for (jj = 0; jj < width; jj++) { 101 | for (kk = 0; kk < channels; kk++) { 102 | float x, y; 103 | if (channels <= 3) { 104 | x = _clamp(*aData++, 0, 1); 105 | y = _clamp(*bData++, 0, 1); 106 | } else { 107 | x = *aData++; 108 | y = *bData++; 109 | } 110 | if (wbUnequalQ(x, y)) { 111 | if (onUnSame != nullptr) { 112 | string str = wbString( 113 | "Image pixels do not match at position ( row = ", 114 | wbString(ii, ", col = ", jj, ", channel = ", kk, 115 | ") expecting a value of "), 116 | wbString(y, " but got a computed value of ", x)); 117 | onUnSame(str); 118 | } 119 | return wbFalse; 120 | } 121 | } 122 | } 123 | } 124 | return wbTrue; 125 | } 126 | } 127 | 128 | static void wbImage_onUnsameFunction(string str) { 129 | wbLog(ERROR, str); 130 | } 131 | 132 | wbBool wbImage_sameQ(wbImage_t a, wbImage_t b) { 133 | return wbImage_sameQ(a, b, wbImage_onUnsameFunction); 134 | } 135 | -------------------------------------------------------------------------------- /wbComparator.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_COMPARATOR_H__ 4 | #define __WB_COMPARATOR_H__ 5 | 6 | #include "wb.h" 7 | 8 | template 9 | static inline T _abs(const T &a) { 10 | return a < 0 ? -a : a; 11 | } 12 | 13 | static inline wbBool _almostEqual(double A, double B, double eps) { 14 | if (A == 0) { 15 | return _abs(B) < eps; 16 | } else if (B == 0) { 17 | return _abs(A) < eps; 18 | } else { 19 | #if 0 20 | double d = max(_abs(A), _abs(B)); 21 | double g = (_abs(A - B) / d); 22 | #else 23 | double g = _abs(A - B); 24 | #endif 25 | if (g <= eps) { 26 | return wbTrue; 27 | } else { 28 | return wbFalse; 29 | } 30 | } 31 | } 32 | 33 | static inline wbBool _almostEqual(float A, float B, float eps) { 34 | if (A == 0) { 35 | return _abs(B) < eps; 36 | } else if (B == 0) { 37 | return _abs(A) < eps; 38 | } else { 39 | #if 0 40 | float d = max(_abs(A), _abs(B)); 41 | float g = (_abs(A - B) / d); 42 | #else 43 | float g = _abs(A - B); 44 | #endif 45 | if (g <= eps) { 46 | return wbTrue; 47 | } else { 48 | return wbFalse; 49 | } 50 | } 51 | } 52 | 53 | static inline wbBool _almostEqual(double A, double B) { 54 | return _almostEqual(A, B, 0.2); 55 | } 56 | 57 | static inline wbBool _almostEqual(float A, float B) { 58 | return _almostEqual(A, B, 0.2f); 59 | } 60 | 61 | static inline wbBool _almostEqual2sComplement(float A, float B, 62 | int maxUlps) { 63 | // Make sure maxUlps is non-negative and small enough that the 64 | // default NAN won't compare as equal to anything. 65 | 66 | int aInt, bInt, intDiff; 67 | 68 | wbAssert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); 69 | 70 | int *tmp = reinterpret_cast(&A); 71 | aInt = *tmp; 72 | 73 | // Make aInt lexicographically ordered as a twos-complement int 74 | if (aInt < 0) { 75 | aInt = 0x80000000 - aInt; 76 | } 77 | // Make bInt lexicographically ordered as a twos-complement int 78 | tmp = reinterpret_cast(&B); 79 | bInt = *tmp; 80 | if (bInt < 0) { 81 | bInt = 0x80000000 - bInt; 82 | } 83 | intDiff = _abs(aInt - bInt); 84 | if (intDiff <= maxUlps) { 85 | return wbTrue; 86 | } 87 | return wbFalse; 88 | } 89 | 90 | static inline wbBool _almostEqual2sComplement(float A, float B) { 91 | return _almostEqual2sComplement(A, B, 4); 92 | } 93 | 94 | static inline wbBool _almostEqual2sComplement(double A, double B, 95 | int maxUlps) { 96 | // Make sure maxUlps is non-negative and small enough that the 97 | // default NAN won't compare as equal to anything. 98 | 99 | int64_t aInt, bInt, intDiff; 100 | 101 | wbAssert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); 102 | 103 | int64_t *tmp = reinterpret_cast(&A); 104 | aInt = *tmp; 105 | 106 | // Make aInt lexicographically ordered as a twos-complement int 107 | if (aInt < 0) { 108 | aInt = 0x80000000 - aInt; 109 | } 110 | // Make bInt lexicographically ordered as a twos-complement int 111 | tmp = reinterpret_cast(&B); 112 | bInt = *tmp; 113 | if (bInt < 0) { 114 | bInt = 0x80000000 - bInt; 115 | } 116 | intDiff = _abs(aInt - bInt); 117 | if (intDiff <= maxUlps) { 118 | return wbTrue; 119 | } 120 | return wbFalse; 121 | } 122 | 123 | static inline wbBool _almostEqual2sComplement(double A, double B) { 124 | return _almostEqual2sComplement(A, B, 4); 125 | } 126 | 127 | template 128 | static inline int wbCompare(const T &a, const T &b) { 129 | if (a == b) { 130 | return 0; 131 | } else if (a < b) { 132 | return -1; 133 | } else { 134 | return 1; 135 | } 136 | } 137 | 138 | template <> 139 | inline int wbCompare(const double &a, const double &b) { 140 | if (_almostEqual(a, b)) { 141 | return 0; 142 | } else if (a < b) { 143 | return -1; 144 | } else { 145 | return 1; 146 | } 147 | } 148 | 149 | template <> 150 | inline int wbCompare(const float &a, const float &b) { 151 | if (_almostEqual(a, b)) { 152 | return 0; 153 | } else if (a < b) { 154 | return -1; 155 | } else { 156 | return 1; 157 | } 158 | } 159 | 160 | template 161 | static inline wbBool wbEqualQ(const T &a, const T &b) { 162 | return wbCompare(a, b) == 0; 163 | } 164 | 165 | template 166 | static inline wbBool wbUnequalQ(const T &a, const T &b) { 167 | return wbCompare(a, b) != 0; 168 | } 169 | 170 | template 171 | static inline wbBool wbEqualQ(const T *a, const T *b, size_t n) { 172 | size_t ii; 173 | 174 | for (ii = 0; ii < n; ii++) { 175 | if (wbUnequalQ(a[ii], b[ii])) { 176 | return wbFalse; 177 | } 178 | } 179 | return wbTrue; 180 | } 181 | 182 | template 183 | static inline wbBool wbUnequalQ(const T *a, const T *b, size_t n) { 184 | return !wbEqualQ(a, b, n); 185 | } 186 | 187 | #endif /* __WB_COMPARATOR_H__ */ 188 | -------------------------------------------------------------------------------- /wb.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_H__ 4 | #define __WB_H__ 5 | 6 | /***********************************************************/ 7 | /***********************************************************/ 8 | /***********************************************************/ 9 | /***********************************************************/ 10 | /***********************************************************/ 11 | /***********************************************************/ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef _MSC_VER 19 | 20 | // set minimal warning level 21 | #pragma warning(push, 0) 22 | // some warnings still occur at this level 23 | // if necessary, disable specific warnings not covered by previous pragma 24 | #pragma warning( \ 25 | disable : 4244 4056 4305 4800 4267 4996 4756 4661 4385 4101 4800) 26 | 27 | #define NOMINMAX // do not define min/max in the standard headers 28 | 29 | #define __func__ __FUNCTION__ 30 | #ifndef _CRT_SECURE_NO_WARNINGS 31 | #define _CRT_SECURE_NO_WARNINGS 1 32 | #endif /* _CRT_SECURE_NO_WARNINGS */ 33 | #define _CRT_SECURE_NO_DEPRECATE 1 34 | #define _CRT_NONSTDC_NO_DEPRECATE 1 35 | #include 36 | #include 37 | #include 38 | #define WB_USE_WINDOWS 39 | #else /* _MSC_VER */ 40 | #include 41 | #include 42 | #include 43 | #include 44 | #define WB_USE_UNIX 45 | #ifdef __APPLE__ 46 | #include 47 | #define WB_USE_DARWIN 48 | #else /* __APPLE__ */ 49 | #define WB_USE_LINUX 50 | #endif /* __APPLE__ */ 51 | #endif /* _MSC_VER */ 52 | 53 | #define wbStmt(stmt) stmt 54 | 55 | /***********************************************************/ 56 | /***********************************************************/ 57 | /***********************************************************/ 58 | /***********************************************************/ 59 | /***********************************************************/ 60 | /***********************************************************/ 61 | 62 | #define wbLine __LINE__ 63 | #define wbFile __FILE__ 64 | #define wbFunction __func__ 65 | 66 | #define wbExit() \ 67 | wbAssert(0); \ 68 | exit(1) 69 | 70 | #ifdef JSON_OUTPUT 71 | #ifdef WB_USE_COURSERA 72 | #define wbLogger_printOnExit 1 73 | #else /* WB_USE_COURSERA */ 74 | #define wbLogger_printOnLog 1 75 | #endif /* WB_USE_COURSERA */ 76 | #endif /* JSON_OUTPUT */ 77 | 78 | /***********************************************************/ 79 | /***********************************************************/ 80 | /***********************************************************/ 81 | /***********************************************************/ 82 | /***********************************************************/ 83 | /***********************************************************/ 84 | 85 | #ifdef __cplusplus 86 | #define EXTERN_C extern "C" 87 | #define START_EXTERN_C EXTERN_C { 88 | #define END_EXTERN_C } 89 | #else 90 | #define EXTERN_C 91 | #define START_EXTERN_C 92 | #define END_EXTERN_C 93 | #endif /* __cplusplus */ 94 | 95 | /***********************************************************/ 96 | /***********************************************************/ 97 | /***********************************************************/ 98 | 99 | #ifndef WB_USE_JSON11 100 | #define WB_USE_JSON11 1 101 | #endif /* WB_USE_JSON11 */ 102 | 103 | #if 1 || WB_USE_JSON11 104 | #include "vendor/json11.hpp" 105 | #endif /* WB_USE_JSON11 */ 106 | 107 | /***********************************************************/ 108 | /***********************************************************/ 109 | /***********************************************************/ 110 | 111 | #define LAZY_FILE_LOAD 112 | extern char *solutionJSON; 113 | 114 | /***********************************************************/ 115 | /***********************************************************/ 116 | /***********************************************************/ 117 | /***********************************************************/ 118 | /***********************************************************/ 119 | /***********************************************************/ 120 | 121 | #ifdef WB_USE_OPENCL 122 | #ifdef WB_USE_DARWIN 123 | #include 124 | #else /* WB_USE_DARWIN */ 125 | #include 126 | #endif /* WB_USE_DARWIN */ 127 | #endif /* WB_USE_OPENCL */ 128 | 129 | #include "wbTypes.h" 130 | 131 | #include "wbAssert.h" 132 | #include "wbMalloc.h" 133 | #include "wbString.h" 134 | #include "wbUtils.h" 135 | 136 | #include "wbArg.h" 137 | #include "wbCUDA.h" 138 | #include "wbCast.h" 139 | #include "wbComparator.h" 140 | #include "wbDirectory.h" 141 | #include "wbExit.h" 142 | #include "wbExport.h" 143 | #include "wbFile.h" 144 | #include "wbImage.h" 145 | #include "wbImport.h" 146 | #include "wbInit.h" 147 | #include "wbLogger.h" 148 | #include "wbMD5.h" 149 | #include "wbMPI.h" 150 | #include "wbSolution.h" 151 | #include "wbSort.h" 152 | #include "wbSparse.h" 153 | #include "wbThrust.h" 154 | #include "wbTimer.h" 155 | #include "wbPath.h" 156 | 157 | #include "wbDataset.h" 158 | 159 | /***********************************************************/ 160 | /***********************************************************/ 161 | /***********************************************************/ 162 | /***********************************************************/ 163 | /***********************************************************/ 164 | /***********************************************************/ 165 | 166 | #endif /* __WB_H__ */ 167 | -------------------------------------------------------------------------------- /wbPPM.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "wb.h" 4 | 5 | static inline float _min(float x, float y) { 6 | return x < y ? x : y; 7 | } 8 | 9 | static inline float _max(float x, float y) { 10 | return x > y ? x : y; 11 | } 12 | 13 | static inline float _clamp(float x, float start, float end) { 14 | return _min(_max(x, start), end); 15 | } 16 | 17 | static const char *skipSpaces(const char *line) { 18 | while (*line == ' ' || *line == '\t') { 19 | line++; 20 | if (*line == '\0') { 21 | break; 22 | } 23 | } 24 | return line; 25 | } 26 | 27 | static char nextNonSpaceChar(const char *line0) { 28 | const char *line = skipSpaces(line0); 29 | return *line; 30 | } 31 | 32 | static wbBool isComment(const char *line) { 33 | char nextChar = nextNonSpaceChar(line); 34 | if (nextChar == '\0') { 35 | return wbTrue; 36 | } else { 37 | return nextChar == '#'; 38 | } 39 | } 40 | 41 | static void parseDimensions(const char *line0, int *width, int *height) { 42 | const char *line = skipSpaces(line0); 43 | sscanf(line, "%d %d", width, height); 44 | } 45 | 46 | static void parseDimensions(const char *line0, int *width, int *height, 47 | int *channels) { 48 | const char *line = skipSpaces(line0); 49 | sscanf(line, "%d %d %d", width, height, channels); 50 | } 51 | 52 | static void parseDepth(const char *line0, int *depth) { 53 | const char *line = skipSpaces(line0); 54 | sscanf(line, "%d", depth); 55 | } 56 | 57 | static char *nextLine(wbFile_t file) { 58 | char *line = nullptr; 59 | while ((line = wbFile_readLine(file)) != nullptr) { 60 | if (!isComment(line)) { 61 | break; 62 | } 63 | } 64 | return line; 65 | } 66 | 67 | wbImage_t wbPPM_import(const char *filename) { 68 | wbImage_t img; 69 | wbFile_t file; 70 | char *header; 71 | char *line; 72 | int ii, jj, kk, channels; 73 | int width, height, depth; 74 | unsigned char *charData, *charIter; 75 | float *imgData, *floatIter; 76 | float scale; 77 | 78 | img = nullptr; 79 | 80 | file = wbFile_open(filename, "rb"); 81 | if (file == nullptr) { 82 | printf("Could not open %s\n", filename); 83 | goto cleanup; 84 | } 85 | 86 | header = wbFile_readLine(file); 87 | if (header == nullptr) { 88 | printf("Could not read from %s\n", filename); 89 | goto cleanup; 90 | } else if (strcmp(header, "P6") != 0 && strcmp(header, "P6\n") != 0 && 91 | strcmp(header, "P5") != 0 && strcmp(header, "P5\n") != 0 && 92 | strcmp(header, "S6") != 0 && strcmp(header, "S6\n") != 0) { 93 | printf("Could not find magic number for %s\n", filename); 94 | goto cleanup; 95 | } 96 | 97 | // P5 are monochrome while P6/S6 are rgb 98 | // S6 needs to parse number of channels out of file 99 | if (strcmp(header, "P5") == 0 || strcmp(header, "P5\n") == 0) { 100 | channels = 1; 101 | line = nextLine(file); 102 | parseDimensions(line, &width, &height); 103 | } else if (strcmp(header, "P6") == 0 || strcmp(header, "P6\n") == 0) { 104 | channels = 3; 105 | line = nextLine(file); 106 | parseDimensions(line, &width, &height); 107 | } else { 108 | line = nextLine(file); 109 | parseDimensions(line, &width, &height, &channels); 110 | } 111 | 112 | // the line now contains the depth information 113 | line = nextLine(file); 114 | parseDepth(line, &depth); 115 | 116 | // the rest of the lines contain the data in binary format 117 | charData = (unsigned char *)wbFile_read( 118 | file, width * channels * sizeof(unsigned char), height); 119 | 120 | img = wbImage_new(width, height, channels); 121 | 122 | imgData = wbImage_getData(img); 123 | 124 | charIter = charData; 125 | floatIter = imgData; 126 | 127 | scale = 1.0f / ((float)depth); 128 | 129 | for (ii = 0; ii < height; ii++) { 130 | for (jj = 0; jj < width; jj++) { 131 | for (kk = 0; kk < channels; kk++) { 132 | *floatIter = ((float)*charIter) * scale; 133 | floatIter++; 134 | charIter++; 135 | } 136 | } 137 | } 138 | 139 | #ifdef LAZY_FILE_LOAD 140 | wbDelete(charData); 141 | #endif 142 | 143 | cleanup: 144 | wbFile_close(file); 145 | return img; 146 | } 147 | 148 | void wbPPM_export(const char *filename, wbImage_t img) { 149 | int ii; 150 | int jj; 151 | int kk; 152 | int depth; 153 | int width; 154 | int height; 155 | int channels; 156 | wbFile_t file; 157 | float *floatIter; 158 | unsigned char *charData; 159 | unsigned char *charIter; 160 | 161 | file = wbFile_open(filename, "wb+"); 162 | 163 | width = wbImage_getWidth(img); 164 | height = wbImage_getHeight(img); 165 | channels = wbImage_getChannels(img); 166 | depth = 255; 167 | 168 | if (channels == 1) { 169 | wbFile_writeLine(file, "P5"); 170 | } else { 171 | wbFile_writeLine(file, "P6"); 172 | } 173 | wbFile_writeLine(file, "#Created via wbPPM Export"); 174 | wbFile_writeLine(file, wbString(width, " ", height)); 175 | wbFile_writeLine(file, wbString(depth)); 176 | 177 | charData = wbNewArray(unsigned char, width *height *channels); 178 | 179 | charIter = charData; 180 | floatIter = wbImage_getData(img); 181 | 182 | for (ii = 0; ii < height; ii++) { 183 | for (jj = 0; jj < width; jj++) { 184 | for (kk = 0; kk < channels; kk++) { 185 | *charIter = (unsigned char)ceil(_clamp(*floatIter, 0, 1) * depth); 186 | floatIter++; 187 | charIter++; 188 | } 189 | } 190 | } 191 | 192 | wbFile_write(file, charData, width * channels * sizeof(unsigned char), 193 | height); 194 | 195 | wbDelete(charData); 196 | wbFile_delete(file); 197 | 198 | return; 199 | } 200 | -------------------------------------------------------------------------------- /wbDataset.cpp: -------------------------------------------------------------------------------- 1 | #include "wb.h" 2 | 3 | template 4 | static inline T _min(const T &x, const T &y) { 5 | return x < y ? x : y; 6 | } 7 | 8 | template 9 | static inline T _max(const T &x, const T &y) { 10 | return x > y ? x : y; 11 | } 12 | 13 | template 14 | inline T lerp(const double &x, const T &start, const T &end) { 15 | return (1 - x) * start + x * end; 16 | } 17 | 18 | static inline void genRandom(void *trgt, wbType_t type, double minVal, 19 | double maxVal) { 20 | const int span = maxVal - minVal; 21 | const int r = rand(); 22 | const double rf = ((double)r) / ((double)RAND_MAX); 23 | switch (type) { 24 | case wbType_ascii: 25 | *((char *)trgt) = (r % span) + minVal; // random printable character; 26 | break; 27 | case wbType_bit8: 28 | *((char *)trgt) = lerp(rf, minVal, maxVal); 29 | break; 30 | case wbType_ubit8: 31 | *((unsigned char *)trgt) = lerp(rf, minVal, maxVal); 32 | break; 33 | case wbType_integer: 34 | *((int *)trgt) = lerp(rf, minVal, maxVal); 35 | break; 36 | case wbType_float: { 37 | *((float *)trgt) = lerp(rf, minVal, maxVal); 38 | break; 39 | } 40 | case wbType_double: { 41 | *((double *)trgt) = lerp(rf, minVal, maxVal); 42 | break; 43 | } 44 | case wbType_unknown: 45 | wbAssert(false && "Invalid wbType_unknown"); 46 | break; 47 | } 48 | return; 49 | } 50 | 51 | static inline void *genRandomList(wbType_t type, size_t len, double minVal, 52 | double maxVal) { 53 | size_t ii; 54 | void *data = wbNewArray(char, wbType_size(type) * len); 55 | switch (type) { 56 | case wbType_ascii: 57 | case wbType_bit8: { 58 | char *iter = (char *)data; 59 | for (ii = 0; ii < len; ii++) { 60 | genRandom(iter++, type, minVal, maxVal); 61 | } 62 | break; 63 | } 64 | case wbType_ubit8: { 65 | unsigned char *iter = (unsigned char *)data; 66 | for (ii = 0; ii < len; ii++) { 67 | genRandom(iter++, type, minVal, maxVal); 68 | } 69 | break; 70 | } 71 | case wbType_integer: { 72 | int *iter = (int *)data; 73 | for (ii = 0; ii < len; ii++) { 74 | genRandom(iter++, type, minVal, maxVal); 75 | } 76 | break; 77 | } 78 | case wbType_float: { 79 | float *iter = (float *)data; 80 | for (ii = 0; ii < len; ii++) { 81 | genRandom(iter++, type, minVal, maxVal); 82 | } 83 | break; 84 | } 85 | case wbType_double: { 86 | double *iter = (double *)data; 87 | for (ii = 0; ii < len; ii++) { 88 | genRandom(iter++, type, minVal, maxVal); 89 | } 90 | break; 91 | } 92 | case wbType_unknown: 93 | wbAssert(false && "Invalid wbType_unknown"); 94 | break; 95 | } 96 | return data; 97 | } 98 | 99 | static void genRaw(const char *path, wbRaw_GenerateParams_t params) { 100 | int rows = _max(1, params.rows); 101 | int cols = _max(1, params.cols); 102 | double minVal = params.minVal; 103 | double maxVal = params.maxVal; 104 | wbType_t type = params.type; 105 | void *data = genRandomList(type, rows * cols, minVal, maxVal); 106 | wbExport(path, wbExportKind_raw, data, rows, cols, type); 107 | wbDelete(data); 108 | } 109 | 110 | static void genCSV(const char *path, wbCSV_GenerateParams_t params) { 111 | int rows = _max(1, params.rows); 112 | int cols = _max(1, params.cols); 113 | double minVal = params.minVal; 114 | double maxVal = params.maxVal; 115 | wbType_t type = params.type; 116 | void *data = genRandomList(type, rows * cols, minVal, maxVal); 117 | wbExport(path, wbExportKind_csv, data, rows, cols, type); 118 | wbDelete(data); 119 | } 120 | 121 | static void genTSV(const char *path, wbTSV_GenerateParams_t params) { 122 | int rows = _max(1, params.rows); 123 | int cols = _max(1, params.cols); 124 | double minVal = params.minVal; 125 | double maxVal = params.maxVal; 126 | wbType_t type = params.type; 127 | void *data = genRandomList(type, rows * cols, minVal, maxVal); 128 | wbExport(path, wbExportKind_tsv, data, rows, cols, type); 129 | wbDelete(data); 130 | } 131 | 132 | static void genText(const char *path, wbText_GenerateParams_t params) { 133 | int length = _max(1, params.length); 134 | wbType_t type = wbType_ascii; 135 | void *data = genRandomList(type, length, 32, 128); 136 | wbExport(path, wbExportKind_text, data, length, 1, type); 137 | wbDelete(data); 138 | } 139 | 140 | static void genPPM(const char *path, wbPPM_GenerateParams_t params) { 141 | int width = _max(1, params.width); 142 | int height = _max(1, params.height); 143 | int channels = _max(1, params.channels); 144 | double minVal = params.minVal; 145 | double maxVal = params.maxVal; 146 | wbType_t type = wbType_float; 147 | float *data = (float *)genRandomList(type, width * height * channels, 148 | minVal, maxVal); 149 | wbImage_t img = wbImage_new(width, height, channels, data); 150 | wbExport(path, img); 151 | wbImage_delete(img); 152 | } 153 | 154 | EXTERN_C void wbDataset_generate(const char *path, wbExportKind_t kind, 155 | wbGenerateParams_t params) { 156 | wbDirectory_create(wbDirectory_name(path)); 157 | 158 | switch (kind) { 159 | case wbExportKind_raw: 160 | genRaw(path, params.raw); 161 | break; 162 | case wbExportKind_csv: 163 | genCSV(path, params.csv); 164 | break; 165 | case wbExportKind_tsv: 166 | genTSV(path, params.tsv); 167 | break; 168 | case wbExportKind_ppm: 169 | genPPM(path, params.ppm); 170 | break; 171 | case wbExportKind_text: 172 | genText(path, params.text); 173 | break; 174 | default: 175 | wbAssert(false && "Invalid Export kind"); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /wbTimer.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_TIMER_H__ 4 | #define __WB_TIMER_H__ 5 | 6 | #ifdef WB_USE_WINDOWS 7 | extern uint64_t _hrtime_frequency; 8 | #endif /* _WIN32 */ 9 | 10 | extern wbTimer_t _timer; 11 | 12 | typedef enum en_wbTimerKind_t { 13 | wbTimerKind_Generic, 14 | wbTimerKind_IO, 15 | wbTimerKind_GPU, 16 | wbTimerKind_Copy, 17 | wbTimerKind_Driver, 18 | wbTimerKind_CopyAsync, 19 | wbTimerKind_Compute, 20 | wbTimerKind_CPUGPUOverlap, 21 | } wbTimerKind_t; 22 | 23 | struct st_wbTimerNode_t { 24 | int idx; 25 | char * id; 26 | char * session_id; 27 | int mpiRank; 28 | int level; 29 | wbBool stoppedQ; 30 | wbTimerKind_t kind; 31 | uint64_t startTime; 32 | uint64_t endTime; 33 | uint64_t elapsedTime; 34 | int startLine; 35 | int endLine; 36 | const char *startFunction; 37 | const char *endFunction; 38 | const char *startFile; 39 | const char *endFile; 40 | wbTimerNode_t next; 41 | wbTimerNode_t prev; 42 | wbTimerNode_t parent; 43 | char *msg; 44 | }; 45 | 46 | struct st_wbTimer_t { 47 | char * id; 48 | char * session_id; 49 | size_t length; 50 | wbTimerNode_t head; 51 | wbTimerNode_t tail; 52 | uint64_t startTime; 53 | uint64_t endTime; 54 | uint64_t elapsedTime; 55 | }; 56 | 57 | #define wbTimerNode_getIdx(node) ((node)->idx) 58 | #define wbTimerNode_getId(node) ((node)->id) 59 | #define wbTimerNode_getSessionId(node) ((node)->session_id) 60 | #define wbTimerNode_getMPIRank(node) ((node)->mpiRank) 61 | #define wbTimerNode_getLevel(node) ((node)->level) 62 | #define wbTimerNode_getStoppedQ(node) ((node)->stoppedQ) 63 | #define wbTimerNode_getKind(node) ((node)->kind) 64 | #define wbTimerNode_getStartTime(node) ((node)->startTime) 65 | #define wbTimerNode_getEndTime(node) ((node)->endTime) 66 | #define wbTimerNode_getElapsedTime(node) ((node)->elapsedTime) 67 | #define wbTimerNode_getStartLine(node) ((node)->startLine) 68 | #define wbTimerNode_getEndLine(node) ((node)->endLine) 69 | #define wbTimerNode_getStartFunction(node) ((node)->startFunction) 70 | #define wbTimerNode_getEndFunction(node) ((node)->endFunction) 71 | #define wbTimerNode_getStartFile(node) ((node)->startFile) 72 | #define wbTimerNode_getEndFile(node) ((node)->endFile) 73 | #define wbTimerNode_getNext(node) ((node)->next) 74 | #define wbTimerNode_getPrevious(node) ((node)->prev) 75 | #define wbTimerNode_getParent(node) ((node)->parent) 76 | #define wbTimerNode_getMessage(node) ((node)->msg) 77 | 78 | #define wbTimerNode_setIdx(node, val) (wbTimerNode_getIdx(node) = val) 79 | #define wbTimerNode_setId(node, val) (wbTimerNode_getId(node) = val) 80 | #define wbTimerNode_setSessionId(node, val) \ 81 | (wbTimerNode_getSessionId(node) = val) 82 | #define wbTimerNode_setMPIRank(node, val) \ 83 | (wbTimerNode_getMPIRank(node) = val) 84 | #define wbTimerNode_setLevel(node, val) (wbTimerNode_getLevel(node) = val) 85 | #define wbTimerNode_setStoppedQ(node, val) \ 86 | (wbTimerNode_getStoppedQ(node) = val) 87 | #define wbTimerNode_setKind(node, val) (wbTimerNode_getKind(node) = val) 88 | #define wbTimerNode_setStartTime(node, val) \ 89 | (wbTimerNode_getStartTime(node) = val) 90 | #define wbTimerNode_setEndTime(node, val) \ 91 | (wbTimerNode_getEndTime(node) = val) 92 | #define wbTimerNode_setElapsedTime(node, val) \ 93 | (wbTimerNode_getElapsedTime(node) = val) 94 | #define wbTimerNode_setStartLine(node, val) \ 95 | (wbTimerNode_getStartLine(node) = val) 96 | #define wbTimerNode_setEndLine(node, val) \ 97 | (wbTimerNode_getEndLine(node) = val) 98 | #define wbTimerNode_setStartFunction(node, val) \ 99 | (wbTimerNode_getStartFunction(node) = val) 100 | #define wbTimerNode_setEndFunction(node, val) \ 101 | (wbTimerNode_getEndFunction(node) = val) 102 | #define wbTimerNode_setStartFile(node, val) \ 103 | (wbTimerNode_getStartFile(node) = val) 104 | #define wbTimerNode_setEndFile(node, val) \ 105 | (wbTimerNode_getEndFile(node) = val) 106 | #define wbTimerNode_setNext(node, val) (wbTimerNode_getNext(node) = val) 107 | #define wbTimerNode_setPrevious(node, val) \ 108 | (wbTimerNode_getPrevious(node) = val) 109 | #define wbTimerNode_setParent(node, val) \ 110 | (wbTimerNode_getParent(node) = val) 111 | #define wbTimerNode_setMessage(node, val) \ 112 | (wbTimerNode_getMessage(node) = val) 113 | 114 | #define wbTimerNode_stoppedQ(node) \ 115 | (wbTimerNode_getStoppedQ(node) == wbTrue) 116 | #define wbTimerNode_hasNext(node) (wbTimerNode_getNext(node) != nullptr) 117 | #define wbTimerNode_hasPrevious(node) \ 118 | (wbTimerNode_getPrevious(node) != nullptr) 119 | #define wbTimerNode_hasParent(node) (wbTimerNode_getParent(node) != nullptr) 120 | 121 | uint64_t _hrtime(void); 122 | 123 | wbTimer_t wbTimer_new(void); 124 | void wbTimer_delete(wbTimer_t timer); 125 | 126 | string wbTimer_toJSON(wbTimer_t timer); 127 | string wbTimer_toJSON(); 128 | 129 | string wbTimer_toXML(wbTimer_t timer); 130 | string wbTimer_toXML(); 131 | 132 | wbTimerNode_t wbTimer_start(wbTimerKind_t kind, const char *file, 133 | const char *fun, int line); 134 | wbTimerNode_t wbTimer_start(wbTimerKind_t kind, string msg, 135 | const char *file, const char *fun, int line); 136 | void wbTimer_stop(wbTimerKind_t kind, string msg, const char *file, 137 | const char *fun, int line); 138 | void wbTimer_stop(wbTimerKind_t kind, const char *file, const char *fun, 139 | int line); 140 | 141 | #define wbTime_start(kind, ...) \ 142 | wbTimer_start(wbTimerKind_##kind, wbString(__VA_ARGS__), wbFile, \ 143 | wbFunction, wbLine) 144 | #define wbTime_stop(kind, ...) \ 145 | wbTimer_stop(wbTimerKind_##kind, wbString(__VA_ARGS__), wbFile, \ 146 | wbFunction, wbLine) 147 | 148 | #endif /* __WB_TIMER_H__ */ 149 | -------------------------------------------------------------------------------- /wbFile.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "wb.h" 4 | 5 | #define wbFile_maxCount 256 6 | 7 | static wbFile_t wbFile_handles[wbFile_maxCount]; 8 | 9 | static int wbFile_nextIndex(void) { 10 | int ii; 11 | for (ii = 0; ii < wbFile_maxCount; ii++) { 12 | if (wbFile_handles[ii] == nullptr) { 13 | return ii; 14 | } 15 | } 16 | wbLog(ERROR, "Ran out of file handles."); 17 | wbExit(); 18 | return -1; 19 | } 20 | 21 | wbFile_t wbFile_new(void) { 22 | int idx = wbFile_nextIndex(); 23 | wbFile_t file = wbNew(struct st_wbFile_t); 24 | 25 | wbAssert(idx >= 0); 26 | 27 | wbFile_setIndex(file, idx); 28 | wbFile_setFileName(file, NULL); 29 | wbFile_setMode(file, NULL); 30 | wbFile_setFileHandle(file, NULL); 31 | wbFile_setData(file, NULL); 32 | 33 | wbFile_handles[idx] = file; 34 | 35 | return file; 36 | } 37 | 38 | void wbFile_delete(wbFile_t file) { 39 | if (file != nullptr) { 40 | int idx = wbFile_getIndex(file); 41 | if (wbFile_getFileName(file) != nullptr) { 42 | wbDelete(wbFile_getFileName(file)); 43 | } 44 | if (wbFile_getMode(file) != nullptr) { 45 | wbDelete(wbFile_getMode(file)); 46 | } 47 | if (wbFile_getFileHandle(file) != nullptr) { 48 | fflush(wbFile_getFileHandle(file)); 49 | fclose(wbFile_getFileHandle(file)); 50 | } 51 | if (idx >= 0) { 52 | wbAssert(wbFile_handles[idx] == file); 53 | wbFile_handles[idx] = nullptr; 54 | } 55 | if (wbFile_getData(file) != nullptr) { 56 | wbDelete(wbFile_getData(file)); 57 | } 58 | wbDelete(file); 59 | } 60 | } 61 | 62 | void wbFile_init(void) { 63 | int ii; 64 | 65 | for (ii = 0; ii < wbFile_maxCount; ii++) { 66 | wbFile_handles[ii] = nullptr; 67 | } 68 | } 69 | 70 | void wbFile_atExit(void) { 71 | int ii; 72 | 73 | for (ii = 0; ii < wbFile_maxCount; ii++) { 74 | if (wbFile_handles[ii] != nullptr) { 75 | wbFile_delete(wbFile_handles[ii]); 76 | } 77 | } 78 | } 79 | 80 | int wbFile_count(void) { 81 | int ii, count = 0; 82 | 83 | for (ii = 0; ii < wbFile_maxCount; ii++) { 84 | if (wbFile_handles[ii] != nullptr) { 85 | count++; 86 | } 87 | } 88 | return count; 89 | } 90 | 91 | wbFile_t wbFile_open(const char *fileName, const char *mode) { 92 | FILE *handle; 93 | wbFile_t file; 94 | 95 | if (fileName == nullptr) { 96 | return NULL; 97 | } 98 | 99 | handle = fopen(fileName, mode); 100 | if (handle == nullptr) { 101 | wbLog(ERROR, "Failed to open ", file, " in mode ", mode); 102 | return NULL; 103 | } 104 | 105 | file = wbFile_new(); 106 | wbFile_setFileName(file, wbString_duplicate(fileName)); 107 | wbFile_setMode(file, wbString_duplicate(mode)); 108 | wbFile_setFileHandle(file, handle); 109 | 110 | return file; 111 | } 112 | 113 | wbFile_t wbFile_open(const char *fileName) { 114 | return wbFile_open(fileName, "r"); 115 | } 116 | 117 | void wbFile_close(wbFile_t file) { 118 | wbFile_delete(file); 119 | } 120 | 121 | char *wbFile_read(wbFile_t file, size_t size, size_t count) { 122 | size_t res; 123 | char *buffer; 124 | size_t bufferLen; 125 | FILE *handle; 126 | 127 | if (file == nullptr) { 128 | return NULL; 129 | } 130 | #ifndef LAZY_FILE_LOAD 131 | if (wbFile_getData(file) != nullptr) { 132 | char *data = wbFile_getData(file) + wbFile_getDataOffset(file); 133 | wbFile_setDataOffset(file, wbFile_getDataOffset(file) + size * count); 134 | return data; 135 | } 136 | #endif /* LAZY_FILE_LOAD */ 137 | 138 | handle = wbFile_getFileHandle(file); 139 | bufferLen = size * count + 1; 140 | buffer = wbNewArray(char, bufferLen); 141 | 142 | res = fread(buffer, size, count, handle); 143 | // make valid C string 144 | buffer[size * res] = '\0'; 145 | 146 | return buffer; 147 | } 148 | 149 | char *wbFile_read(wbFile_t file, size_t len) { 150 | char *buffer = wbFile_read(file, sizeof(char), len); 151 | return buffer; 152 | } 153 | 154 | void wbFile_rewind(wbFile_t file) { 155 | if (file == nullptr) { 156 | return; 157 | } 158 | 159 | if (wbFile_getData(file) == nullptr) { 160 | FILE *handle; 161 | handle = wbFile_getFileHandle(file); 162 | wbAssert(handle != nullptr); 163 | rewind(handle); 164 | } 165 | #ifndef LAZY_FILE_LOAD 166 | else { 167 | wbFile_setDataOffset(file, 0); 168 | } 169 | #endif 170 | 171 | return; 172 | } 173 | 174 | size_t wbFile_size(wbFile_t file) { 175 | size_t len; 176 | FILE *handle; 177 | 178 | if (file == nullptr) { 179 | return 0; 180 | } 181 | #ifndef LAZY_FILE_LOAD 182 | if (wbFile_getData(file) != nullptr) { 183 | if (wbFile_getLength(file) == 0) { 184 | wbFile_setLength(file, strlen(wbFile_getData(file))); 185 | } 186 | return wbFile_getLength(file); 187 | } 188 | #endif /* LAZY_FILE_LOAD */ 189 | 190 | handle = wbFile_getFileHandle(file); 191 | 192 | fseek(handle, 0, SEEK_END); 193 | len = ftell(handle); 194 | rewind(handle); 195 | 196 | return len; 197 | } 198 | 199 | char *wbFile_read(wbFile_t file) { 200 | size_t len; 201 | 202 | if (file == nullptr) { 203 | return NULL; 204 | } 205 | 206 | len = wbFile_size(file); 207 | 208 | if (len == 0) { 209 | return NULL; 210 | } 211 | 212 | wbFile_setLength(file, len); 213 | 214 | return wbFile_read(file, len); 215 | } 216 | 217 | #define MAX_CHARS_PER_LINE (1 << 17) 218 | 219 | static char buffer[MAX_CHARS_PER_LINE]; 220 | 221 | char *wbFile_readLine(wbFile_t file) { 222 | if (file == nullptr) { 223 | return NULL; 224 | } 225 | #ifdef LAZY_FILE_LOAD 226 | FILE *handle; 227 | memset(buffer, 0, MAX_CHARS_PER_LINE); 228 | 229 | handle = wbFile_getFileHandle(file); 230 | 231 | if (fgets(buffer, MAX_CHARS_PER_LINE - 1, handle)) { 232 | return buffer; 233 | } else { 234 | // wbLog(ERROR, "Was not able to read line from ", 235 | // wbFile_getFileName(file)); 236 | return NULL; 237 | } 238 | #else 239 | size_t newOffset; 240 | size_t lenToNewLine = 0; 241 | const char *tmp; 242 | 243 | if (wbFile_getData(file) == nullptr) { 244 | wbFile_setData(file, wbFile_read(file)); 245 | fclose(wbFile_getFileHandle(file)); 246 | wbFile_setFileHandle(file, NULL); 247 | wbFile_setDataOffset(file, 0); 248 | wbFile_setLength(file, strlen(wbFile_getData(file))); 249 | } 250 | 251 | memset(buffer, 0, MAX_CHARS_PER_LINE); 252 | 253 | if (wbFile_getDataOffset(file) >= wbFile_getLength(file)) { 254 | return NULL; 255 | } 256 | 257 | newOffset = wbFile_getDataOffset(file); 258 | tmp = wbFile_getData(file) + wbFile_getDataOffset(file); 259 | while (newOffset < wbFile_getLength(file) && *tmp != '\n') { 260 | tmp++; 261 | lenToNewLine++; 262 | newOffset++; 263 | } 264 | 265 | memcpy(buffer, wbFile_getData(file) + wbFile_getDataOffset(file), 266 | lenToNewLine); 267 | wbFile_setDataOffset(file, newOffset + 1); 268 | 269 | return buffer; 270 | #endif 271 | } 272 | 273 | void wbFile_write(wbFile_t file, const void *buffer, size_t size, 274 | size_t count) { 275 | size_t res; 276 | FILE *handle; 277 | 278 | if (file == nullptr) { 279 | return; 280 | } 281 | 282 | handle = wbFile_getFileHandle(file); 283 | 284 | res = fwrite(buffer, size, count, handle); 285 | if (res != count) { 286 | wbLog(ERROR, "Failed to write data to ", wbFile_getFileName(file)); 287 | } 288 | 289 | return; 290 | } 291 | 292 | void wbFile_write(wbFile_t file, const void *buffer, size_t len) { 293 | wbFile_write(file, buffer, sizeof(char), len); 294 | return; 295 | } 296 | 297 | void wbFile_write(wbFile_t file, const char *buffer) { 298 | size_t len; 299 | 300 | len = strlen(buffer); 301 | wbFile_write(file, buffer, len); 302 | 303 | return; 304 | } 305 | 306 | void wbFile_writeLine(wbFile_t file, const char *buffer0) { 307 | string buffer = wbString(buffer0, "\n"); 308 | wbFile_write(file, buffer.c_str()); 309 | } 310 | 311 | void wbFile_write(wbFile_t file, string buffer) { 312 | wbFile_write(file, buffer.c_str()); 313 | } 314 | 315 | void wbFile_writeLine(wbFile_t file, string buffer0) { 316 | string buffer = buffer0 + "\n"; 317 | wbFile_write(file, buffer.c_str()); 318 | } 319 | 320 | wbBool wbFile_existsQ(const char *path) { 321 | if (path == nullptr) { 322 | return wbFalse; 323 | } else { 324 | FILE *file = fopen(path, "r"); 325 | if (file != nullptr) { 326 | fclose(file); 327 | return wbTrue; 328 | } 329 | return wbFalse; 330 | } 331 | } 332 | 333 | char *wbFile_extension(const char *file) { 334 | char *extension; 335 | char *extensionLower; 336 | char *end; 337 | size_t len; 338 | 339 | len = strlen(file); 340 | end = (char *)&file[len - 1]; 341 | while (*end != '.') { 342 | end--; 343 | } 344 | if (*end == '.') { 345 | end++; 346 | } 347 | 348 | extension = wbString_duplicate(end); 349 | extensionLower = wbString_toLower(extension); 350 | wbDelete(extension); 351 | 352 | return extensionLower; 353 | } 354 | -------------------------------------------------------------------------------- /wbLogger.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | wbLogger_t _logger = nullptr; 5 | 6 | static inline wbBool wbLogEntry_hasNext(wbLogEntry_t elem) { 7 | return wbLogEntry_getNext(elem) != nullptr; 8 | } 9 | 10 | static inline wbLogEntry_t wbLogEntry_new() { 11 | wbLogEntry_t elem; 12 | 13 | elem = wbNew(struct st_wbLogEntry_t); 14 | 15 | wbLogEntry_setId(elem, uuid()); 16 | wbLogEntry_setSessionId(elem, sessionId()); 17 | wbLogEntry_setMessage(elem, NULL); 18 | wbLogEntry_setMPIRank(elem, wbMPI_getRank()); 19 | wbLogEntry_setTime(elem, _hrtime()); 20 | 21 | wbLogEntry_setLevel(elem, wbLogLevel_TRACE); 22 | 23 | wbLogEntry_setNext(elem, NULL); 24 | 25 | wbLogEntry_setLine(elem, -1); 26 | wbLogEntry_setFile(elem, NULL); 27 | wbLogEntry_setFunction(elem, NULL); 28 | 29 | return elem; 30 | } 31 | 32 | static inline wbLogEntry_t 33 | wbLogEntry_initialize(wbLogLevel_t level, string msg, const char *file, 34 | const char *fun, int line) { 35 | wbLogEntry_t elem; 36 | 37 | elem = wbLogEntry_new(); 38 | 39 | wbLogEntry_setLevel(elem, level); 40 | 41 | wbLogEntry_setMessage(elem, wbString_duplicate(msg)); 42 | 43 | wbLogEntry_setLine(elem, line); 44 | wbLogEntry_setFile(elem, file); 45 | wbLogEntry_setFunction(elem, fun); 46 | 47 | return elem; 48 | } 49 | 50 | static inline void wbLogEntry_delete(wbLogEntry_t elem) { 51 | if (elem != nullptr) { 52 | if (wbLogEntry_getMessage(elem) != nullptr) { 53 | wbFree(wbLogEntry_getMessage(elem)); 54 | } 55 | wbDelete(elem); 56 | } 57 | return; 58 | } 59 | 60 | static inline const char *getLevelName(wbLogLevel_t level) { 61 | switch (level) { 62 | case wbLogLevel_unknown: 63 | return "Unknown"; 64 | case wbLogLevel_OFF: 65 | return "Off"; 66 | case wbLogLevel_FATAL: 67 | return "Fatal"; 68 | case wbLogLevel_ERROR: 69 | return "Error"; 70 | case wbLogLevel_WARN: 71 | return "Warn"; 72 | case wbLogLevel_INFO: 73 | return "Info"; 74 | case wbLogLevel_DEBUG: 75 | return "Debug"; 76 | case wbLogLevel_TRACE: 77 | return "Trace"; 78 | } 79 | return NULL; 80 | } 81 | 82 | static inline json11::Json wbLogEntry_toJSONObject(wbLogEntry_t elem) { 83 | if (elem == nullptr) { 84 | return json11::Json{}; 85 | } 86 | json11::Json json = json11::Json::object{ 87 | {"id", wbLogEntry_getId(elem)}, 88 | {"session_id", wbLogEntry_getSessionId(elem)}, 89 | {"mpi_rank", wbLogEntry_getMPIRank(elem)}, 90 | {"level", getLevelName(wbLogEntry_getLevel(elem))}, 91 | {"file", wbLogEntry_getFile(elem)}, 92 | {"function", wbLogEntry_getFunction(elem)}, 93 | {"line", wbLogEntry_getLine(elem)}, 94 | {"time", wbLogEntry_getTime(elem)}, 95 | {"message", wbLogEntry_getMessage(elem)}, 96 | }; 97 | return json; 98 | } 99 | 100 | static inline string wbLogEntry_toJSON(wbLogEntry_t elem) { 101 | if (elem == NULL) { 102 | return "\"\""; 103 | } else if (WB_USE_JSON11) { 104 | json11::Json json = wbLogEntry_toJSONObject(elem); 105 | return json.string_value(); 106 | } else { 107 | stringstream ss; 108 | 109 | ss << "{\n"; 110 | ss << wbString_quote("id") << ":" 111 | << wbString_quote(wbLogEntry_getId(elem)) << ",\n"; 112 | ss << wbString_quote("session_id") << ":" 113 | << wbString_quote(wbLogEntry_getSessionId(elem)) << ",\n"; 114 | ss << wbString_quote("mpi_rank") << ":" 115 | << wbString(wbLogEntry_getMPIRank(elem)) << ",\n"; 116 | ss << wbString_quote("level") << ":" 117 | << wbString_quote(getLevelName(wbLogEntry_getLevel(elem))) << ",\n"; 118 | ss << wbString_quote("message") << ":" 119 | << wbString_quote(wbLogEntry_getMessage(elem)) << ",\n"; 120 | ss << wbString_quote("file") << ":" 121 | << wbString_quote(wbLogEntry_getFile(elem)) << ",\n"; 122 | ss << wbString_quote("function") << ":" 123 | << wbString_quote(wbLogEntry_getFunction(elem)) << ",\n"; 124 | ss << wbString_quote("line") << ":" << wbLogEntry_getLine(elem) 125 | << ",\n"; 126 | ss << wbString_quote("time") << ":" << wbLogEntry_getTime(elem) 127 | << "\n"; 128 | ss << "}"; 129 | 130 | return ss.str(); 131 | } 132 | return ""; 133 | } 134 | 135 | static inline string wbLogEntry_toXML(wbLogEntry_t elem) { 136 | if (elem != nullptr) { 137 | stringstream ss; 138 | 139 | ss << "\n"; 140 | ss << "" 141 | << "LoggerElement" 142 | << "\n"; 143 | ss << "" << wbLogEntry_getId(elem) << "\n"; 144 | ss << "" << wbLogEntry_getSessionId(elem) 145 | << "\n"; 146 | ss << "" << wbLogEntry_getLevel(elem) << "\n"; 147 | ss << "" << wbLogEntry_getMessage(elem) << "\n"; 148 | ss << "" << wbLogEntry_getFile(elem) << "\n"; 149 | ss << "" << wbLogEntry_getFunction(elem) << "\n"; 150 | ss << "" << wbLogEntry_getLine(elem) << "\n"; 151 | ss << "\n"; 152 | ss << "\n"; 153 | 154 | return ss.str(); 155 | } 156 | return ""; 157 | } 158 | 159 | wbLogger_t wbLogger_new() { 160 | wbLogger_t logger; 161 | 162 | logger = wbNew(struct st_wbLogger_t); 163 | 164 | wbLogger_setId(logger, uuid()); 165 | wbLogger_setSessionId(logger, sessionId()); 166 | wbLogger_setLength(logger, 0); 167 | wbLogger_setHead(logger, NULL); 168 | 169 | wbLogger_getLevel(logger) = wbLogLevel_TRACE; 170 | 171 | return logger; 172 | } 173 | 174 | static inline void _wbLogger_setLevel(wbLogger_t logger, 175 | wbLogLevel_t level) { 176 | wbLogger_getLevel(logger) = level; 177 | } 178 | 179 | static inline void _wbLogger_setLevel(wbLogLevel_t level) { 180 | _wbLogger_setLevel(_logger, level); 181 | } 182 | 183 | #define wbLogger_setLevel(level) _wbLogger_setLevel(wbLogLevel_##level) 184 | 185 | void wbLogger_clear(wbLogger_t logger) { 186 | if (logger != nullptr) { 187 | wbLogEntry_t tmp; 188 | wbLogEntry_t iter; 189 | 190 | iter = wbLogger_getHead(logger); 191 | while (iter != nullptr) { 192 | tmp = wbLogEntry_getNext(iter); 193 | wbLogEntry_delete(iter); 194 | iter = tmp; 195 | } 196 | 197 | wbLogger_setLength(logger, 0); 198 | wbLogger_setHead(logger, NULL); 199 | } 200 | } 201 | 202 | void wbLogger_delete(wbLogger_t logger) { 203 | if (logger != nullptr) { 204 | wbLogger_clear(logger); 205 | wbDelete(logger); 206 | } 207 | return; 208 | } 209 | 210 | void wbLogger_append(wbLogLevel_t level, string msg, const char *file, 211 | const char *fun, int line) { 212 | wbLogEntry_t elem; 213 | wbLogger_t logger; 214 | 215 | wb_init(NULL, NULL); 216 | 217 | logger = _logger; 218 | 219 | if (wbLogger_getLevel(logger) < level) { 220 | return; 221 | } 222 | 223 | elem = wbLogEntry_initialize(level, msg, file, fun, line); 224 | 225 | #ifdef wbLogger_printOnLog 226 | if (wbLogger_printOnLog) { 227 | if (level <= wbLogger_getLevel(logger) && elem) { 228 | json11::Json json = json11::Json::object{ 229 | {"type", "logger"}, 230 | {"id", wbLogEntry_getId(elem)}, 231 | {"session_id", wbLogEntry_getSessionId(elem)}, 232 | {"data", wbLogEntry_toJSONObject(elem)}}; 233 | std::cout << json.dump() << std::endl; 234 | } 235 | } 236 | #endif /* wbLogger_printOnLog */ 237 | 238 | if (wbLogger_getHead(logger) == nullptr) { 239 | wbLogger_setHead(logger, elem); 240 | } else { 241 | wbLogEntry_t prev = wbLogger_getHead(logger); 242 | 243 | while (wbLogEntry_hasNext(prev)) { 244 | prev = wbLogEntry_getNext(prev); 245 | } 246 | wbLogEntry_setNext(prev, elem); 247 | } 248 | 249 | #if 0 250 | if (level <= wbLogger_getLevel(logger) && elem) { 251 | const char *levelName = getLevelName(level); 252 | 253 | fprintf(stderr, "= LOG: %s: %s (In %s:%s on line %d). =\n", levelName, 254 | wbLogEntry_getMessage(elem), wbLogEntry_getFile(elem), 255 | wbLogEntry_getFunction(elem), wbLogEntry_getLine(elem)); 256 | } 257 | #endif 258 | 259 | wbLogger_incrementLength(logger); 260 | 261 | #ifndef JSON_OUTPUT 262 | printf("%s\n",wbLogEntry_getMessage(elem)); 263 | #endif /* JSON_OUTPUT */ 264 | 265 | return; 266 | } 267 | 268 | string wbLogger_toJSON() { 269 | return wbLogger_toJSON(_logger); 270 | } 271 | 272 | static json11::Json wbLogger_toJSONObject(wbLogger_t logger) { 273 | std::vector elems{}; 274 | 275 | if (logger != nullptr) { 276 | wbLogEntry_t iter; 277 | stringstream ss; 278 | 279 | for (iter = wbLogger_getHead(logger); iter != nullptr; 280 | iter = wbLogEntry_getNext(iter)) { 281 | elems.push_back(wbLogEntry_toJSONObject(iter)); 282 | } 283 | } 284 | return json11::Json(elems); 285 | } 286 | 287 | string wbLogger_toJSON(wbLogger_t logger) { 288 | if (logger != nullptr) { 289 | wbLogEntry_t iter; 290 | stringstream ss; 291 | 292 | for (iter = wbLogger_getHead(logger); iter != nullptr; 293 | iter = wbLogEntry_getNext(iter)) { 294 | ss << wbLogEntry_toJSON(iter); 295 | if (wbLogEntry_getNext(iter) != nullptr) { 296 | ss << ",\n"; 297 | } 298 | } 299 | 300 | return ss.str(); 301 | } 302 | return ""; 303 | } 304 | 305 | string wbLogger_toXML() { 306 | return wbLogger_toXML(_logger); 307 | } 308 | 309 | string wbLogger_toXML(wbLogger_t logger) { 310 | if (logger != nullptr) { 311 | wbLogEntry_t iter; 312 | stringstream ss; 313 | 314 | ss << "\n"; 315 | ss << "" 316 | << "Logger" 317 | << "\n"; 318 | ss << "" << wbLogger_getId(logger) << "\n"; 319 | ss << "" << wbLogger_getSessionId(logger) 320 | << "\n"; 321 | ss << "\n"; 322 | for (iter = wbLogger_getHead(logger); iter != nullptr; 323 | iter = wbLogEntry_getNext(iter)) { 324 | ss << wbLogEntry_toXML(iter); 325 | } 326 | ss << "\n"; 327 | ss << "\n"; 328 | 329 | return ss.str(); 330 | } 331 | return ""; 332 | } 333 | -------------------------------------------------------------------------------- /vendor/json11.hpp: -------------------------------------------------------------------------------- 1 | /* json11 2 | * 3 | * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization. 4 | * 5 | * The core object provided by the library is json11::Json. A Json object represents any JSON 6 | * value: null, bool, number (int or double), string (std::string), array (std::vector), or 7 | * object (std::map). 8 | * 9 | * Json objects act like values: they can be assigned, copied, moved, compared for equality or 10 | * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and 11 | * Json::parse (static) to parse a std::string as a Json object. 12 | * 13 | * Internally, the various types of Json object are represented by the JsonValue class 14 | * hierarchy. 15 | * 16 | * A note on numbers - JSON specifies the syntax of number formatting but not its semantics, 17 | * so some JSON implementations distinguish between integers and floating-point numbers, while 18 | * some don't. In json11, we choose the latter. Because some JSON implementations (namely 19 | * Javascript itself) treat all numbers as the same type, distinguishing the two leads 20 | * to JSON that will be *silently* changed by a round-trip through those implementations. 21 | * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also 22 | * provides integer helpers. 23 | * 24 | * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the 25 | * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64 26 | * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch 27 | * will be exact for +/- 275 years.) 28 | */ 29 | 30 | /* Copyright (c) 2013 Dropbox, Inc. 31 | * 32 | * Permission is hereby granted, free of charge, to any person obtaining a copy 33 | * of this software and associated documentation files (the "Software"), to deal 34 | * in the Software without restriction, including without limitation the rights 35 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 | * copies of the Software, and to permit persons to whom the Software is 37 | * furnished to do so, subject to the following conditions: 38 | * 39 | * The above copyright notice and this permission notice shall be included in 40 | * all copies or substantial portions of the Software. 41 | * 42 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 | * THE SOFTWARE. 49 | */ 50 | 51 | #pragma once 52 | 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | #ifdef _MSC_VER 60 | #if _MSC_VER <= 1800 // VS 2013 61 | #ifndef noexcept 62 | #define noexcept throw() 63 | #endif 64 | 65 | #ifndef snprintf 66 | #define snprintf _snprintf_s 67 | #endif 68 | #endif 69 | #endif 70 | 71 | namespace json11 { 72 | 73 | enum JsonParse { 74 | STANDARD, COMMENTS 75 | }; 76 | 77 | class JsonValue; 78 | 79 | class Json final { 80 | public: 81 | // Types 82 | enum Type { 83 | NUL, NUMBER, NUMBER64, UNUMBER64, BOOL, STRING, ARRAY, OBJECT 84 | }; 85 | 86 | // Array and object typedefs 87 | typedef std::vector array; 88 | typedef std::map object; 89 | 90 | // Constructors for the various types of JSON value. 91 | Json() noexcept; // NUL 92 | Json(std::nullptr_t) noexcept; // NUL 93 | Json(double value); // NUMBER 94 | Json(int value); // NUMBER 95 | Json(bool value); // BOOL 96 | Json(int64_t value); // NUMBER64 97 | Json(uint64_t value); // UNUMBER64 98 | Json(const std::string &value); // STRING 99 | Json(std::string &&value); // STRING 100 | Json(const char * value); // STRING 101 | Json(const array &values); // ARRAY 102 | Json(array &&values); // ARRAY 103 | Json(const object &values); // OBJECT 104 | Json(object &&values); // OBJECT 105 | 106 | // Implicit constructor: anything with a to_json() function. 107 | template 108 | Json(const T & t) : Json(t.to_json()) {} 109 | 110 | // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) 111 | template ::value 113 | && std::is_constructible::value, 114 | int>::type = 0> 115 | Json(const M & m) : Json(object(m.begin(), m.end())) {} 116 | 117 | // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) 118 | template ::value, 120 | int>::type = 0> 121 | Json(const V & v) : Json(array(v.begin(), v.end())) {} 122 | 123 | // This prevents Json(some_pointer) from accidentally producing a bool. Use 124 | // Json(bool(some_pointer)) if that behavior is desired. 125 | Json(void *) = delete; 126 | 127 | // Accessors 128 | Type type() const; 129 | 130 | bool is_null() const { return type() == NUL; } 131 | bool is_number() const { return type() == NUMBER; } 132 | bool is_number64() const { return type() == NUMBER64; } 133 | bool is_unumber64() const { return type() == UNUMBER64; } 134 | bool is_bool() const { return type() == BOOL; } 135 | bool is_string() const { return type() == STRING; } 136 | bool is_array() const { return type() == ARRAY; } 137 | bool is_object() const { return type() == OBJECT; } 138 | 139 | // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not 140 | // distinguish between integer and non-integer numbers - number_value() and int_value() 141 | // can both be applied to a NUMBER-typed object. 142 | double number_value() const; 143 | int int_value() const; 144 | int64_t int64_value() const; 145 | uint64_t uint64_value() const; 146 | 147 | 148 | // Return the enclosed value if this is a boolean, false otherwise. 149 | bool bool_value() const; 150 | // Return the enclosed string if this is a string, "" otherwise. 151 | const std::string &string_value() const; 152 | // Return the enclosed std::vector if this is an array, or an empty vector otherwise. 153 | const array &array_items() const; 154 | // Return the enclosed std::map if this is an object, or an empty map otherwise. 155 | const object &object_items() const; 156 | 157 | // Return a reference to arr[i] if this is an array, Json() otherwise. 158 | const Json & operator[](size_t i) const; 159 | // Return a reference to obj[key] if this is an object, Json() otherwise. 160 | const Json & operator[](const std::string &key) const; 161 | 162 | // Serialize. 163 | void dump(std::string &out) const; 164 | std::string dump() const { 165 | std::string out; 166 | dump(out); 167 | return out; 168 | } 169 | 170 | // Parse. If parse fails, return Json() and assign an error message to err. 171 | static Json parse(const std::string & in, 172 | std::string & err, 173 | JsonParse strategy = JsonParse::STANDARD); 174 | static Json parse(const char * in, 175 | std::string & err, 176 | JsonParse strategy = JsonParse::STANDARD) { 177 | if (in) { 178 | return parse(std::string(in), err, strategy); 179 | } else { 180 | err = "null input"; 181 | return nullptr; 182 | } 183 | } 184 | // Parse multiple objects, concatenated or separated by whitespace 185 | static std::vector parse_multi( 186 | const std::string & in, 187 | std::string::size_type & parser_stop_pos, 188 | std::string & err, 189 | JsonParse strategy = JsonParse::STANDARD); 190 | 191 | static inline std::vector parse_multi( 192 | const std::string & in, 193 | std::string & err, 194 | JsonParse strategy = JsonParse::STANDARD) { 195 | std::string::size_type parser_stop_pos; 196 | return parse_multi(in, parser_stop_pos, err, strategy); 197 | } 198 | 199 | bool operator== (const Json &rhs) const; 200 | bool operator< (const Json &rhs) const; 201 | bool operator!= (const Json &rhs) const { return !(*this == rhs); } 202 | bool operator<= (const Json &rhs) const { return !(rhs < *this); } 203 | bool operator> (const Json &rhs) const { return (rhs < *this); } 204 | bool operator>= (const Json &rhs) const { return !(*this < rhs); } 205 | 206 | /* has_shape(types, err) 207 | * 208 | * Return true if this is a JSON object and, for each item in types, has a field of 209 | * the given type. If not, return false and set err to a descriptive message. 210 | */ 211 | typedef std::initializer_list> shape; 212 | bool has_shape(const shape & types, std::string & err) const; 213 | 214 | private: 215 | std::shared_ptr m_ptr; 216 | }; 217 | 218 | // Internal class hierarchy - JsonValue objects are not exposed to users of this API. 219 | class JsonValue { 220 | protected: 221 | friend class Json; 222 | friend class JsonInt; 223 | friend class JsonInt64; 224 | friend class JsonUInt64; 225 | friend class JsonDouble; 226 | virtual Json::Type type() const = 0; 227 | virtual bool equals(const JsonValue * other) const = 0; 228 | virtual bool less(const JsonValue * other) const = 0; 229 | virtual void dump(std::string &out) const = 0; 230 | virtual double number_value() const; 231 | virtual int int_value() const; 232 | virtual int64_t int64_value() const; 233 | virtual uint64_t uint64_value() const; 234 | virtual bool bool_value() const; 235 | virtual const std::string &string_value() const; 236 | virtual const Json::array &array_items() const; 237 | virtual const Json &operator[](size_t i) const; 238 | virtual const Json::object &object_items() const; 239 | virtual const Json &operator[](const std::string &key) const; 240 | virtual ~JsonValue() {} 241 | }; 242 | 243 | } // namespace json11 -------------------------------------------------------------------------------- /wbMD5.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This code implements the MD5 message-digest algorithm. 4 | * The algorithm is due to Ron Rivest. This code was 5 | * written by Colin Plumb in 1993, no copyright is claimed. 6 | * This code is in the public domain; do with it what you wish. 7 | * 8 | * Equivalent code is available from RSA Data Security, Inc. 9 | * This code has been tested against that, and is equivalent, 10 | * except that you don't need to include two pages of legalese 11 | * with every copy. 12 | * 13 | * To compute the message digest of a chunk of bytes, declare an 14 | * MD5Context structure, pass it to MD5Init, call MD5Update as 15 | * needed on buffers full of bytes, and then call MD5Final, which 16 | * will fill a supplied 16-byte array with the digest. 17 | * 18 | * Changed so as no longer to depend on Colin Plumb's `usual.h' header 19 | * definitions; now uses stuff from dpkg's config.h. 20 | * - Ian Jackson . 21 | * Still in the public domain. 22 | */ 23 | 24 | #ifndef __WB_MD5_H__ 25 | #define __WB_MD5_H__ 26 | 27 | #include /* for memcpy() */ 28 | #include /* for stupid systems */ 29 | 30 | #define UWORD32 unsigned int 31 | 32 | #define md5byte unsigned char 33 | 34 | struct MD5Context { 35 | UWORD32 buf[4]; 36 | UWORD32 bytes[2]; 37 | UWORD32 in[16]; 38 | }; 39 | 40 | static void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]); 41 | 42 | static int g_bigEndian = 0; 43 | static int g_endianessDetected = 0; 44 | 45 | static void detectEndianess() { 46 | int nl = 0x12345678; 47 | short ns = 0x1234; 48 | 49 | unsigned char *p = (unsigned char *)(&nl); 50 | unsigned char *sp = (unsigned char *)(&ns); 51 | 52 | if (g_endianessDetected) 53 | return; 54 | if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78) { 55 | g_bigEndian = 1; 56 | } else if (p[0] == 0x78 && p[1] == 0x56 && p[2] == 0x34 && 57 | p[3] == 0x12) { 58 | g_bigEndian = 0; 59 | } else { 60 | g_bigEndian = *sp != 0x12; 61 | } 62 | 63 | g_endianessDetected = 1; 64 | } 65 | 66 | static void byteSwap(UWORD32 *buf, unsigned words) { 67 | md5byte *p; 68 | 69 | if (!g_bigEndian) 70 | return; 71 | 72 | p = (md5byte *)buf; 73 | 74 | do { 75 | *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 | 76 | ((unsigned)p[1] << 8 | p[0]); 77 | p += 4; 78 | } while (--words); 79 | } 80 | 81 | /* 82 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 83 | * initialization constants. 84 | */ 85 | static void MD5Init(struct MD5Context *ctx) { 86 | detectEndianess(); 87 | 88 | ctx->buf[0] = 0x67452301; 89 | ctx->buf[1] = 0xefcdab89; 90 | ctx->buf[2] = 0x98badcfe; 91 | ctx->buf[3] = 0x10325476; 92 | 93 | ctx->bytes[0] = 0; 94 | ctx->bytes[1] = 0; 95 | } 96 | 97 | /* 98 | * Update context to reflect the concatenation of another buffer full 99 | * of bytes. 100 | */ 101 | static void MD5Update(struct MD5Context *ctx, md5byte const *buf, 102 | unsigned len) { 103 | UWORD32 t; 104 | 105 | /* Update byte count */ 106 | 107 | t = ctx->bytes[0]; 108 | if ((ctx->bytes[0] = t + len) < t) 109 | ctx->bytes[1]++; /* Carry from low to high */ 110 | 111 | t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ 112 | if (t > len) { 113 | memcpy((md5byte *)ctx->in + 64 - t, buf, len); 114 | return; 115 | } 116 | /* First chunk is an odd size */ 117 | memcpy((md5byte *)ctx->in + 64 - t, buf, t); 118 | byteSwap(ctx->in, 16); 119 | MD5Transform(ctx->buf, ctx->in); 120 | buf += t; 121 | len -= t; 122 | 123 | /* Process data in 64-byte chunks */ 124 | while (len >= 64) { 125 | memcpy(ctx->in, buf, 64); 126 | byteSwap(ctx->in, 16); 127 | MD5Transform(ctx->buf, ctx->in); 128 | buf += 64; 129 | len -= 64; 130 | } 131 | 132 | /* Handle any remaining bytes of data. */ 133 | memcpy(ctx->in, buf, len); 134 | } 135 | 136 | /* 137 | * Final wrapup - pad to 64-byte boundary with the bit pattern 138 | * 1 0* (64-bit count of bits processed, MSB-first) 139 | */ 140 | static void MD5Final(md5byte digest[16], struct MD5Context *ctx) { 141 | int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ 142 | md5byte *p = (md5byte *)ctx->in + count; 143 | 144 | /* Set the first char of padding to 0x80. There is always room. */ 145 | *p++ = 0x80; 146 | 147 | /* Bytes of padding needed to make 56 bytes (-8..55) */ 148 | count = 56 - 1 - count; 149 | 150 | if (count < 0) { /* Padding forces an extra block */ 151 | memset(p, 0, count + 8); 152 | byteSwap(ctx->in, 16); 153 | MD5Transform(ctx->buf, ctx->in); 154 | p = (md5byte *)ctx->in; 155 | count = 56; 156 | } 157 | memset(p, 0, count); 158 | byteSwap(ctx->in, 14); 159 | 160 | /* Append length in bits and transform */ 161 | ctx->in[14] = ctx->bytes[0] << 3; 162 | ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; 163 | MD5Transform(ctx->buf, ctx->in); 164 | 165 | byteSwap(ctx->buf, 4); 166 | memcpy(digest, ctx->buf, 16); 167 | memset(&ctx, 0, sizeof(ctx)); /* In case it's sensitive */ 168 | } 169 | 170 | #ifndef ASM_MD5 171 | 172 | /* The four core functions - F1 is optimized somewhat */ 173 | 174 | /* #define F1(x, y, z) (x & y | ~x & z) */ 175 | #define F1(x, y, z) (z ^ (x & (y ^ z))) 176 | #define F2(x, y, z) F1(z, x, y) 177 | #define F3(x, y, z) (x ^ y ^ z) 178 | #define F4(x, y, z) (y ^ (x | ~z)) 179 | 180 | /* This is the central step in the MD5 algorithm. */ 181 | #define MD5STEP(f, w, x, y, z, in, s) \ 182 | (w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x) 183 | 184 | /* 185 | * The core of the MD5 algorithm, this alters an existing MD5 hash to 186 | * reflect the addition of 16 longwords of new data. MD5Update blocks 187 | * the data and converts bytes into longwords for this routine. 188 | */ 189 | static void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) { 190 | UWORD32 a, b, c, d; 191 | 192 | a = buf[0]; 193 | b = buf[1]; 194 | c = buf[2]; 195 | d = buf[3]; 196 | 197 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 198 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 199 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 200 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 201 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 202 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 203 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 204 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 205 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 206 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 207 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 208 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 209 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 210 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 211 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 212 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 213 | 214 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 215 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 216 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 217 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 218 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 219 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 220 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 221 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 222 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 223 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 224 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 225 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 226 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 227 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 228 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 229 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 230 | 231 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 232 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 233 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 234 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 235 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 236 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 237 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 238 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 239 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 240 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 241 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 242 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 243 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 244 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 245 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 246 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 247 | 248 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 249 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 250 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 251 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 252 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 253 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 254 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 255 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 256 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 257 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 258 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 259 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 260 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 261 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 262 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 263 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 264 | 265 | buf[0] += a; 266 | buf[1] += b; 267 | buf[2] += c; 268 | buf[3] += d; 269 | } 270 | 271 | #endif 272 | 273 | static void MD5_buffer(const unsigned char *buf, unsigned int len, 274 | unsigned char sig[16]) { 275 | struct MD5Context md5; 276 | MD5Init(&md5); 277 | MD5Update(&md5, buf, len); 278 | MD5Final(sig, &md5); 279 | } 280 | 281 | #define wbMD5 MD5_buffer 282 | 283 | #define HEX_STRING "0123456789abcdef" /* to convert to hex */ 284 | 285 | static void wbMD5_sigToString(unsigned char signature[16], char *str, 286 | int len) { 287 | unsigned char *sig_p; 288 | char *str_p, *max_p; 289 | unsigned int high, low; 290 | 291 | str_p = str; 292 | max_p = str + len; 293 | 294 | for (sig_p = (unsigned char *)signature; 295 | sig_p < (unsigned char *)signature + 16; sig_p++) { 296 | high = *sig_p / 16; 297 | low = *sig_p % 16; 298 | /* account for 2 chars */ 299 | if (str_p + 1 >= max_p) { 300 | break; 301 | } 302 | *str_p++ = HEX_STRING[high]; 303 | *str_p++ = HEX_STRING[low]; 304 | } 305 | /* account for 2 chars */ 306 | if (str_p < max_p) { 307 | *str_p++ = '\0'; 308 | } 309 | } 310 | 311 | #endif /* __WB_MD5_H__ */ 312 | -------------------------------------------------------------------------------- /wbSolution.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | char *solutionJSON = nullptr; 5 | static string _solution_correctQ(""); 6 | 7 | static void _onUnsameImageFunction(string str) { 8 | _solution_correctQ = str; 9 | } 10 | 11 | template 12 | static wbBool wbSolution_listCorrectQ(const char *expectedOutputFile, 13 | wbSolution_t sol, const char *type) { 14 | wbBool res; 15 | T *expectedData; 16 | int expectedRows, expectedColumns; 17 | 18 | expectedData = (T *)wbImport(expectedOutputFile, &expectedRows, 19 | &expectedColumns, type); 20 | 21 | if (expectedData == nullptr) { 22 | _solution_correctQ = "Failed to open expected output file."; 23 | res = wbFalse; 24 | } else if (expectedRows != wbSolution_getRows(sol)) { 25 | wbLog(TRACE, "Number of rows in the solution is ", 26 | wbSolution_getRows(sol), ". Expected number of rows is ", 27 | expectedRows, "."); 28 | _solution_correctQ = 29 | "The number of rows in the solution did not match " 30 | "that of the expected results."; 31 | res = wbFalse; 32 | } else if (expectedColumns != wbSolution_getColumns(sol)) { 33 | wbLog(TRACE, "Number of columns in the solution is ", 34 | wbSolution_getColumns(sol), ". Expected number of columns is ", 35 | expectedColumns, "."); 36 | _solution_correctQ = "The number of columns in the solution did not " 37 | "match that of the expected results."; 38 | res = wbFalse; 39 | } else { 40 | int ii, jj, idx; 41 | T *solutionData; 42 | 43 | solutionData = (T *)wbSolution_getData(sol); 44 | if (wbSolution_getType(sol) == "integral_vector/sorted") { 45 | wbSort(solutionData, expectedRows * expectedColumns); 46 | } 47 | 48 | for (ii = 0; ii < expectedRows; ii++) { 49 | for (jj = 0; jj < expectedColumns; jj++) { 50 | idx = ii * expectedColumns + jj; 51 | if (wbUnequalQ(expectedData[idx], solutionData[idx])) { 52 | string str; 53 | if (expectedColumns == 1) { 54 | str = wbString( 55 | "The solution did not match the expected results at row ", 56 | ii, ". Expecting ", expectedData[idx], " but got ", 57 | solutionData[idx], "."); 58 | } else { 59 | str = wbString("The solution did not match the expected " 60 | "results at column ", 61 | jj, " and row ", ii, ". Expecting ", 62 | expectedData[idx], " but got ", 63 | solutionData[idx], "."); 64 | } 65 | _solution_correctQ = str; 66 | res = wbFalse; 67 | goto matrixCleanup; 68 | } 69 | } 70 | } 71 | 72 | res = wbTrue; 73 | matrixCleanup: 74 | if (expectedData != nullptr) { 75 | wbFree(expectedData); 76 | } 77 | } 78 | return res; 79 | } 80 | 81 | static wbBool wbSolution_correctQ(char *expectedOutputFile, 82 | wbSolution_t sol) { 83 | if (expectedOutputFile == nullptr) { 84 | _solution_correctQ = "Failed to determined the expected output file."; 85 | return wbFalse; 86 | } else if (!wbFile_existsQ(expectedOutputFile)) { 87 | _solution_correctQ = 88 | wbString("The file ", expectedOutputFile, " does not exist."); 89 | return wbFalse; 90 | } else if (wbString_sameQ(wbSolution_getType(sol), "image")) { 91 | wbBool res; 92 | wbImage_t solutionImage = nullptr; 93 | wbImage_t expectedImage = wbImport(expectedOutputFile); 94 | if (expectedImage == nullptr) { 95 | _solution_correctQ = "Failed to open expected output file."; 96 | res = wbFalse; 97 | } else if (wbImage_getWidth(expectedImage) != 98 | wbSolution_getWidth(sol)) { 99 | _solution_correctQ = 100 | "The image width of the expected image does not " 101 | "match that of the solution."; 102 | res = wbFalse; 103 | } else if (wbImage_getHeight(expectedImage) != 104 | wbSolution_getHeight(sol)) { 105 | _solution_correctQ = 106 | "The image height of the expected image does not " 107 | "match that of the solution."; 108 | res = wbFalse; 109 | } else if (wbImage_getChannels(expectedImage) != 110 | wbSolution_getChannels(sol)) { 111 | _solution_correctQ = 112 | "The image channels of the expected image does not " 113 | "match that of the solution."; 114 | res = wbFalse; 115 | } else { 116 | solutionImage = (wbImage_t)wbSolution_getData(sol); 117 | wbAssert(solutionImage != nullptr); 118 | res = wbImage_sameQ(solutionImage, expectedImage, 119 | _onUnsameImageFunction); 120 | } 121 | if (expectedImage != nullptr) { 122 | wbImage_delete(expectedImage); 123 | } 124 | return res; 125 | } else if (wbString_sameQ(wbSolution_getType(sol), "histogram")) { 126 | return wbSolution_listCorrectQ(expectedOutputFile, sol, 127 | "Integer"); 128 | } else if (wbString_sameQ(wbSolution_getType(sol), "integral_vector/sorted") || 129 | wbString_sameQ(wbSolution_getType(sol), "integral_vector")) { 130 | return wbSolution_listCorrectQ(expectedOutputFile, sol, 131 | "Integer"); 132 | } else if (wbString_sameQ(wbSolution_getType(sol), "vector") || 133 | wbString_sameQ(wbSolution_getType(sol), "matrix")) { 134 | return wbSolution_listCorrectQ(expectedOutputFile, sol, 135 | "Real"); 136 | } else { 137 | wbAssert(wbFalse); 138 | return wbFalse; 139 | } 140 | } 141 | 142 | wbBool wbSolution(char *expectedOutputFile, char *outputFile, char *type0, 143 | void *data, int rows, int columns, int depth) { 144 | char *type; 145 | wbBool res; 146 | wbSolution_t sol; 147 | 148 | if (expectedOutputFile == nullptr || data == nullptr || type0 == nullptr) { 149 | wbLog(ERROR, "Failed to grade solution"); 150 | return wbFalse; 151 | } 152 | 153 | type = wbString_toLower(type0); 154 | 155 | if (_solution_correctQ != "") { 156 | _solution_correctQ = ""; 157 | } 158 | 159 | wbSolution_setOutputFile(sol, outputFile); 160 | wbSolution_setId(sol, uuid()); 161 | wbSolution_setSessionId(sol, sessionId()); 162 | wbSolution_setType(sol, type); 163 | wbSolution_setData(sol, data); 164 | wbSolution_setRows(sol, rows); 165 | wbSolution_setColumns(sol, columns); 166 | wbSolution_setDepth(sol, depth); 167 | 168 | res = wbSolution_correctQ(expectedOutputFile, sol); 169 | 170 | if (outputFile != nullptr) { 171 | if (wbString_sameQ(type, "image")) { 172 | wbImage_t inputImage = (wbImage_t)data; 173 | wbImage_t img = wbImage_new(wbImage_getWidth(inputImage), 174 | wbImage_getHeight(inputImage), 175 | wbImage_getChannels(inputImage)); 176 | memcpy(wbImage_getData(img), wbImage_getData(inputImage), 177 | rows * columns * depth * sizeof(wbReal_t)); 178 | wbExport(outputFile, img); 179 | wbImage_delete(img); 180 | } else if (wbString_sameQ(type, "integral_vector/sort")) { 181 | wbSort((int *)data, rows*columns); 182 | wbExport(outputFile, (int *)data, rows, columns); 183 | } else if (wbString_sameQ(type, "integral_vector")) { 184 | wbExport(outputFile, (int *)data, rows, columns); 185 | } else if (wbString_sameQ(type, "vector") || 186 | wbString_sameQ(type, "matrix")) { 187 | wbExport(outputFile, (wbReal_t *)data, rows, columns); 188 | } else if (wbString_sameQ(type, "histogram")) { 189 | wbExport(outputFile, (unsigned char *)data, rows, columns); 190 | } else if (wbString_sameQ(type, "text")) { 191 | wbExport_text(outputFile, (unsigned char *)data, rows * columns); 192 | } 193 | } 194 | 195 | wbFree(type); 196 | 197 | return res; 198 | } 199 | 200 | wbBool wbSolution(char *expectedOutputFile, char *outputFile, char *type0, 201 | void *data, int rows, int columns) { 202 | return wbSolution(expectedOutputFile, outputFile, type0, data, rows, 203 | columns, 1); 204 | } 205 | 206 | wbBool wbSolution(wbArg_t arg, void *data, int rows, int columns, 207 | int depth) { 208 | char *type; 209 | wbBool res; 210 | char *expectedOutputFile; 211 | char *outputFile; 212 | stringstream ss; 213 | 214 | expectedOutputFile = wbArg_getExpectedOutputFile(arg); 215 | outputFile = wbArg_getOutputFile(arg); 216 | type = wbArg_getType(arg); 217 | 218 | wbAssert(type != nullptr); 219 | wbAssert(expectedOutputFile != nullptr); 220 | wbAssert(outputFile != nullptr); 221 | 222 | res = wbSolution(expectedOutputFile, outputFile, type, data, rows, 223 | columns, depth); 224 | 225 | if (WB_USE_JSON11) { 226 | json11::Json json; 227 | if (res) { 228 | #ifndef JSON_OUTPUT 229 | printf("The solution is correct\n"); 230 | #endif 231 | json = json11::Json::object{{"correctq", true}, 232 | {"message", "The solution is correct"}}; 233 | } else { 234 | #ifndef JSON_OUTPUT 235 | printf("The solution is NOT correct\n"); 236 | #endif 237 | json = json11::Json::object{{"correctq", false}, 238 | {"message", _solution_correctQ}}; 239 | } 240 | 241 | #ifdef wbLogger_printOnLog 242 | if (wbLogger_printOnLog) { 243 | json11::Json e = 244 | json11::Json::object{{"type", "solution"}, {"data", json}}; 245 | std::cout << e.dump() << std::endl; 246 | } 247 | #endif /* wbLogger_printOnLog */ 248 | 249 | solutionJSON = wbString_duplicate(json.string_value()); 250 | } else { 251 | if (res) { 252 | #ifndef JSON_OUTPUT 253 | printf("Solution is correct\n"); 254 | #endif 255 | ss << "{\n"; 256 | ss << wbString_quote("correctq") << ": true,\n"; 257 | ss << wbString_quote("message") << ": " 258 | << wbString_quote("Solution is correct.") << "\n"; 259 | ss << "}"; 260 | } else { 261 | #ifndef JSON_OUTPUT 262 | printf("Solution is NOT correct\n"); 263 | #endif 264 | ss << "{\n"; 265 | ss << wbString_quote("correctq") << ": false,\n"; 266 | ss << wbString_quote("message") << ": " 267 | << wbString_quote(_solution_correctQ) << "\n"; 268 | ss << "}"; 269 | } 270 | solutionJSON = wbString_duplicate(ss.str()); 271 | } 272 | 273 | return res; 274 | } 275 | 276 | wbBool wbSolution(wbArg_t arg, void *data, int rows, int columns) { 277 | return wbSolution(arg, data, rows, columns, 1); 278 | } 279 | 280 | EXTERN_C wbBool wbSolution(wbArg_t arg, void *data, int rows) { 281 | return wbSolution(arg, data, rows, 1); 282 | } 283 | 284 | wbBool wbSolution(wbArg_t arg, wbImage_t img) { 285 | return wbSolution(arg, img, wbImage_getHeight(img), 286 | wbImage_getWidth(img), wbImage_getChannels(img)); 287 | } 288 | -------------------------------------------------------------------------------- /wbString.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __WB_STRING_H__ 4 | #define __WB_STRING_H__ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "wb.h" 13 | 14 | using std::string; 15 | using std::vector; 16 | using std::stringstream; 17 | using std::exception; 18 | 19 | template 20 | static inline string wbString(const T &x); 21 | 22 | static inline void wbString_replace(string &value, string const &search, 23 | string const &replace) { 24 | for (string::size_type next = value.find(search); next != string::npos; 25 | next = value.find(search, next)) { 26 | value.replace(next, search.length(), replace); 27 | next += replace.length(); 28 | } 29 | } 30 | 31 | static inline string wbString_quote(string str) { 32 | string s = str; 33 | wbString_replace(s, "\\", "\\\\"); 34 | s = "\"" + s + "\""; 35 | return s; 36 | } 37 | 38 | static inline string wbString_quote(const char *str) { 39 | if (str == nullptr) { 40 | return wbString_quote(""); 41 | } else { 42 | return wbString_quote(string(str)); 43 | } 44 | } 45 | 46 | static inline char *wbString_duplicate(const char *str) { 47 | if (str == nullptr) { 48 | return NULL; 49 | } else { 50 | char *newstr; 51 | size_t len = strlen(str); 52 | newstr = wbNewArray(char, len + 1); 53 | memcpy(newstr, str, len * sizeof(char)); 54 | newstr[len] = '\0'; 55 | return newstr; 56 | } 57 | } 58 | 59 | static inline char *wbString_duplicate(std::string str) { 60 | return wbString_duplicate(str.c_str()); 61 | } 62 | 63 | static inline string wbString(void) { 64 | string s = ""; 65 | return s; 66 | } 67 | 68 | template 69 | static inline string wbString(const T &x) { 70 | try { 71 | stringstream ss; 72 | ss << x; 73 | return ss.str(); 74 | } catch (exception &e) { 75 | return string(); 76 | } 77 | } 78 | 79 | template <> 80 | inline string wbString(const bool &x) { 81 | return x ? "True" : "False"; 82 | } 83 | 84 | template <> 85 | inline string wbString(const vector &x) { 86 | stringstream ss; 87 | ss << "{"; 88 | for (size_t ii = 0; ii < x.size(); ii++) { 89 | ss << wbString_quote(x[ii]); 90 | if (ii != x.size() - 1) { 91 | ss << ", "; 92 | } 93 | } 94 | ss << "}"; 95 | 96 | return ss.str(); 97 | } 98 | 99 | template <> 100 | inline string wbString(const vector &x) { 101 | stringstream ss; 102 | ss << "{"; 103 | for (size_t ii = 0; ii < x.size(); ii++) { 104 | ss << x[ii]; 105 | if (ii != x.size() - 1) { 106 | ss << ", "; 107 | } 108 | } 109 | ss << "}"; 110 | 111 | return ss.str(); 112 | } 113 | 114 | template <> 115 | inline string wbString(const vector &x) { 116 | stringstream ss; 117 | ss << "{"; 118 | for (size_t ii = 0; ii < x.size(); ii++) { 119 | ss << x[ii]; 120 | if (ii != x.size() - 1) { 121 | ss << ", "; 122 | } 123 | } 124 | ss << "}"; 125 | 126 | return ss.str(); 127 | } 128 | 129 | template 130 | static inline string wbString(const T0 &x0, const T1 &x1) { 131 | stringstream ss; 132 | ss << wbString(x0) << wbString(x1); 133 | 134 | return ss.str(); 135 | } 136 | 137 | template 138 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2) { 139 | stringstream ss; 140 | ss << wbString(x0) << wbString(x1) << wbString(x2); 141 | return ss.str(); 142 | } 143 | 144 | template 145 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 146 | const T3 &x3) { 147 | stringstream ss; 148 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3); 149 | 150 | return ss.str(); 151 | } 152 | 153 | template 154 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 155 | const T3 &x3, const T4 &x4) { 156 | stringstream ss; 157 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 158 | << wbString(x4); 159 | 160 | return ss.str(); 161 | } 162 | 163 | template 165 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 166 | const T3 &x3, const T4 &x4, const T5 &x5) { 167 | stringstream ss; 168 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 169 | << wbString(x4) << wbString(x5); 170 | 171 | return ss.str(); 172 | } 173 | 174 | template 176 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 177 | const T3 &x3, const T4 &x4, const T5 &x5, 178 | const T6 &x6) { 179 | stringstream ss; 180 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 181 | << wbString(x4) << wbString(x5) << wbString(x6); 182 | 183 | return ss.str(); 184 | } 185 | 186 | template 188 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 189 | const T3 &x3, const T4 &x4, const T5 &x5, 190 | const T6 &x6, const T7 &x7) { 191 | stringstream ss; 192 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 193 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7); 194 | 195 | return ss.str(); 196 | } 197 | 198 | template 200 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 201 | const T3 &x3, const T4 &x4, const T5 &x5, 202 | const T6 &x6, const T7 &x7, const T8 &x8) { 203 | stringstream ss; 204 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 205 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7) 206 | << wbString(x8); 207 | 208 | return ss.str(); 209 | } 210 | 211 | template 213 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 214 | const T3 &x3, const T4 &x4, const T5 &x5, 215 | const T6 &x6, const T7 &x7, const T8 &x8, 216 | const T9 &x9) { 217 | stringstream ss; 218 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 219 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7) 220 | << wbString(x8) << wbString(x9); 221 | 222 | return ss.str(); 223 | } 224 | 225 | template 228 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 229 | const T3 &x3, const T4 &x4, const T5 &x5, 230 | const T6 &x6, const T7 &x7, const T8 &x8, 231 | const T9 &x9, const T10 &x10) { 232 | stringstream ss; 233 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 234 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7) 235 | << wbString(x8) << wbString(x9) << wbString(x10); 236 | 237 | return ss.str(); 238 | } 239 | 240 | template 243 | static inline string 244 | wbString(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, 245 | const T4 &x4, const T5 &x5, const T6 &x6, const T7 &x7, 246 | const T8 &x8, const T9 &x9, const T10 &x10, const T11 &x11) { 247 | stringstream ss; 248 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 249 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7) 250 | << wbString(x8) << wbString(x9) << wbString(x10) << wbString(x11); 251 | 252 | return ss.str(); 253 | } 254 | 255 | template 258 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 259 | const T3 &x3, const T4 &x4, const T5 &x5, 260 | const T6 &x6, const T7 &x7, const T8 &x8, 261 | const T9 &x9, const T10 &x10, const T11 &x11, 262 | const T12 &x12) { 263 | stringstream ss; 264 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 265 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7) 266 | << wbString(x8) << wbString(x9) << wbString(x10) << wbString(x11) 267 | << wbString(x12); 268 | return ss.str(); 269 | } 270 | 271 | template 274 | static inline string wbString(const T0 &x0, const T1 &x1, const T2 &x2, 275 | const T3 &x3, const T4 &x4, const T5 &x5, 276 | const T6 &x6, const T7 &x7, const T8 &x8, 277 | const T9 &x9, const T10 &x10, const T11 &x11, 278 | const T12 &x12, const T13 &x13) { 279 | stringstream ss; 280 | ss << wbString(x0) << wbString(x1) << wbString(x2) << wbString(x3) 281 | << wbString(x4) << wbString(x5) << wbString(x6) << wbString(x7) 282 | << wbString(x8) << wbString(x9) << wbString(x10) << wbString(x11) 283 | << wbString(x12) << wbString(x13); 284 | return ss.str(); 285 | } 286 | 287 | template 288 | static inline wbBool wbString_sameQ(const X &x, const Y &y) { 289 | string xs = wbString(x); 290 | string ys = wbString(y); 291 | return strcmp(xs.c_str(), ys.c_str()) == 0; 292 | } 293 | 294 | static inline wbBool wbString_sameQ(const string &x, const string &y) { 295 | return x.compare(y) == 0; 296 | } 297 | 298 | static inline char *wbString_toLower(const char *str) { 299 | if (str == nullptr) { 300 | return NULL; 301 | } else { 302 | char *res, *iter; 303 | 304 | res = iter = wbString_duplicate(str); 305 | while (*iter != '\0') { 306 | *iter++ = tolower(*str++); 307 | } 308 | return res; 309 | } 310 | } 311 | 312 | static inline wbBool wbString_startsWith(const char *str, 313 | const char *prefix) { 314 | while (*prefix != '\0') { 315 | if (*str == '\0' || *str != *prefix) { 316 | return wbFalse; 317 | } 318 | str++; 319 | prefix++; 320 | } 321 | return wbTrue; 322 | } 323 | 324 | #endif /* __WB_STRING_H__ */ 325 | -------------------------------------------------------------------------------- /wbExport.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "wb.h" 3 | 4 | static inline void wbExportText_setFile(wbExportText_t text, 5 | const char *path) { 6 | if (text != nullptr) { 7 | if (wbExportText_getFile(text) != nullptr) { 8 | wbFile_delete(wbExportText_getFile(text)); 9 | } 10 | if (path != nullptr) { 11 | wbExportText_getFile(text) = wbFile_open(path, "w+"); 12 | } else { 13 | wbExportText_getFile(text) = nullptr; 14 | } 15 | } 16 | 17 | return; 18 | } 19 | 20 | static inline wbExportText_t wbExportText_new(void) { 21 | wbExportText_t text; 22 | 23 | text = wbNew(struct st_wbExportText_t); 24 | 25 | wbExportText_getFile(text) = nullptr; 26 | wbExportText_setLength(text, -1); 27 | 28 | return text; 29 | } 30 | 31 | static inline void wbExportText_delete(wbExportText_t text) { 32 | if (text != nullptr) { 33 | wbExportText_setFile(text, NULL); 34 | wbDelete(text); 35 | } 36 | return; 37 | } 38 | 39 | static inline void wbExportText_write(wbExportText_t text, 40 | const char *data, int length) { 41 | int ii; 42 | FILE *handle; 43 | wbFile_t file; 44 | 45 | if (text == nullptr || wbExportText_getFile(text) == nullptr) { 46 | return; 47 | } 48 | 49 | file = wbExportText_getFile(text); 50 | 51 | handle = wbFile_getFileHandle(file); 52 | 53 | if (handle == nullptr) { 54 | return; 55 | } 56 | 57 | for (ii = 0; ii < length; ii++) { 58 | fprintf(handle, "%c", data[ii]); 59 | } 60 | 61 | return; 62 | } 63 | 64 | static inline void wbExportRaw_setFile(wbExportRaw_t raw, 65 | const char *path) { 66 | if (raw != nullptr) { 67 | if (wbExportRaw_getFile(raw) != nullptr) { 68 | wbFile_delete(wbExportRaw_getFile(raw)); 69 | } 70 | if (path != nullptr) { 71 | wbExportRaw_getFile(raw) = wbFile_open(path, "w+"); 72 | } else { 73 | wbExportRaw_getFile(raw) = nullptr; 74 | } 75 | } 76 | 77 | return; 78 | } 79 | 80 | static inline wbExportRaw_t wbExportRaw_new(void) { 81 | wbExportRaw_t raw; 82 | 83 | raw = wbNew(struct st_wbExportRaw_t); 84 | 85 | wbExportRaw_getFile(raw) = nullptr; 86 | wbExportRaw_setRowCount(raw, -1); 87 | wbExportRaw_setColumnCount(raw, -1); 88 | 89 | return raw; 90 | } 91 | 92 | static inline void wbExportRaw_delete(wbExportRaw_t raw) { 93 | if (raw != nullptr) { 94 | wbExportRaw_setFile(raw, NULL); 95 | wbDelete(raw); 96 | } 97 | return; 98 | } 99 | 100 | static inline void wbExportRaw_write(wbExportRaw_t raw, void *data, 101 | int rows, int columns, 102 | wbType_t type) { 103 | int ii, jj; 104 | FILE *handle; 105 | wbFile_t file; 106 | 107 | if (raw == nullptr || wbExportRaw_getFile(raw) == nullptr) { 108 | return; 109 | } 110 | 111 | file = wbExportRaw_getFile(raw); 112 | 113 | handle = wbFile_getFileHandle(file); 114 | 115 | if (handle == nullptr) { 116 | return; 117 | } 118 | 119 | if (columns == 1) { 120 | fprintf(handle, "%d\n", rows); 121 | } else { 122 | fprintf(handle, "%d %d\n", rows, columns); 123 | } 124 | 125 | for (ii = 0; ii < rows; ii++) { 126 | for (jj = 0; jj < columns; jj++) { 127 | if (type == wbType_integer) { 128 | int elem = ((int *)data)[ii * columns + jj]; 129 | fprintf(handle, "%d", elem); 130 | } else if (type == wbType_ubit8) { 131 | int elem = ((unsigned char *)data)[ii * columns + jj]; 132 | fprintf(handle, "%d", elem); 133 | } else { 134 | wbReal_t elem = ((wbReal_t *)data)[ii * columns + jj]; 135 | fprintf(handle, "%f", elem); 136 | } 137 | if (jj == columns - 1) { 138 | fprintf(handle, "\n"); 139 | } else { 140 | fprintf(handle, " "); 141 | } 142 | } 143 | } 144 | 145 | return; 146 | } 147 | 148 | static inline void wbExportCSV_setFile(wbExportCSV_t csv, 149 | const char *path) { 150 | if (csv != nullptr) { 151 | if (wbExportCSV_getFile(csv) != nullptr) { 152 | wbFile_delete(wbExportCSV_getFile(csv)); 153 | } 154 | if (path != nullptr) { 155 | wbExportCSV_getFile(csv) = wbFile_open(path, "w+"); 156 | } else { 157 | wbExportCSV_getFile(csv) = nullptr; 158 | } 159 | } 160 | 161 | return; 162 | } 163 | 164 | static inline wbExportCSV_t wbExportCSV_new(void) { 165 | wbExportCSV_t csv; 166 | 167 | csv = wbNew(struct st_wbExportCSV_t); 168 | 169 | wbExportCSV_getFile(csv) = nullptr; 170 | wbExportCSV_setColumnCount(csv, -1); 171 | wbExportCSV_setRowCount(csv, -1); 172 | wbExportCSV_setSeperator(csv, '\0'); 173 | 174 | return csv; 175 | } 176 | 177 | static inline void wbExportCSV_delete(wbExportCSV_t csv) { 178 | if (csv != nullptr) { 179 | wbExportCSV_setFile(csv, NULL); 180 | wbDelete(csv); 181 | } 182 | } 183 | 184 | static inline void wbExportCSV_write(wbExportCSV_t csv, void *data, 185 | int rows, int columns, char sep, 186 | wbType_t type) { 187 | int ii, jj; 188 | wbFile_t file; 189 | FILE *handle; 190 | char seperator[2]; 191 | 192 | if (csv == nullptr || wbExportCSV_getFile(csv) == nullptr) { 193 | return; 194 | } 195 | 196 | file = wbExportCSV_getFile(csv); 197 | 198 | handle = wbFile_getFileHandle(file); 199 | 200 | if (handle == nullptr) { 201 | return; 202 | } 203 | 204 | if (sep == '\0') { 205 | seperator[0] = ','; 206 | } else { 207 | seperator[0] = sep; 208 | } 209 | seperator[1] = '\0'; 210 | 211 | for (ii = 0; ii < rows; ii++) { 212 | for (jj = 0; jj < columns; jj++) { 213 | if (type == wbType_integer) { 214 | int elem = ((int *)data)[ii * columns + jj]; 215 | fprintf(handle, "%d", elem); 216 | } else if (type == wbType_ubit8) { 217 | int elem = ((unsigned char *)data)[ii * columns + jj]; 218 | fprintf(handle, "%d", elem); 219 | } else { 220 | wbReal_t elem = ((wbReal_t *)data)[ii * columns + jj]; 221 | fprintf(handle, "%f", elem); 222 | } 223 | if (jj == columns - 1) { 224 | fprintf(handle, "\n"); 225 | } else { 226 | fprintf(handle, "%s", seperator); 227 | } 228 | } 229 | } 230 | 231 | return; 232 | } 233 | 234 | static inline wbExport_t wbExport_open(const char *file, 235 | wbExportKind_t kind) { 236 | wbExport_t exprt; 237 | 238 | if (file == nullptr) { 239 | wbLog(ERROR, "Go NULL for file value."); 240 | wbExit(); 241 | } 242 | 243 | wbExport_setFile(exprt, NULL); 244 | wbExport_setKind(exprt, kind); 245 | 246 | if (kind == wbExportKind_raw) { 247 | wbExportRaw_t raw = wbExportRaw_new(); 248 | wbExportRaw_setFile(raw, file); 249 | wbExport_setRaw(exprt, raw); 250 | } else if (kind == wbExportKind_text) { 251 | wbExportText_t txt = wbExportText_new(); 252 | wbExportText_setFile(txt, file); 253 | wbExport_setText(exprt, txt); 254 | } else if (kind == wbExportKind_tsv || kind == wbExportKind_csv) { 255 | wbExportCSV_t csv = wbExportCSV_new(); 256 | if (kind == wbExportKind_csv) { 257 | wbExportCSV_setSeperator(csv, ','); 258 | } else { 259 | wbExportCSV_setSeperator(csv, '\t'); 260 | } 261 | wbExportCSV_setFile(csv, file); 262 | wbExport_setCSV(exprt, csv); 263 | } else if (kind == wbExportKind_ppm) { 264 | wbExport_setFile(exprt, wbString_duplicate(file)); 265 | } else { 266 | wbLog(ERROR, "Invalid export type."); 267 | wbExit(); 268 | } 269 | 270 | return exprt; 271 | } 272 | 273 | static inline wbExport_t wbExport_open(const char *file, 274 | const char *type0) { 275 | wbExport_t exprt; 276 | wbExportKind_t kind; 277 | char *type; 278 | 279 | type = wbString_toLower(type0); 280 | 281 | if (wbString_sameQ(type, "csv")) { 282 | kind = wbExportKind_csv; 283 | } else if (wbString_sameQ(type, "tsv")) { 284 | kind = wbExportKind_tsv; 285 | } else if (wbString_sameQ(type, "raw") || wbString_sameQ(type, "dat")) { 286 | kind = wbExportKind_raw; 287 | } else if (wbString_sameQ(type, "ppm") || wbString_sameQ(type, "pbm")) { 288 | kind = wbExportKind_ppm; 289 | } else if (wbString_sameQ(type, "txt") || wbString_sameQ(type, "text")) { 290 | kind = wbExportKind_text; 291 | } else { 292 | wbLog(ERROR, "Invalid export type ", type0); 293 | wbExit(); 294 | } 295 | 296 | exprt = wbExport_open(file, kind); 297 | 298 | wbDelete(type); 299 | 300 | return exprt; 301 | } 302 | 303 | static inline void wbExport_close(wbExport_t exprt) { 304 | wbExportKind_t kind; 305 | 306 | kind = wbExport_getKind(exprt); 307 | 308 | if (wbExport_getFile(exprt)) { 309 | wbDelete(wbExport_getFile(exprt)); 310 | } 311 | 312 | if (kind == wbExportKind_tsv || kind == wbExportKind_csv) { 313 | wbExportCSV_t csv = wbExport_getCSV(exprt); 314 | wbExportCSV_delete(csv); 315 | wbExport_setCSV(exprt, NULL); 316 | } else if (kind == wbExportKind_raw) { 317 | wbExportRaw_t raw = wbExport_getRaw(exprt); 318 | wbExportRaw_delete(raw); 319 | wbExport_setRaw(exprt, NULL); 320 | } else if (kind == wbExportKind_text) { 321 | wbExportText_t text = wbExport_getText(exprt); 322 | wbExportText_delete(text); 323 | wbExport_setText(exprt, NULL); 324 | } else if (kind == wbExportKind_ppm) { 325 | } else { 326 | wbLog(ERROR, "Invalid export type."); 327 | wbExit(); 328 | } 329 | return; 330 | } 331 | 332 | static inline void wbExport_writeAsImage(wbExport_t exprt, wbImage_t img) { 333 | wbAssert(wbExport_getKind(exprt) == wbExportKind_ppm); 334 | 335 | wbPPM_export(wbExport_getFile(exprt), img); 336 | 337 | return; 338 | } 339 | 340 | static inline void wbExport_write(wbExport_t exprt, void *data, int rows, 341 | int columns, char sep, wbType_t type) { 342 | wbExportKind_t kind; 343 | 344 | kind = wbExport_getKind(exprt); 345 | if (kind == wbExportKind_tsv || kind == wbExportKind_csv) { 346 | wbExportCSV_t csv = wbExport_getCSV(exprt); 347 | wbExportCSV_write(csv, data, rows, columns, sep, type); 348 | } else if (kind == wbExportKind_raw) { 349 | wbExportRaw_t raw = wbExport_getRaw(exprt); 350 | wbExportRaw_write(raw, data, rows, columns, type); 351 | } else if (kind == wbExportKind_text) { 352 | wbExportText_t text = wbExport_getText(exprt); 353 | if (columns == 0) { 354 | columns = 1; 355 | } 356 | if (rows == 0) { 357 | rows = 1; 358 | } 359 | wbExportText_write(text, (const char *)data, rows * columns); 360 | } else { 361 | wbLog(ERROR, "Invalid export type."); 362 | wbExit(); 363 | } 364 | return; 365 | } 366 | 367 | static inline void wbExport_write(wbExport_t exprt, void *data, int rows, 368 | int columns, wbType_t type) { 369 | wbExport_write(exprt, data, rows, columns, ',', type); 370 | } 371 | 372 | static wbExportKind_t _parseExportExtension(const char *file) { 373 | char *extension; 374 | wbExportKind_t kind; 375 | 376 | extension = wbFile_extension(file); 377 | 378 | if (wbString_sameQ(extension, "csv")) { 379 | kind = wbExportKind_csv; 380 | } else if (wbString_sameQ(extension, "tsv")) { 381 | kind = wbExportKind_tsv; 382 | } else if (wbString_sameQ(extension, "raw") || 383 | wbString_sameQ(extension, "dat")) { 384 | kind = wbExportKind_raw; 385 | } else if (wbString_sameQ(extension, "text") || 386 | wbString_sameQ(extension, "txt")) { 387 | kind = wbExportKind_text; 388 | } else if (wbString_sameQ(extension, "ppm") || 389 | wbString_sameQ(extension, "pbm")) { 390 | kind = wbExportKind_ppm; 391 | } else { 392 | kind = wbExportKind_unknown; 393 | wbLog(ERROR, "File ", file, " does not have a compatible extension."); 394 | } 395 | 396 | wbDelete(extension); 397 | 398 | return kind; 399 | } 400 | 401 | static void wbExport(const char *file, void *data, int rows, int columns, 402 | wbType_t type) { 403 | wbExportKind_t kind; 404 | wbExport_t exprt; 405 | 406 | if (file == nullptr) { 407 | return; 408 | } 409 | 410 | kind = _parseExportExtension(file); 411 | exprt = wbExport_open(file, kind); 412 | 413 | wbExport_write(exprt, data, rows, columns, type); 414 | wbExport_close(exprt); 415 | } 416 | 417 | void wbExport(const char *file, unsigned char *data, int rows) { 418 | wbExport(file, data, rows, 1); 419 | return; 420 | } 421 | 422 | void wbExport(const char *file, int *data, int rows) { 423 | wbExport(file, data, rows, 1); 424 | return; 425 | } 426 | 427 | void wbExport(const char *file, wbReal_t *data, int rows) { 428 | wbExport(file, data, rows, 1); 429 | return; 430 | } 431 | 432 | void wbExport(const char *file, unsigned char *data, int rows, 433 | int columns) { 434 | wbExportKind_t kind; 435 | wbExport_t exprt; 436 | 437 | if (file == nullptr) { 438 | return; 439 | } 440 | 441 | kind = _parseExportExtension(file); 442 | exprt = wbExport_open(file, kind); 443 | 444 | wbExport_write(exprt, data, rows, columns, wbType_ubit8); 445 | wbExport_close(exprt); 446 | } 447 | 448 | void wbExport(const char *file, int *data, int rows, int columns) { 449 | wbExportKind_t kind; 450 | wbExport_t exprt; 451 | 452 | if (file == nullptr) { 453 | return; 454 | } 455 | 456 | kind = _parseExportExtension(file); 457 | exprt = wbExport_open(file, kind); 458 | 459 | wbExport_write(exprt, data, rows, columns, wbType_integer); 460 | wbExport_close(exprt); 461 | } 462 | 463 | void wbExport(const char *file, wbReal_t *data, int rows, int columns) { 464 | wbExportKind_t kind; 465 | wbExport_t exprt; 466 | 467 | if (file == nullptr) { 468 | return; 469 | } 470 | 471 | kind = _parseExportExtension(file); 472 | exprt = wbExport_open(file, kind); 473 | 474 | wbExport_write(exprt, data, rows, columns, wbType_real); 475 | wbExport_close(exprt); 476 | } 477 | 478 | void wbExport(const char *file, wbExportKind_t kind, void *data, int rows, 479 | int columns, wbType_t type) { 480 | wbExport_t exprt; 481 | 482 | if (file == nullptr) { 483 | return; 484 | } 485 | 486 | exprt = wbExport_open(file, kind); 487 | 488 | wbExport_write(exprt, data, rows, columns, type); 489 | wbExport_close(exprt); 490 | } 491 | 492 | void wbExport(const char *file, wbImage_t img) { 493 | wbExportKind_t kind; 494 | wbExport_t exprt; 495 | 496 | if (file == nullptr) { 497 | return; 498 | } 499 | 500 | kind = _parseExportExtension(file); 501 | exprt = wbExport_open(file, kind); 502 | 503 | wbAssert(kind == wbExportKind_ppm); 504 | 505 | wbExport_writeAsImage(exprt, img); 506 | wbExport_close(exprt); 507 | } 508 | 509 | void wbExport_text(const char *file, void *data, int length) { 510 | wbExport(file, wbExportKind_text, data, 1, length, wbType_ascii); 511 | } 512 | -------------------------------------------------------------------------------- /wbTimer.cpp: -------------------------------------------------------------------------------- 1 | #include "wb.h" 2 | 3 | #ifdef WB_USE_WINDOWS 4 | uint64_t _hrtime_frequency = 0; 5 | #endif /* WB_USE_WINDOWS */ 6 | wbTimer_t _timer = nullptr; 7 | 8 | #ifdef WB_USE_DARWIN 9 | static double o_timebase = 0; 10 | static uint64_t o_timestart = 0; 11 | #endif /* WB_USE_DARWIN */ 12 | 13 | uint64_t _hrtime(void) { 14 | #define NANOSEC ((uint64_t)1e9) 15 | #ifdef WB_USE_WINDOWS 16 | LARGE_INTEGER counter; 17 | if (!QueryPerformanceCounter(&counter)) { 18 | return 0; 19 | } 20 | return ((uint64_t)counter.LowPart * NANOSEC / _hrtime_frequency) + 21 | (((uint64_t)counter.HighPart * NANOSEC / _hrtime_frequency) 22 | << 32); 23 | #else 24 | struct timespec ts; 25 | #ifdef WB_USE_DARWIN 26 | #define O_NANOSEC (+1.0E-9) 27 | #define O_GIGA UINT64_C(1000000000) 28 | if (!o_timestart) { 29 | mach_timebase_info_data_t tb{}; 30 | mach_timebase_info(&tb); 31 | o_timebase = tb.numer; 32 | o_timebase /= tb.denom; 33 | o_timestart = mach_absolute_time(); 34 | } 35 | double diff = (mach_absolute_time() - o_timestart) * o_timebase; 36 | ts.tv_sec = diff * O_NANOSEC; 37 | ts.tv_nsec = diff - (ts.tv_sec * O_GIGA); 38 | #undef O_NANOSEC 39 | #undef O_GIGA 40 | #else /* WB_USE_DARWIN */ 41 | clock_gettime(CLOCK_MONOTONIC, &ts); 42 | #endif /* WB_USE_DARWIN */ 43 | return (((uint64_t)ts.tv_sec) * NANOSEC + ts.tv_nsec); 44 | #endif /* WB_USE_WINDOWS */ 45 | #undef NANOSEC 46 | } 47 | 48 | static inline uint64_t getTime(void) { 49 | #ifdef WB_USE_CUDA 50 | cudaDeviceSynchronize(); 51 | #endif /* WB_USE_CUDA */ 52 | return _hrtime(); 53 | } 54 | 55 | static inline wbTimerNode_t wbTimerNode_new(int idx, wbTimerKind_t kind, 56 | const char *file, 57 | const char *fun, 58 | int startLine) { 59 | wbTimerNode_t node = wbNew(struct st_wbTimerNode_t); 60 | wbTimerNode_setId(node, uuid()); 61 | wbTimerNode_setIdx(node, idx); 62 | wbTimerNode_setSessionId(node, sessionId()); 63 | wbTimerNode_setMPIRank(node, wbMPI_getRank()); 64 | wbTimerNode_setLevel(node, 0); 65 | wbTimerNode_setStoppedQ(node, wbFalse); 66 | wbTimerNode_setKind(node, kind); 67 | wbTimerNode_setStartTime(node, 0); 68 | wbTimerNode_setEndTime(node, 0); 69 | wbTimerNode_setElapsedTime(node, 0); 70 | wbTimerNode_setStartLine(node, startLine); 71 | wbTimerNode_setEndLine(node, 0); 72 | wbTimerNode_setStartFunction(node, fun); 73 | wbTimerNode_setEndFunction(node, NULL); 74 | wbTimerNode_setStartFile(node, file); 75 | wbTimerNode_setEndFile(node, NULL); 76 | wbTimerNode_setNext(node, NULL); 77 | wbTimerNode_setPrevious(node, NULL); 78 | wbTimerNode_setParent(node, NULL); 79 | wbTimerNode_setMessage(node, NULL); 80 | return node; 81 | } 82 | 83 | static inline void wbTimerNode_delete(wbTimerNode_t node) { 84 | if (node != nullptr) { 85 | if (wbTimerNode_getMessage(node)) { 86 | wbDelete(wbTimerNode_getMessage(node)); 87 | } 88 | wbDelete(node); 89 | } 90 | } 91 | 92 | static inline const char *_nodeKind(wbTimerKind_t kind) { 93 | switch (kind) { 94 | case wbTimerKind_Generic: 95 | return "Generic"; 96 | case wbTimerKind_IO: 97 | return "IO"; 98 | case wbTimerKind_GPU: 99 | return "GPU"; 100 | case wbTimerKind_Copy: 101 | return "Copy"; 102 | case wbTimerKind_Driver: 103 | return "Driver"; 104 | case wbTimerKind_CopyAsync: 105 | return "CopyAsync"; 106 | case wbTimerKind_Compute: 107 | return "Compute"; 108 | case wbTimerKind_CPUGPUOverlap: 109 | return "CPUGPUOverlap"; 110 | } 111 | return "Undefined"; 112 | } 113 | 114 | static inline json11::Json wbTimerNode_toJSONObject(wbTimerNode_t node) { 115 | if (node == nullptr) { 116 | return json11::Json{}; 117 | } 118 | int parent_id = wbTimerNode_hasParent(node) 119 | ? wbTimerNode_getIdx(wbTimerNode_getParent(node)) 120 | : -1; 121 | json11::Json json = json11::Json::object{ 122 | {"id", wbTimerNode_getId(node)}, 123 | {"session_id", wbTimerNode_getSessionId(node)}, 124 | {"idx", wbTimerNode_getIdx(node)}, 125 | {"mpi_rank", wbTimerNode_getMPIRank(node)}, 126 | {"stopped", wbTimerNode_stoppedQ(node)}, 127 | {"kind", _nodeKind(wbTimerNode_getKind(node))}, 128 | {"start_time", wbTimerNode_getStartTime(node)}, 129 | {"end_time", wbTimerNode_getEndTime(node)}, 130 | {"elapsed_time", wbTimerNode_getElapsedTime(node)}, 131 | {"start_line", wbTimerNode_getStartLine(node)}, 132 | {"end_line", wbTimerNode_getEndLine(node)}, 133 | {"start_function", wbTimerNode_getStartFunction(node)}, 134 | {"end_function", wbTimerNode_getEndFunction(node)}, 135 | {"start_file", wbTimerNode_getStartFile(node)}, 136 | {"end_file", wbTimerNode_getEndFile(node)}, 137 | {"parent_id", parent_id}, 138 | {"message", wbTimerNode_getMessage(node)}, 139 | }; 140 | return json; 141 | } 142 | 143 | static inline string wbTimerNode_toJSON(wbTimerNode_t node) { 144 | if (node == nullptr) { 145 | return ""; 146 | } else if (WB_USE_JSON11) { 147 | json11::Json json = wbTimerNode_toJSONObject(node); 148 | return json.string_value(); 149 | } else { 150 | stringstream ss; 151 | 152 | ss << "{\n"; 153 | ss << wbString_quote("idx") << ":" << wbTimerNode_getIdx(node) 154 | << ",\n"; 155 | ss << wbString_quote("id") << ":" 156 | << wbString_quote(wbTimerNode_getId(node)) << ",\n"; 157 | ss << wbString_quote("session_id") << ":" 158 | << wbString_quote(wbTimerNode_getSessionId(node)) << ",\n"; 159 | ss << wbString_quote("mpi_rank") << ":" << wbTimerNode_getMPIRank(node) 160 | << ",\n"; 161 | ss << wbString_quote("stopped") << ":" 162 | << wbString(wbTimerNode_stoppedQ(node) ? "true" : "false") << ",\n"; 163 | ss << wbString_quote("kind") << ":" 164 | << wbString_quote(_nodeKind(wbTimerNode_getKind(node))) << ",\n"; 165 | ss << wbString_quote("start_time") << ":" 166 | << wbTimerNode_getStartTime(node) << ",\n"; 167 | ss << wbString_quote("end_time") << ":" << wbTimerNode_getEndTime(node) 168 | << ",\n"; 169 | ss << wbString_quote("elapsed_time") << ":" 170 | << wbTimerNode_getElapsedTime(node) << ",\n"; 171 | ss << wbString_quote("start_line") << ":" 172 | << wbTimerNode_getStartLine(node) << ",\n"; 173 | ss << wbString_quote("end_line") << ":" << wbTimerNode_getEndLine(node) 174 | << ",\n"; 175 | ss << wbString_quote("start_function") << ":" 176 | << wbString_quote(wbTimerNode_getStartFunction(node)) << ",\n"; 177 | ss << wbString_quote("end_function") << ":" 178 | << wbString_quote(wbTimerNode_getEndFunction(node)) << ",\n"; 179 | ss << wbString_quote("start_file") << ":" 180 | << wbString_quote(wbTimerNode_getStartFile(node)) << ",\n"; 181 | ss << wbString_quote("end_file") << ":" 182 | << wbString_quote(wbTimerNode_getEndFile(node)) << ",\n"; 183 | ss << wbString_quote("parent_id") << ":" 184 | << wbString(wbTimerNode_hasParent(node) 185 | ? wbTimerNode_getIdx(wbTimerNode_getParent(node)) 186 | : -1) 187 | << ",\n"; 188 | ss << wbString_quote("message") << ":" 189 | << wbString_quote(wbTimerNode_getMessage(node)) << "\n"; 190 | ss << "}"; 191 | 192 | return ss.str(); 193 | } 194 | } 195 | 196 | static inline string wbTimerNode_toXML(wbTimerNode_t node) { 197 | if (node == nullptr) { 198 | return ""; 199 | } else { 200 | stringstream ss; 201 | 202 | ss << "\n"; 203 | ss << "" << wbTimerNode_getIdx(node) << "\n"; 204 | ss << "" << wbTimerNode_getId(node) << "\n"; 205 | ss << "" << wbTimerNode_getSessionId(node) << "\n"; 206 | ss << "" 207 | << wbString(wbTimerNode_stoppedQ(node) ? "true" : "false") 208 | << "\n"; 209 | ss << "" << _nodeKind(wbTimerNode_getKind(node)) << "\n"; 210 | ss << "" << wbTimerNode_getStartTime(node) 211 | << "\n"; 212 | ss << "" << wbTimerNode_getEndTime(node) << "\n"; 213 | ss << "" << wbTimerNode_getElapsedTime(node) 214 | << "\n"; 215 | ss << "" << wbTimerNode_getStartLine(node) 216 | << "\n"; 217 | ss << "" << wbTimerNode_getEndLine(node) << "\n"; 218 | ss << "" << wbTimerNode_getStartFunction(node) 219 | << "\n"; 220 | ss << "" << wbTimerNode_getEndFunction(node) 221 | << "\n"; 222 | ss << "" << wbTimerNode_getStartFile(node) 223 | << "\n"; 224 | ss << "" << wbTimerNode_getEndFile(node) << "\n"; 225 | ss << "" 226 | << wbString(wbTimerNode_hasParent(node) 227 | ? wbTimerNode_getIdx(wbTimerNode_getParent(node)) 228 | : -1) 229 | << "\n"; 230 | ss << "" << wbTimerNode_getMessage(node) << "\n"; 231 | ss << "\n"; 232 | 233 | return ss.str(); 234 | } 235 | } 236 | 237 | #define wbTimer_getId(timer) ((timer)->id) 238 | #define wbTimer_getSessionId(timer) ((timer)->session_id) 239 | #define wbTimer_getLength(timer) ((timer)->length) 240 | #define wbTimer_getHead(timer) ((timer)->head) 241 | #define wbTimer_getTail(timer) ((timer)->tail) 242 | #define wbTimer_getStartTime(timer) ((timer)->startTime) 243 | #define wbTimer_getEndTime(timer) ((timer)->endTime) 244 | #define wbTimer_getElapsedTime(timer) ((timer)->elapsedTime) 245 | 246 | #define wbTimer_setId(timer, val) (wbTimer_getId(timer) = val) 247 | #define wbTimer_setSessionId(timer, val) \ 248 | (wbTimer_getSessionId(timer) = val) 249 | #define wbTimer_setLength(timer, val) (wbTimer_getLength(timer) = val) 250 | #define wbTimer_setHead(timer, val) (wbTimer_getHead(timer) = val) 251 | #define wbTimer_setTail(timer, val) (wbTimer_getTail(timer) = val) 252 | #define wbTimer_setStartTime(node, val) (wbTimer_getStartTime(node) = val) 253 | #define wbTimer_setEndTime(node, val) (wbTimer_getEndTime(node) = val) 254 | #define wbTimer_setElapsedTime(node, val) \ 255 | (wbTimer_getElapsedTime(node) = val) 256 | 257 | #define wbTimer_incrementLength(timer) (wbTimer_getLength(timer)++) 258 | #define wbTimer_decrementLength(timer) (wbTimer_getLength(timer)--) 259 | 260 | #define wbTimer_emptyQ(timer) (wbTimer_getLength(timer) == 0) 261 | 262 | void wbTimer_delete(wbTimer_t timer) { 263 | if (timer != nullptr) { 264 | wbTimerNode_t tmp, iter; 265 | 266 | iter = wbTimer_getHead(timer); 267 | while (iter) { 268 | tmp = wbTimerNode_getNext(iter); 269 | wbTimerNode_delete(iter); 270 | iter = tmp; 271 | } 272 | 273 | wbDelete(timer); 274 | } 275 | } 276 | 277 | static json11::Json wbTimer_toJSONObject(wbTimer_t timer) { 278 | 279 | stringstream ss; 280 | wbTimerNode_t iter; 281 | uint64_t currentTime; 282 | std::vector elems; 283 | 284 | currentTime = getTime(); 285 | 286 | wbTimer_setEndTime(timer, currentTime); 287 | wbTimer_setElapsedTime(timer, currentTime - wbTimer_getStartTime(timer)); 288 | 289 | for (iter = wbTimer_getHead(timer); iter != nullptr; 290 | iter = wbTimerNode_getNext(iter)) { 291 | if (!wbTimerNode_stoppedQ(iter)) { 292 | wbTimerNode_setEndTime(iter, currentTime); 293 | wbTimerNode_setElapsedTime(iter, currentTime - 294 | wbTimerNode_getStartTime(iter)); 295 | } 296 | elems.push_back(wbTimerNode_toJSONObject(iter)); 297 | } 298 | return json11::Json(elems); 299 | } 300 | 301 | string wbTimer_toJSON(wbTimer_t timer) { 302 | if (timer == nullptr) { 303 | return ""; 304 | } else if (WB_USE_JSON11) { 305 | json11::Json json = wbTimer_toJSONObject(timer); 306 | return json.string_value(); 307 | } else { 308 | stringstream ss; 309 | wbTimerNode_t iter; 310 | uint64_t currentTime; 311 | 312 | currentTime = getTime(); 313 | 314 | wbTimer_setEndTime(timer, currentTime); 315 | wbTimer_setElapsedTime(timer, 316 | currentTime - wbTimer_getStartTime(timer)); 317 | 318 | for (iter = wbTimer_getHead(timer); iter != nullptr; 319 | iter = wbTimerNode_getNext(iter)) { 320 | if (!wbTimerNode_stoppedQ(iter)) { 321 | wbTimerNode_setEndTime(iter, currentTime); 322 | wbTimerNode_setElapsedTime( 323 | iter, currentTime - wbTimerNode_getStartTime(iter)); 324 | } 325 | ss << wbTimerNode_toJSON(iter); 326 | if (wbTimerNode_getNext(iter) != nullptr) { 327 | ss << ",\n"; 328 | } 329 | } 330 | 331 | return ss.str(); 332 | } 333 | } 334 | 335 | string wbTimer_toJSON() { 336 | return wbTimer_toJSON(_timer); 337 | } 338 | 339 | string wbTimer_toXML(wbTimer_t timer) { 340 | if (timer == nullptr) { 341 | return ""; 342 | } else { 343 | stringstream ss; 344 | wbTimerNode_t iter; 345 | uint64_t currentTime; 346 | 347 | currentTime = getTime(); 348 | 349 | wbTimer_setEndTime(timer, currentTime); 350 | wbTimer_setElapsedTime(timer, 351 | currentTime - wbTimer_getStartTime(timer)); 352 | 353 | ss << "\n"; 354 | ss << "" << wbTimer_getStartTime(timer) 355 | << "\n"; 356 | ss << "" << wbTimer_getEndTime(timer) << "\n"; 357 | ss << "" << wbTimer_getElapsedTime(timer) 358 | << "\n"; 359 | ss << "\n"; 360 | for (iter = wbTimer_getHead(timer); iter != nullptr; 361 | iter = wbTimerNode_getNext(iter)) { 362 | if (!wbTimerNode_stoppedQ(iter)) { 363 | wbTimerNode_setEndTime(iter, currentTime); 364 | wbTimerNode_setElapsedTime( 365 | iter, currentTime - wbTimerNode_getStartTime(iter)); 366 | } 367 | ss << wbTimerNode_toXML(iter); 368 | } 369 | ss << "\n"; 370 | ss << "\n"; 371 | 372 | return ss.str(); 373 | } 374 | } 375 | 376 | string wbTimer_toXML() { 377 | return wbTimer_toXML(_timer); 378 | } 379 | 380 | wbTimer_t wbTimer_new(void) { 381 | wbTimer_t timer = wbNew(struct st_wbTimer_t); 382 | wbTimer_setId(timer, uuid()); 383 | wbTimer_setSessionId(timer, sessionId()); 384 | wbTimer_setLength(timer, 0); 385 | wbTimer_setHead(timer, NULL); 386 | wbTimer_setTail(timer, NULL); 387 | wbTimer_setStartTime(timer, getTime()); 388 | wbTimer_setEndTime(timer, 0); 389 | wbTimer_setElapsedTime(timer, 0); 390 | 391 | return timer; 392 | } 393 | 394 | static inline wbTimerNode_t _findParent(wbTimer_t timer) { 395 | wbTimerNode_t iter; 396 | 397 | for (iter = wbTimer_getTail(timer); iter != nullptr; 398 | iter = wbTimerNode_getPrevious(iter)) { 399 | if (!wbTimerNode_stoppedQ(iter)) { 400 | return iter; 401 | } 402 | } 403 | return NULL; 404 | } 405 | 406 | static inline void _insertIntoList(wbTimer_t timer, wbTimerNode_t node) { 407 | if (wbTimer_emptyQ(timer)) { 408 | wbTimer_setHead(timer, node); 409 | wbTimer_setTail(timer, node); 410 | } else { 411 | wbTimerNode_t end = wbTimer_getTail(timer); 412 | wbTimer_setTail(timer, node); 413 | wbTimerNode_setNext(end, node); 414 | wbTimerNode_setPrevious(node, end); 415 | } 416 | wbTimer_incrementLength(timer); 417 | } 418 | 419 | wbTimerNode_t wbTimer_start(wbTimerKind_t kind, const char *file, 420 | const char *fun, int line) { 421 | int id; 422 | uint64_t currentTime; 423 | wbTimerNode_t node; 424 | wbTimerNode_t parent; 425 | 426 | // wb_init(NULL, NULL); 427 | 428 | currentTime = getTime(); 429 | 430 | id = wbTimer_getLength(_timer); 431 | 432 | node = wbTimerNode_new(id, kind, file, fun, line); 433 | 434 | parent = _findParent(_timer); 435 | _insertIntoList(_timer, node); 436 | 437 | wbTimerNode_setStartTime(node, currentTime); 438 | wbTimerNode_setParent(node, parent); 439 | if (parent != nullptr) { 440 | wbTimerNode_setLevel(node, wbTimerNode_getLevel(parent) + 1); 441 | } 442 | 443 | return node; 444 | } 445 | 446 | wbTimerNode_t wbTimer_start(wbTimerKind_t kind, string msg, 447 | const char *file, const char *fun, int line) { 448 | wbTimerNode_t node = wbTimer_start(kind, file, fun, line); 449 | wbTimerNode_setMessage(node, wbString_duplicate(msg)); 450 | return node; 451 | } 452 | 453 | static inline wbTimerNode_t _findNode(wbTimer_t timer, wbTimerKind_t kind, 454 | string msg) { 455 | wbTimerNode_t iter; 456 | 457 | for (iter = wbTimer_getTail(timer); iter != nullptr; 458 | iter = wbTimerNode_getPrevious(iter)) { 459 | if (msg == "") { 460 | if (!wbTimerNode_stoppedQ(iter) && 461 | wbTimerNode_getKind(iter) == kind) { 462 | return iter; 463 | } 464 | } else { 465 | if (!wbTimerNode_stoppedQ(iter) && 466 | wbTimerNode_getKind(iter) == kind && 467 | msg == wbTimerNode_getMessage(iter)) { 468 | return iter; 469 | } 470 | } 471 | } 472 | return NULL; 473 | } 474 | 475 | void wbTimer_stop(wbTimerKind_t kind, string msg, const char *file, 476 | const char *fun, int line) { 477 | uint64_t currentTime; 478 | wbTimerNode_t node; 479 | 480 | currentTime = getTime(); 481 | 482 | node = _findNode(_timer, kind, msg); 483 | 484 | wbAssert(node != nullptr); 485 | if (node == nullptr) { 486 | return; 487 | } 488 | 489 | wbTimerNode_setEndTime(node, currentTime); 490 | wbTimerNode_setElapsedTime(node, 491 | currentTime - wbTimerNode_getStartTime(node)); 492 | wbTimerNode_setEndLine(node, line); 493 | wbTimerNode_setEndFunction(node, fun); 494 | wbTimerNode_setEndFile(node, file); 495 | wbTimerNode_setStoppedQ(node, wbTrue); 496 | 497 | #ifdef wbLogger_printOnLog 498 | if (wbLogger_printOnLog && node) { 499 | json11::Json json = json11::Json::object{ 500 | {"type", "timer"}, 501 | {"id", wbTimerNode_getId(node)}, 502 | {"session_id", wbTimerNode_getSessionId(node)}, 503 | {"data", wbTimerNode_toJSONObject(node)}}; 504 | std::cout << json.dump() << std::endl; 505 | } 506 | #endif /* wbLogger_printOnLog */ 507 | return; 508 | } 509 | 510 | void wbTimer_stop(wbTimerKind_t kind, const char *file, const char *fun, 511 | int line) { 512 | wbTimer_stop(kind, "", file, fun, line); 513 | } 514 | -------------------------------------------------------------------------------- /wbImport.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "wb.h" 4 | 5 | static inline void wbImportCSV_setFile(wbImportCSV_t csv, 6 | const char *path) { 7 | if (csv != nullptr) { 8 | if (wbImportCSV_getFile(csv) != nullptr) { 9 | wbFile_delete(wbImportCSV_getFile(csv)); 10 | } 11 | if (path != nullptr) { 12 | wbImportCSV_getFile(csv) = wbFile_open(path, "r"); 13 | } else { 14 | wbImportCSV_getFile(csv) = nullptr; 15 | } 16 | } 17 | 18 | return; 19 | } 20 | 21 | static inline wbImportCSV_t wbImportCSV_new(void) { 22 | wbImportCSV_t csv; 23 | 24 | csv = wbNew(struct st_wbImportCSV_t); 25 | 26 | wbImportCSV_setRowCount(csv, -1); 27 | wbImportCSV_setColumnCount(csv, -1); 28 | wbImportCSV_setData(csv, NULL); 29 | wbImportCSV_getFile(csv) = nullptr; 30 | wbImportCSV_setSeperator(csv, '\0'); 31 | 32 | return csv; 33 | } 34 | 35 | static inline void wbImportCSV_delete(wbImportCSV_t csv) { 36 | if (csv != nullptr) { 37 | wbImportCSV_setFile(csv, NULL); 38 | if (wbImportCSV_getData(csv)) { 39 | wbDelete(wbImportCSV_getData(csv)); 40 | } 41 | wbDelete(csv); 42 | } 43 | } 44 | 45 | static inline wbImportCSV_t wbImportCSV_findDimensions(wbImportCSV_t csv, 46 | int *resRows, 47 | int *resColumns) { 48 | int rows = 0, columns = -1; 49 | char *line; 50 | wbFile_t file; 51 | char seperator[2]; 52 | 53 | if (csv == nullptr) { 54 | return NULL; 55 | } 56 | 57 | if (wbImportCSV_getSeperator(csv) == '\0') { 58 | seperator[0] = ','; 59 | } else { 60 | seperator[0] = wbImportCSV_getSeperator(csv); 61 | } 62 | seperator[1] = '\0'; 63 | 64 | file = wbImportCSV_getFile(csv); 65 | 66 | while ((line = wbFile_readLine(file)) != nullptr) { 67 | int currColumn = 0; 68 | char *token = strtok(line, seperator); 69 | while (token != nullptr) { 70 | token = strtok(NULL, seperator); 71 | currColumn++; 72 | } 73 | rows++; 74 | if (columns == -1) { 75 | columns = currColumn; 76 | } 77 | if (columns != currColumn) { 78 | wbLog(ERROR, "The csv file is not rectangular."); 79 | } 80 | wbAssert(columns == currColumn); 81 | } 82 | 83 | wbFile_rewind(file); 84 | 85 | *resRows = rows; 86 | *resColumns = columns; 87 | 88 | return csv; 89 | } 90 | 91 | static inline int *csv_readAsInteger(wbFile_t file, char sep, int rows, 92 | int columns) { 93 | int ii = 0; 94 | int *data; 95 | char *line; 96 | int var; 97 | char seperator[2]; 98 | 99 | if (file == nullptr) { 100 | return NULL; 101 | } 102 | 103 | data = wbNewArray(int, rows *columns); 104 | 105 | if (sep == '\0') { 106 | seperator[0] = ','; 107 | } else { 108 | seperator[0] = sep; 109 | } 110 | seperator[1] = '\0'; 111 | 112 | // printf("cols = %d rows = %d\n", columns, rows); 113 | if (columns == 1) { 114 | while ((line = wbFile_readLine(file)) != nullptr) { 115 | sscanf(line, "%d", &var); 116 | // printf("reading %d\n", var); 117 | data[ii++] = var; 118 | } 119 | } else { 120 | while ((line = wbFile_readLine(file)) != nullptr) { 121 | char *token = strtok(line, seperator); 122 | while (token != nullptr) { 123 | sscanf(token, "%d", &var); 124 | token = strtok(NULL, seperator); 125 | data[ii++] = var; 126 | } 127 | } 128 | } 129 | 130 | return data; 131 | } 132 | 133 | static inline wbReal_t *csv_readAsReal(wbFile_t file, char sep, int rows, 134 | int columns) { 135 | int ii = 0; 136 | wbReal_t *data; 137 | char *line; 138 | wbReal_t var; 139 | char seperator[2]; 140 | 141 | if (file == nullptr) { 142 | return NULL; 143 | } 144 | 145 | data = wbNewArray(wbReal_t, rows * columns); 146 | 147 | if (sep == '\0') { 148 | seperator[0] = ','; 149 | } else { 150 | seperator[0] = sep; 151 | } 152 | seperator[1] = '\0'; 153 | 154 | if (columns == 1) { 155 | while ((line = wbFile_readLine(file)) != nullptr) { 156 | sscanf(line, "%f", &var); 157 | data[ii++] = var; 158 | } 159 | } else { 160 | while ((line = wbFile_readLine(file)) != nullptr) { 161 | char *token = strtok(line, seperator); 162 | while (token != nullptr) { 163 | sscanf(token, "%f", &var); 164 | token = strtok(NULL, seperator); 165 | data[ii++] = var; 166 | } 167 | } 168 | } 169 | 170 | return data; 171 | } 172 | 173 | static inline wbImportCSV_t wbImportCSV_read(wbImportCSV_t csv, 174 | wbType_t type) { 175 | void *data; 176 | wbFile_t file; 177 | char seperator; 178 | int rows, columns; 179 | 180 | if (csv == nullptr) { 181 | return NULL; 182 | } 183 | 184 | if (wbImportCSV_getRowCount(csv) == -1 || 185 | wbImportCSV_getColumnCount(csv) == -1) { 186 | if (wbImportCSV_findDimensions(csv, &rows, &columns) == nullptr) { 187 | wbLog(ERROR, "Failed to figure out csv dimensions."); 188 | return NULL; 189 | } 190 | wbImportCSV_setRowCount(csv, rows); 191 | wbImportCSV_setColumnCount(csv, columns); 192 | } 193 | 194 | file = wbImportCSV_getFile(csv); 195 | seperator = wbImportCSV_getSeperator(csv); 196 | rows = wbImportCSV_getRowCount(csv); 197 | columns = wbImportCSV_getColumnCount(csv); 198 | 199 | if (wbImportCSV_getData(csv) != nullptr) { 200 | wbDelete(wbImportCSV_getData(csv)); 201 | wbImportCSV_setData(csv, NULL); 202 | } 203 | 204 | if (type == wbType_integer) { 205 | // printf("ReadXXXing as integer...\n"); 206 | data = csv_readAsInteger(file, seperator, rows, columns); 207 | } else { 208 | data = csv_readAsReal(file, seperator, rows, columns); 209 | } 210 | 211 | wbImportCSV_setData(csv, data); 212 | 213 | return csv; 214 | } 215 | 216 | static inline wbImportCSV_t wbImportCSV_readAsInteger(wbImportCSV_t csv) { 217 | return wbImportCSV_read(csv, wbType_integer); 218 | } 219 | 220 | static inline wbImportCSV_t wbImportCSV_readAsReal(wbImportCSV_t csv) { 221 | return wbImportCSV_read(csv, wbType_real); 222 | } 223 | 224 | static inline void wbImportRaw_setFile(wbImportRaw_t raw, 225 | const char *path) { 226 | if (raw != nullptr) { 227 | if (wbImportRaw_getFile(raw) != nullptr) { 228 | wbFile_delete(wbImportRaw_getFile(raw)); 229 | } 230 | if (path != nullptr) { 231 | wbImportRaw_getFile(raw) = wbFile_open(path, "r"); 232 | } else { 233 | wbImportRaw_getFile(raw) = nullptr; 234 | } 235 | } 236 | 237 | return; 238 | } 239 | 240 | static inline wbImportRaw_t wbImportRaw_new(void) { 241 | wbImportRaw_t raw; 242 | 243 | raw = wbNew(struct st_wbImportRaw_t); 244 | 245 | wbImportRaw_setRowCount(raw, -1); 246 | wbImportRaw_setColumnCount(raw, -1); 247 | wbImportRaw_setData(raw, NULL); 248 | wbImportRaw_getFile(raw) = nullptr; 249 | 250 | return raw; 251 | } 252 | 253 | static inline void wbImportRaw_delete(wbImportRaw_t raw) { 254 | if (raw != nullptr) { 255 | wbImportRaw_setFile(raw, NULL); 256 | if (wbImportRaw_getData(raw)) { 257 | wbDelete(wbImportRaw_getData(raw)); 258 | } 259 | wbDelete(raw); 260 | } 261 | } 262 | 263 | static inline wbBool lineHasSpace(const char *line) { 264 | while (*line != '\0') { 265 | if (*line == ' ') { 266 | return wbTrue; 267 | } 268 | line++; 269 | } 270 | return wbFalse; 271 | } 272 | 273 | static inline char *lineStrip(const char *line) { 274 | char *sl = wbString_duplicate(line); 275 | char *iter = sl; 276 | size_t slen = strlen(line); 277 | 278 | iter += slen - 1; 279 | while (*iter == '\0' || *iter == '\r' || *iter == '\t' || 280 | *iter == '\n' || *iter == ' ') { 281 | *iter-- = '\0'; 282 | } 283 | return sl; 284 | } 285 | 286 | static inline wbBool wbImportRaw_findDimensions(wbImportRaw_t raw) { 287 | if (raw != nullptr) { 288 | int rows; 289 | int columns; 290 | char *line; 291 | wbFile_t file; 292 | char *strippedLine; 293 | 294 | file = wbImportRaw_getFile(raw); 295 | 296 | wbFile_rewind(file); 297 | 298 | line = wbFile_readLine(file); 299 | 300 | if (line == nullptr) { 301 | return wbTrue; 302 | } 303 | 304 | strippedLine = lineStrip(line); 305 | 306 | if (lineHasSpace(strippedLine)) { 307 | sscanf(strippedLine, "%d %d", &rows, &columns); 308 | } else { 309 | columns = 1; 310 | sscanf(strippedLine, "%d", &rows); 311 | } 312 | 313 | wbImportRaw_setRowCount(raw, rows); 314 | wbImportRaw_setColumnCount(raw, columns); 315 | 316 | wbDelete(strippedLine); 317 | 318 | return wbFalse; 319 | } 320 | 321 | return wbTrue; 322 | } 323 | 324 | static inline wbImportRaw_t wbImportRaw_read(wbImportRaw_t raw, 325 | wbType_t type) { 326 | void *data; 327 | wbFile_t file; 328 | char seperator; 329 | int rows, columns; 330 | 331 | if (raw == nullptr) { 332 | return NULL; 333 | } 334 | 335 | if (wbImportRaw_getRowCount(raw) == -1 || 336 | wbImportRaw_getColumnCount(raw) == -1) { 337 | if (wbImportRaw_findDimensions(raw)) { 338 | wbLog(ERROR, "Failed to figure out raw dimensions."); 339 | return NULL; 340 | } 341 | } 342 | 343 | file = wbImportRaw_getFile(raw); 344 | seperator = ' '; 345 | rows = wbImportRaw_getRowCount(raw); 346 | columns = wbImportRaw_getColumnCount(raw); 347 | 348 | if (wbImportRaw_getData(raw) != nullptr) { 349 | wbDelete(wbImportRaw_getData(raw)); 350 | wbImportRaw_setData(raw, NULL); 351 | } 352 | 353 | if (type == wbType_integer) { 354 | // printf("Rdin gas integer...\n"); 355 | data = csv_readAsInteger(file, seperator, rows, columns); 356 | } else { 357 | data = csv_readAsReal(file, seperator, rows, columns); 358 | } 359 | 360 | wbImportRaw_setData(raw, data); 361 | 362 | return raw; 363 | } 364 | 365 | static inline wbImportRaw_t wbImportRaw_readAsInteger(wbImportRaw_t raw) { 366 | return wbImportRaw_read(raw, wbType_integer); 367 | } 368 | 369 | static inline wbImportRaw_t wbImportRaw_readAsReal(wbImportRaw_t raw) { 370 | return wbImportRaw_read(raw, wbType_real); 371 | } 372 | 373 | static inline wbImportText_t wbImportText_new(void) { 374 | wbImportText_t text; 375 | 376 | text = wbNew(struct st_wbImportText_t); 377 | 378 | wbImportText_setLength(text, 0); 379 | wbImportText_setData(text, NULL); 380 | wbImportText_getFile(text) = nullptr; 381 | 382 | return text; 383 | } 384 | 385 | static inline void wbImportText_setFile(wbImportText_t text, 386 | const char *path) { 387 | if (text != nullptr) { 388 | if (wbImportText_getFile(text) != nullptr) { 389 | wbFile_delete(wbImportText_getFile(text)); 390 | } 391 | if (path != nullptr) { 392 | wbImportText_getFile(text) = wbFile_open(path, "r"); 393 | } else { 394 | wbImportText_getFile(text) = nullptr; 395 | } 396 | } 397 | 398 | return; 399 | } 400 | 401 | static inline void wbImportText_delete(wbImportText_t text) { 402 | if (text != nullptr) { 403 | wbImportText_setFile(text, NULL); 404 | if (wbImportText_getData(text)) { 405 | wbDelete(wbImportText_getData(text)); 406 | } 407 | wbDelete(text); 408 | } 409 | } 410 | 411 | static inline wbImportText_t wbImportText_read(wbImportText_t text) { 412 | char *data; 413 | wbFile_t file; 414 | int length; 415 | 416 | if (text == nullptr) { 417 | return NULL; 418 | } 419 | 420 | file = wbImportText_getFile(text); 421 | 422 | if (wbImportText_getData(text) != nullptr) { 423 | wbDelete(wbImportText_getData(text)); 424 | wbImportText_setData(text, NULL); 425 | } 426 | 427 | length = wbFile_size(file); 428 | data = wbFile_read(file, length); 429 | 430 | wbImportText_setData(text, data); 431 | wbImportText_setLength(text, length); 432 | 433 | return text; 434 | } 435 | 436 | static inline wbImport_t wbImport_open(const char *file, 437 | wbImportKind_t kind) { 438 | wbImport_t imp; 439 | 440 | if (file == nullptr) { 441 | wbLog(ERROR, "Go NULL for file value."); 442 | wbExit(); 443 | } 444 | 445 | if (!wbFile_existsQ(file)) { 446 | wbLog(ERROR, "File ", file, " does not exist."); 447 | wbExit(); 448 | } 449 | 450 | wbImport_setKind(imp, kind); 451 | 452 | if (kind == wbImportKind_raw) { 453 | wbImportRaw_t raw = wbImportRaw_new(); 454 | wbImportRaw_setFile(raw, file); 455 | wbImport_setRaw(imp, raw); 456 | } else if (kind == wbImportKind_tsv || kind == wbImportKind_csv) { 457 | wbImportCSV_t csv = wbImportCSV_new(); 458 | if (kind == wbImportKind_csv) { 459 | wbImportCSV_setSeperator(csv, ','); 460 | } else { 461 | wbImportCSV_setSeperator(csv, '\t'); 462 | } 463 | wbImportCSV_setFile(csv, file); 464 | wbImport_setCSV(imp, csv); 465 | } else if (kind == wbImportKind_text) { 466 | wbImportText_t text = wbImportText_new(); 467 | wbImportText_setFile(text, file); 468 | wbImport_setText(imp, text); 469 | } else if (kind == wbImportKind_ppm) { 470 | wbImage_t img = wbPPM_import(file); 471 | wbImport_setImage(imp, img); 472 | } else { 473 | wbLog(ERROR, "Invalid import type."); 474 | wbExit(); 475 | } 476 | 477 | return imp; 478 | } 479 | 480 | static inline wbImport_t wbImport_open(const char *file, 481 | const char *type0) { 482 | wbImport_t imp; 483 | wbImportKind_t kind; 484 | char *type; 485 | 486 | type = wbString_toLower(type0); 487 | 488 | if (wbString_sameQ(type, "csv")) { 489 | kind = wbImportKind_csv; 490 | } else if (wbString_sameQ(type, "tsv")) { 491 | kind = wbImportKind_tsv; 492 | } else if (wbString_sameQ(type, "raw") || wbString_sameQ(type, "dat")) { 493 | kind = wbImportKind_raw; 494 | } else if (wbString_sameQ(type, "ppm")) { 495 | kind = wbImportKind_ppm; 496 | } else if (wbString_sameQ(type, "text") || wbString_sameQ(type, "txt")) { 497 | kind = wbImportKind_text; 498 | } else { 499 | wbLog(ERROR, "Invalid import type ", type0); 500 | wbExit(); 501 | } 502 | 503 | imp = wbImport_open(file, kind); 504 | 505 | wbDelete(type); 506 | 507 | return imp; 508 | } 509 | 510 | static inline void wbImport_close(wbImport_t imp) { 511 | wbImportKind_t kind; 512 | 513 | kind = wbImport_getKind(imp); 514 | if (kind == wbImportKind_tsv || kind == wbImportKind_csv) { 515 | wbImportCSV_t csv = wbImport_getCSV(imp); 516 | wbImportCSV_delete(csv); 517 | wbImport_setCSV(imp, NULL); 518 | } else if (kind == wbImportKind_raw) { 519 | wbImportRaw_t raw = wbImport_getRaw(imp); 520 | wbImportRaw_delete(raw); 521 | wbImport_setRaw(imp, NULL); 522 | } else if (kind == wbImportKind_text) { 523 | wbImportText_t text = wbImport_getText(imp); 524 | wbImportText_delete(text); 525 | wbImport_setText(imp, NULL); 526 | } else if (kind == wbImportKind_ppm) { 527 | } else { 528 | wbLog(ERROR, "Invalid import type."); 529 | wbExit(); 530 | } 531 | return; 532 | } 533 | 534 | static inline void *wbImport_read(wbImport_t imp, wbType_t type) { 535 | void *data = nullptr; 536 | wbImportKind_t kind; 537 | 538 | kind = wbImport_getKind(imp); 539 | if (kind == wbImportKind_tsv || kind == wbImportKind_csv) { 540 | wbImportCSV_t csv = wbImport_getCSV(imp); 541 | wbImportCSV_read(csv, type); 542 | data = wbImportCSV_getData(csv); 543 | } else if (kind == wbImportKind_raw) { 544 | wbImportRaw_t raw = wbImport_getRaw(imp); 545 | wbImportRaw_read(raw, type); 546 | data = wbImportRaw_getData(raw); 547 | } else if (wbImportKind_text == kind) { 548 | wbImportText_t text = wbImport_getText(imp); 549 | text = wbImportText_read(text); 550 | data = wbImportText_getData(text); 551 | 552 | } else { 553 | wbLog(ERROR, "Invalid import type."); 554 | wbExit(); 555 | } 556 | return data; 557 | } 558 | 559 | static inline int *wbImport_readAsInteger(wbImport_t imp) { 560 | void *data = wbImport_read(imp, wbType_integer); 561 | return (int *)data; 562 | } 563 | 564 | static inline wbReal_t *wbImport_readAsReal(wbImport_t imp) { 565 | void *data = wbImport_read(imp, wbType_real); 566 | return (wbReal_t *)data; 567 | } 568 | 569 | static inline wbChar_t *wbImport_readAsText(wbImport_t imp) { 570 | void *data = wbImport_read(imp, wbType_ubit8); 571 | return (wbChar_t *)data; 572 | } 573 | 574 | static wbImportKind_t _parseImportExtension(const char *file) { 575 | char *extension; 576 | wbImportKind_t kind; 577 | 578 | extension = wbFile_extension(file); 579 | 580 | if (wbString_sameQ(extension, "csv")) { 581 | kind = wbImportKind_csv; 582 | } else if (wbString_sameQ(extension, "tsv")) { 583 | kind = wbImportKind_tsv; 584 | } else if (wbString_sameQ(extension, "raw") || 585 | wbString_sameQ(extension, "dat")) { 586 | kind = wbImportKind_raw; 587 | } else if (wbString_sameQ(extension, "ppm") || 588 | wbString_sameQ(extension, "pbm")) { 589 | kind = wbImportKind_ppm; 590 | } else if (wbString_sameQ(extension, "text") || 591 | wbString_sameQ(extension, "txt")) { 592 | kind = wbImportKind_text; 593 | } else { 594 | kind = wbImportKind_unknown; 595 | wbLog(ERROR, "File ", file, " does not have a compatible extension."); 596 | } 597 | 598 | wbDelete(extension); 599 | 600 | return kind; 601 | } 602 | 603 | void *wbImport(const char *file, int *resRows, int *resColumns, 604 | const char *type) { 605 | void *data, *res; 606 | wbImport_t imp; 607 | size_t sz; 608 | int columns = 0, rows = 0; 609 | wbImportKind_t kind; 610 | 611 | if (file == nullptr) { 612 | fprintf(stderr, "Failed to import file.\n"); 613 | wbExit(); 614 | } 615 | 616 | kind = _parseImportExtension(file); 617 | 618 | wbAssert(kind != wbImportKind_unknown); 619 | 620 | imp = wbImport_open(file, kind); 621 | if (wbString_sameQ(type, "Real")) { 622 | data = wbImport_readAsReal(imp); 623 | sz = sizeof(wbReal_t); 624 | } else if (wbString_sameQ(type, "Text")) { 625 | data = wbImport_readAsText(imp); 626 | sz = sizeof(char); 627 | } else { 628 | // printf("Reading as integer..d\n"); 629 | data = wbImport_readAsInteger(imp); 630 | sz = sizeof(int); 631 | } 632 | 633 | if (kind == wbImportKind_csv || kind == wbImportKind_tsv) { 634 | rows = wbImportCSV_getRowCount(wbImport_getCSV(imp)); 635 | columns = wbImportCSV_getColumnCount(wbImport_getCSV(imp)); 636 | } else if (kind == wbImportKind_raw) { 637 | rows = wbImportRaw_getRowCount(wbImport_getRaw(imp)); 638 | columns = wbImportRaw_getColumnCount(wbImport_getRaw(imp)); 639 | } else if (kind == wbImportKind_text) { 640 | rows = 1; 641 | columns = wbImportText_getLength(wbImport_getText(imp)); 642 | } 643 | 644 | if (rows == 1 && columns > 0) { 645 | rows = columns; 646 | columns = 1; 647 | } 648 | 649 | if (resRows != nullptr) { 650 | *resRows = rows; 651 | } 652 | 653 | if (resColumns != nullptr) { 654 | *resColumns = columns; 655 | } 656 | 657 | res = wbMalloc(sz * rows * columns); 658 | memcpy(res, data, sz * rows * columns); 659 | 660 | wbImport_close(imp); 661 | 662 | return res; 663 | } 664 | 665 | void *wbImport(const char *file, int *rows, int *columns) { 666 | return wbImport(file, rows, columns, "Real"); 667 | } 668 | 669 | EXTERN_C void *wbImport(const char *file, int *rows) { 670 | return wbImport(file, rows, NULL, "Real"); 671 | } 672 | 673 | void *wbImport(const char *file, int *res_rows, const char *type) { 674 | int cols, rows; 675 | void *res = wbImport(file, &rows, &cols, type); 676 | if (rows == 1 && cols > 1) { 677 | rows = cols; 678 | } 679 | *res_rows = rows; 680 | return res; 681 | } 682 | 683 | wbImage_t wbImport(const char *file) { 684 | wbImage_t img; 685 | wbImport_t imp; 686 | wbImportKind_t kind; 687 | 688 | if (file == nullptr) { 689 | fprintf(stderr, "Failed to import file.\n"); 690 | wbExit(); 691 | } 692 | 693 | kind = _parseImportExtension(file); 694 | 695 | wbAssert(kind == wbImportKind_ppm); 696 | 697 | imp = wbImport_open(file, kind); 698 | img = wbImport_getImage(imp); 699 | wbImport_close(imp); 700 | 701 | return img; 702 | } 703 | 704 | int wbImport_flag(const char *file) { 705 | int res; 706 | wbFile_t fh = wbFile_open(file, "r"); 707 | const char *line = wbFile_readLine(fh); 708 | sscanf(line, "%d", &res); 709 | wbFile_close(fh); 710 | return res; 711 | } 712 | --------------------------------------------------------------------------------