tmp
This commit is contained in:
parent
84eaa8c169
commit
51fa6d6eef
@ -12,6 +12,9 @@ option(GCTL_EEMD "Use the EEMD library" ON)
|
||||
option(GCTL_OPENBLAS "Use the Openblas library" OFF)
|
||||
option(GCTL_CHECK_BOUNDER "Check array's index" OFF)
|
||||
option(GCTL_CHECK_SIZE "Check array's size" OFF)
|
||||
# 传递安装地址给编译期宏变量
|
||||
option(GCTL_INSTALL_PREFIX "Pass the install directory." ON)
|
||||
set(DIR_VAR ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
message(STATUS "Platform: " ${CMAKE_HOST_SYSTEM_NAME})
|
||||
message(STATUS "Install prefix: " ${CMAKE_INSTALL_PREFIX})
|
||||
@ -79,4 +82,5 @@ configure_file(
|
||||
|
||||
# 添加库源文件地址
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(example)
|
||||
add_subdirectory(example)
|
||||
add_subdirectory(tool)
|
@ -1,3 +1,4 @@
|
||||
#cmakedefine GCTL_INSTALL_PREFIX "${DIR_VAR}"
|
||||
#cmakedefine GCTL_OPENMP
|
||||
#cmakedefine GCTL_NETCDF
|
||||
#cmakedefine GCTL_FFTW3
|
||||
|
@ -1,3 +1,4 @@
|
||||
#define GCTL_INSTALL_PREFIX "/opt/stow/gctl"
|
||||
#define GCTL_OPENMP
|
||||
#define GCTL_NETCDF
|
||||
#define GCTL_FFTW3
|
||||
|
@ -427,4 +427,11 @@ void gctl::parse_string_with_quotes(std::string in_str, std::vector<std::string>
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void gctl::parse_filename(std::string filename, std::string &naked_name, std::string &exten_name)
|
||||
{
|
||||
naked_name = filename.substr(0, filename.rfind("."));
|
||||
exten_name = filename.substr(filename.find_last_of('.'));
|
||||
return;
|
||||
}
|
@ -188,6 +188,15 @@ namespace gctl
|
||||
* @param str_vec 输出字符串向量
|
||||
*/
|
||||
void parse_string_with_quotes(std::string in_str, std::vector<std::string> &str_vec);
|
||||
|
||||
/**
|
||||
* @brief 解析文件路径
|
||||
*
|
||||
* @param in_str 输入字符串
|
||||
* @param naked_name 不含后缀的文件名
|
||||
* @param exten_name 文件后缀名
|
||||
*/
|
||||
void parse_filename(std::string filename, std::string &naked_name, std::string &exten_name);
|
||||
}
|
||||
|
||||
#endif // _GCTL_STREAM_H
|
2
tool/CMakeLists.txt
Normal file
2
tool/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
# add directories to compile the tool
|
||||
add_subdirectory(dsviewer)
|
24
tool/dsviewer/CMakeLists.txt
Normal file
24
tool/dsviewer/CMakeLists.txt
Normal file
@ -0,0 +1,24 @@
|
||||
set(TOOL_NAME dsviewer)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(EDITLINE REQUIRED libeditline)
|
||||
include_directories(${EDITLINE_INCLUDE_DIRS})
|
||||
link_directories(${EDITLINE_LIBRARY_DIRS})
|
||||
|
||||
aux_source_directory(. TOOL_SRC)
|
||||
add_executable(${TOOL_NAME} ${TOOL_SRC})
|
||||
|
||||
set_target_properties(${TOOL_NAME} PROPERTIES INSTALL_RPATH /usr/local/lib)
|
||||
set_target_properties(${TOOL_NAME} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
target_link_libraries(${TOOL_NAME} PRIVATE gctl)
|
||||
target_link_libraries(${TOOL_NAME} PRIVATE ${EDITLINE_LIBRARIES})
|
||||
|
||||
install(TARGETS ${TOOL_NAME} RUNTIME DESTINATION sbin)
|
||||
|
||||
file(GLOB HELP_DOC *.md)
|
||||
install(FILES ${HELP_DOC} DESTINATION sbin/share)
|
345
tool/dsviewer/dsviewer.cpp
Normal file
345
tool/dsviewer/dsviewer.cpp
Normal file
@ -0,0 +1,345 @@
|
||||
/********************************************************
|
||||
* ██████╗ ██████╗████████╗██╗
|
||||
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
||||
* ██║ ███╗██║ ██║ ██║
|
||||
* ██║ ██║██║ ██║ ██║
|
||||
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
||||
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
||||
* Geophysical Computational Tools & Library (GCTL)
|
||||
*
|
||||
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
|
||||
*
|
||||
* GCTL is distributed under a dual licensing scheme. You can redistribute
|
||||
* it and/or modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation, either version 2
|
||||
* of the License, or (at your option) any later version. You should have
|
||||
* received a copy of the GNU Lesser General Public License along with this
|
||||
* program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* If the terms and conditions of the LGPL v.2. would prevent you from using
|
||||
* the GCTL, please consider the option to obtain a commercial license for a
|
||||
* fee. These licenses are offered by the GCTL's original author. As a rule,
|
||||
* licenses are provided "as-is", unlimited in time for a one time fee. Please
|
||||
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
|
||||
* to include some description of your company and the realm of its activities.
|
||||
* Also add information on how to contact you by electronic and paper mail.
|
||||
******************************************************/
|
||||
|
||||
#include "dsviewer.h"
|
||||
// We use the editline library to handle all inputs
|
||||
#include "editline.h"
|
||||
|
||||
cmd_pair curr_cmd; // Executing command
|
||||
gctl::text_content tc; // Grid object
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
* Strip whitespace from the start and end of STRING. Return a pointer
|
||||
* into STRING.
|
||||
*/
|
||||
char *stripwhite(char *string)
|
||||
{
|
||||
char *s, *t;
|
||||
|
||||
for (s = string; isspace(*s); s++) ;
|
||||
|
||||
if (*s == 0)
|
||||
return s;
|
||||
|
||||
t = s + strlen(s) - 1;
|
||||
while (t > s && isspace(*t))
|
||||
t--;
|
||||
*++t = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Generator function for command completion. STATE lets us
|
||||
know whether to start from scratch; without any state
|
||||
(i.e. STATE == 0), then we start at the top of the list. */
|
||||
char *command_generator(const char *text, int state)
|
||||
{
|
||||
static int list_index, len;
|
||||
|
||||
/* If this is a new word to complete, initialize now. This
|
||||
includes saving the length of TEXT for efficiency, and
|
||||
initializing the index variable to 0. */
|
||||
if (!state)
|
||||
{
|
||||
list_index = 0;
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
/* Return the next name which partially matches from the command list. */
|
||||
while (list_index < CMD_NUM)
|
||||
{
|
||||
if (std::string(text) == commands[list_index].name.substr(0, len))
|
||||
{
|
||||
//const char* name = commands[list_index].name.data();
|
||||
return strdup(commands[list_index].name.data());
|
||||
}
|
||||
else list_index++;
|
||||
}
|
||||
|
||||
/* If no names matched, then return NULL. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to complete on the contents of TEXT. START and END
|
||||
* bound the region of rl_line_buffer that contains the word to
|
||||
* complete. TEXT is the word to complete. We can use the entire
|
||||
* contents of rl_line_buffer in case we want to do some simple
|
||||
* parsing. Return the array of matches, or NULL if there aren't any.
|
||||
*/
|
||||
char **gridmanager_completion(const char *text, int start, int end)
|
||||
{
|
||||
char **matches = nullptr;
|
||||
|
||||
/* If this word is at the start of the line, then it is a command
|
||||
to complete. Otherwise it is the name of a file in the current
|
||||
directory. */
|
||||
if (start == 0) matches = rl_completion_matches(text, command_generator);
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
void initialize_readline(void)
|
||||
{
|
||||
/* Allow conditional parsing of the ~/.inputrc file. */
|
||||
rl_readline_name = "gridmanager";
|
||||
|
||||
/* Tell the completer that we want a crack first. */
|
||||
rl_attempted_completion_function = gridmanager_completion;
|
||||
}
|
||||
|
||||
} // End C section
|
||||
|
||||
void display_cmds()
|
||||
{
|
||||
std::clog << "Command:\n";
|
||||
for (size_t i = 0; i < CMD_NUM - 1; i++)
|
||||
{
|
||||
std::clog << std::setw(12) << commands[i].name << ":\t" << commands[i].brief << "\n";
|
||||
}
|
||||
|
||||
std::clog << "\nEnter \"<command>?\" to see detailed instructions.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void display_help(std::string input_cmd)
|
||||
{
|
||||
std::string install_dir = GCTL_INSTALL_PREFIX;
|
||||
std::ifstream helpin;
|
||||
open_infile(helpin, install_dir + "/sbin/share/dsviewer", ".md");
|
||||
|
||||
std::string tmp_l, tmp_help;
|
||||
std::vector<std::string> cmds;
|
||||
std::vector<std::string> helps;
|
||||
while (getline(helpin, tmp_l))
|
||||
{
|
||||
if (tmp_l.substr(0, 4) == "####")
|
||||
{
|
||||
cmds.push_back(tmp_l.substr(5));
|
||||
tmp_help = "";
|
||||
while (getline(helpin, tmp_l))
|
||||
{
|
||||
if (tmp_l == "") break;
|
||||
else tmp_help += tmp_l + "\n";
|
||||
}
|
||||
helps.push_back(tmp_help);
|
||||
}
|
||||
}
|
||||
helpin.close();
|
||||
|
||||
std::string cmd_str;
|
||||
for (size_t j = 0; j < cmds.size(); j++)
|
||||
{
|
||||
parse_string_to_value(cmds[j], ' ', true, cmd_str);
|
||||
if (input_cmd == cmd_str)
|
||||
{
|
||||
replace_all(tmp_l, cmds[j], "\\", "");
|
||||
std::cout << GCTL_BOLDGREEN << tmp_l << GCTL_RESET << "\n";
|
||||
std::cout << helps[j] << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void exec_cmd(std::string cmd)
|
||||
{
|
||||
std::string cmd_name;
|
||||
parse_string_to_value(cmd, ' ', true, cmd_name);
|
||||
|
||||
// show instruction if there is a question mark at end of the command
|
||||
if (cmd_name.back() == '?')
|
||||
{
|
||||
cmd_name = cmd_name.substr(0, cmd_name.length() - 1);
|
||||
display_help(cmd_name);
|
||||
return;
|
||||
}
|
||||
|
||||
// set default command to null
|
||||
curr_cmd = commands[CMD_NUM - 1];
|
||||
for (size_t i = 0; i < CMD_NUM - 1; i++)
|
||||
{
|
||||
if (cmd_name == commands[i].name)
|
||||
{
|
||||
curr_cmd = commands[i]; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (curr_cmd.func_p == nullptr) throw gctl::runtime_error("Invalid command: " + cmd_name);
|
||||
|
||||
std::vector<std::string> cmd_units;
|
||||
parse_string_with_quotes(cmd, cmd_units);
|
||||
|
||||
return curr_cmd.func_p(cmd_units);
|
||||
}
|
||||
|
||||
// This function is defined to avoid potential breakdown while running in script mode.
|
||||
void quit(const std::vector<std::string> &cmd_units)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void info(const std::vector<std::string> &cmd_units)
|
||||
{
|
||||
if (cmd_units.size() == 1) // cmd_units[0] == info
|
||||
{
|
||||
tc.info();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void load_file(const std::vector<std::string> &cmd_units)
|
||||
{
|
||||
// load <file> [nohead|hashead] [<delimeter>] [tag_sym] [att_sym] [head_num]
|
||||
if (cmd_units.size() < 2) throw std::runtime_error("open: insufficient parameters.");
|
||||
|
||||
gctl::array<std::string> copy_str(5, "null");
|
||||
for (size_t i = 0; i < GCTL_MIN(cmd_units.size() - 2, 5); i++)
|
||||
{
|
||||
copy_str[i] = cmd_units[i + 2];
|
||||
}
|
||||
|
||||
text_head_type_e ht = NoColumnName;
|
||||
if (copy_str[0] == "nohead") ht = NoColumnName;
|
||||
else if (copy_str[0] == "hashead") ht = HasColumnName;
|
||||
|
||||
if (copy_str[1] != "null") tc.set_delimeter(copy_str[1][0]);
|
||||
if (copy_str[2] != "null") tc.set_tag_symbol(copy_str[2][0]);
|
||||
if (copy_str[3] != "null") tc.set_annotation_symbol(copy_str[3][0]);
|
||||
|
||||
int hnum = 0;
|
||||
if (copy_str[4] != "null") hnum = atoi(copy_str[4].c_str());
|
||||
if (hnum != 0) tc.set_head_number(hnum);
|
||||
|
||||
std::string naked_name, exten_name;
|
||||
parse_filename(cmd_units[1], naked_name, exten_name);
|
||||
|
||||
if (exten_name == ".csv") tc.load_csv(naked_name);
|
||||
else tc.load_text(naked_name, exten_name, ht);
|
||||
return;
|
||||
}
|
||||
|
||||
void save_file(const std::vector<std::string> &cmd_units)
|
||||
{
|
||||
// save <file> [<delimeter>] [tag_sym] [att_sym]
|
||||
if (cmd_units.size() < 2) throw std::runtime_error("save: insufficient parameters.");
|
||||
|
||||
gctl::array<std::string> copy_str(3, "null");
|
||||
for (size_t i = 0; i < GCTL_MIN(cmd_units.size() - 2, 3); i++)
|
||||
{
|
||||
copy_str[i] = cmd_units[i + 2];
|
||||
}
|
||||
|
||||
if (copy_str[0] != "null") tc.set_delimeter(copy_str[0][0]);
|
||||
if (copy_str[1] != "null") tc.set_tag_symbol(copy_str[1][0]);
|
||||
if (copy_str[2] != "null") tc.set_annotation_symbol(copy_str[2][0]);
|
||||
|
||||
std::string naked_name, exten_name;
|
||||
parse_filename(cmd_units[1], naked_name, exten_name);
|
||||
|
||||
if (exten_name == ".csv") tc.save_csv(naked_name);
|
||||
else tc.save_text(naked_name, exten_name);
|
||||
return;
|
||||
}
|
||||
|
||||
void statistic(const std::vector<std::string> &cmd_units)
|
||||
{
|
||||
// stats <column> <column>...
|
||||
if (cmd_units.size() < 2) throw std::runtime_error("stats: insufficient parameters.");
|
||||
|
||||
_1d_array data;
|
||||
for (size_t i = 1; i < cmd_units.size(); i++)
|
||||
{
|
||||
tc.get_column(cmd_units[i], data);
|
||||
std::clog << "column: " << cmd_units[i]
|
||||
<< " | " << data.min() << "/" << data.mean() << "/" << data.max()
|
||||
<< " | STD: " << data.std() << "\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc >= 2)
|
||||
{
|
||||
std::string tmp_l;
|
||||
std::ifstream cmdin;
|
||||
|
||||
// Run commands from files. Each line is a command.
|
||||
// You can give more than one file
|
||||
for (size_t i = 1; i < argc; i++) try
|
||||
{
|
||||
open_infile(cmdin, argv[i]);
|
||||
while (getline(cmdin, tmp_l) && tmp_l != "" && tmp_l[0] != '#')
|
||||
{
|
||||
exec_cmd(tmp_l);
|
||||
}
|
||||
cmdin.close();
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, "run dsviewer in the interactive mode for instructions.", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setlocale(LC_CTYPE, "");
|
||||
initialize_readline(); /* Bind our completer. */
|
||||
|
||||
display_logo();
|
||||
std::clog << "dsviewer - read, manipulate and write dsv/csv files.\n";
|
||||
std::clog << "Enter '?' to see all available commands.\n";
|
||||
|
||||
std::string cmd_str;
|
||||
char *c_line = (char *)NULL;
|
||||
char *c_line_s = (char *)NULL;
|
||||
bool quit = false;
|
||||
|
||||
while (!quit) try
|
||||
{
|
||||
c_line = readline(">> ");
|
||||
if (!c_line) break;
|
||||
|
||||
c_line_s = stripwhite(c_line);
|
||||
cmd_str = c_line_s;
|
||||
|
||||
if (cmd_str == "quit") quit = true;
|
||||
else if (cmd_str == "?") display_cmds();
|
||||
else exec_cmd(cmd_str);
|
||||
|
||||
free(c_line);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, "Enter 'help' for instructions.", 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
62
tool/dsviewer/dsviewer.h
Normal file
62
tool/dsviewer/dsviewer.h
Normal file
@ -0,0 +1,62 @@
|
||||
/********************************************************
|
||||
* ██████╗ ██████╗████████╗██╗
|
||||
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
||||
* ██║ ███╗██║ ██║ ██║
|
||||
* ██║ ██║██║ ██║ ██║
|
||||
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
||||
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
||||
* Geophysical Computational Tools & Library (GCTL)
|
||||
*
|
||||
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
|
||||
*
|
||||
* GCTL is distributed under a dual licensing scheme. You can redistribute
|
||||
* it and/or modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation, either version 2
|
||||
* of the License, or (at your option) any later version. You should have
|
||||
* received a copy of the GNU Lesser General Public License along with this
|
||||
* program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* If the terms and conditions of the LGPL v.2. would prevent you from using
|
||||
* the GCTL, please consider the option to obtain a commercial license for a
|
||||
* fee. These licenses are offered by the GCTL's original author. As a rule,
|
||||
* licenses are provided "as-is", unlimited in time for a one time fee. Please
|
||||
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
|
||||
* to include some description of your company and the realm of its activities.
|
||||
* Also add information on how to contact you by electronic and paper mail.
|
||||
******************************************************/
|
||||
|
||||
#ifndef GCTL_DSVIEWER_H
|
||||
#define GCTL_DSVIEWER_H
|
||||
|
||||
#include "../../lib/gctl_config.h"
|
||||
#include "../../lib/io.h"
|
||||
|
||||
using namespace gctl;
|
||||
|
||||
// Function pointer for commands
|
||||
typedef void (*cmd_func_ptr)(const std::vector<std::string> &cmd_units);
|
||||
|
||||
struct cmd_pair
|
||||
{
|
||||
std::string name;
|
||||
cmd_func_ptr func_p;
|
||||
std::string brief;
|
||||
};
|
||||
|
||||
void quit(const std::vector<std::string> &cmd_units);
|
||||
void info(const std::vector<std::string> &cmd_units);
|
||||
void load_file(const std::vector<std::string> &cmd_units);
|
||||
void save_file(const std::vector<std::string> &cmd_units);
|
||||
void statistic(const std::vector<std::string> &cmd_units);
|
||||
|
||||
#define CMD_NUM 6
|
||||
const cmd_pair commands[CMD_NUM] = {
|
||||
{"quit", quit, "Quit the program."},
|
||||
{"info", info, "Show the table information."},
|
||||
{"open", load_file, "Open a dsv/csv file."},
|
||||
{"save", save_file, "Save the table to a file."},
|
||||
{"stats", statistic, "Calculate statistics of the selected columns."},
|
||||
{"null", nullptr, "null"}
|
||||
};
|
||||
|
||||
#endif // GCTL_DSVIEWER_H
|
14
tool/dsviewer/dsviewer.md
Normal file
14
tool/dsviewer/dsviewer.md
Normal file
@ -0,0 +1,14 @@
|
||||
#### quit
|
||||
Does what it says.
|
||||
|
||||
#### info
|
||||
Show the table information.
|
||||
|
||||
#### open \<file\> [hashead|nohead] [\<delimeter\>] [\<tag-sym\>] [\<att-sym\>]
|
||||
Open a dsv/csv file
|
||||
|
||||
#### save
|
||||
Save table to a dsv/csv file
|
||||
|
||||
#### stats \<column\> \<column\>...
|
||||
Show statistics of a data column or columns.
|
Loading…
Reference in New Issue
Block a user