Skip to content

Commit 08f21fb

Browse files
committed
Added a dependency to Exprtk. The library is downloaded and used automatically. The project libeval was created to wrap exprtk library for easier usage.
Implemented Validator::SetExprtk() and Validator::GetExprtk() with tests. Created the following new properties: `selection.count`, `selection.files.count` and `selection.directories.count`. For issue #23.
1 parent ab055c9 commit 08f21fb

File tree

8 files changed

+310
-20
lines changed

8 files changed

+310
-20
lines changed

CMakeLists.txt

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,42 @@ find_package(WIX)
88
find_package(NSIS)
99
find_package(GRIP)
1010

11+
##############################################################################################################################################
12+
# Dependencies
13+
##############################################################################################################################################
14+
15+
# packages directory
16+
set(PACKAGE_DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external)
17+
if(NOT EXISTS ${PACKAGE_DOWNLOAD_DIR})
18+
file(MAKE_DIRECTORY ${PACKAGE_DOWNLOAD_DIR})
19+
endif()
20+
21+
# exprtk
22+
# As the time of this writing, HEAD revision is commit d312ba91419c9cb12c8279fd3a19096d39dfcb5e
23+
# available at https://github.com/ArashPartow/exprtk/archive/d312ba91419c9cb12c8279fd3a19096d39dfcb5e.zip
24+
# Using latest revision to get all bug fixes.
25+
set(EXPRTK_PACKAGE_URL "https://github.com/ArashPartow/exprtk/archive/master.zip")
26+
set(EXPRTK_PACKAGE_PATH ${PACKAGE_DOWNLOAD_DIR}/exprtk.zip)
27+
if(NOT EXISTS ${EXPRTK_PACKAGE_PATH})
28+
message(STATUS "Downloading exprtk package from ${EXPRTK_PACKAGE_URL}")
29+
file(DOWNLOAD ${EXPRTK_PACKAGE_URL} ${EXPRTK_PACKAGE_PATH}
30+
TIMEOUT 60 # seconds
31+
TLS_VERIFY ON
32+
)
33+
34+
message(STATUS "Extracting exprtk package to ${EXPRTK_PACKAGE_PATH}")
35+
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf
36+
${EXPRTK_PACKAGE_PATH}
37+
WORKING_DIRECTORY ${PACKAGE_DOWNLOAD_DIR}
38+
)
39+
endif()
40+
set(EXPRTK_HEADER_PATH ${PACKAGE_DOWNLOAD_DIR}/exprtk-master/exprtk.hpp)
41+
if(EXISTS ${EXPRTK_HEADER_PATH})
42+
message(STATUS "Found exprtk header file: ${EXPRTK_HEADER_PATH}")
43+
else()
44+
message(FATAL_ERROR "exprtk header file not found.")
45+
endif()
46+
1147
##############################################################################################################################################
1248
# Standard CMake variables
1349
##############################################################################################################################################
@@ -187,25 +223,25 @@ endif()
187223
set (README_FILENAME README.md)
188224
set (USERMANUAL_FILENAME UserManual.md)
189225

190-
if (GRIP_FOUND)
191-
# Convert README.md
192-
execute_process(COMMAND grip README.md --export README.html --user-content --context=end2endzone/ShellAnything RESULT_VARIABLE res_var WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
193-
if("${res_var}" STREQUAL "0")
194-
set (README_FILENAME README.html)
195-
else()
196-
message(FATAL_ERROR "grip failed converting README.md with res_var='${res_var}'")
197-
endif()
198-
199-
# Convert UserManual.md
200-
execute_process(COMMAND grip UserManual.md --export UserManual.html --user-content --context=end2endzone/ShellAnything RESULT_VARIABLE res_var WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
201-
if("${res_var}" STREQUAL "0")
202-
set (USERMANUAL_FILENAME UserManual.html)
203-
else()
204-
message(FATAL_ERROR "grip failed converting UserManual.md with res_var='${res_var}'")
205-
endif()
206-
else()
207-
message(WARNING "grip is not found on the system. grip is required for publishing markdown files to html. Files will be published as *.md files.")
208-
endif()
226+
# if (GRIP_FOUND)
227+
# # Convert README.md
228+
# execute_process(COMMAND grip README.md --export README.html --user-content --context=end2endzone/ShellAnything RESULT_VARIABLE res_var WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
229+
# if("${res_var}" STREQUAL "0")
230+
# set (README_FILENAME README.html)
231+
# else()
232+
# message(FATAL_ERROR "grip failed converting README.md with res_var='${res_var}'")
233+
# endif()
234+
#
235+
# # Convert UserManual.md
236+
# execute_process(COMMAND grip UserManual.md --export UserManual.html --user-content --context=end2endzone/ShellAnything RESULT_VARIABLE res_var WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
237+
# if("${res_var}" STREQUAL "0")
238+
# set (USERMANUAL_FILENAME UserManual.html)
239+
# else()
240+
# message(FATAL_ERROR "grip failed converting UserManual.md with res_var='${res_var}'")
241+
# endif()
242+
# else()
243+
# message(WARNING "grip is not found on the system. grip is required for publishing markdown files to html. Files will be published as *.md files.")
244+
# endif()
209245

210246

211247
##############################################################################################################################################

include/shellanything/Validator.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ namespace shellanything
114114
/// </summary>
115115
void SetPattern(const std::string & iPattern);
116116

117+
/// <summary>
118+
/// Getter for the 'exprtk' parameter.
119+
/// </summary>
120+
const std::string & GetExprtk() const;
121+
122+
/// <summary>
123+
/// Setter for the 'exprtk' parameter.
124+
/// </summary>
125+
void SetExprtk(const std::string & iExprtk);
126+
117127
/// <summary>
118128
/// Getter for the 'inserve' parameter.
119129
/// </summary>
@@ -152,6 +162,7 @@ namespace shellanything
152162
bool ValidateClass(const Context & context, const std::string & class_, bool inversed) const;
153163
bool ValidateClassSingle(const Context & context, const std::string & class_, bool inversed) const;
154164
bool ValidatePattern(const Context & context, const std::string & pattern, bool inversed) const;
165+
bool ValidateExprtk(const Context & context, const std::string & exprtk, bool inversed) const;
155166

156167
private:
157168
int mMaxFiles;
@@ -161,6 +172,7 @@ namespace shellanything
161172
std::string mFileExists;
162173
std::string mClass;
163174
std::string mPattern;
175+
std::string mExprtk;
164176
std::string mInverse;
165177
};
166178

src/CMakeLists.txt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ add_library(shellext SHARED
103103
Win32Registry.h
104104
)
105105

106+
add_library(libeval STATIC
107+
${EXPRTK_HEADER_PATH}
108+
libEval.h
109+
libEval.cpp
110+
)
111+
106112
# Group external files as filter for Visual Studio
107113
source_group("Default Configuration Files" FILES ${CONFIGURATION_DEFAULT_FILES})
108114

@@ -125,6 +131,10 @@ add_custom_command( TARGET shellanything POST_BUILD
125131
# Force CMAKE_DEBUG_POSTFIX for executables
126132
set_target_properties(shellanything PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
127133
set_target_properties(shellext PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
134+
set_target_properties(libeval PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
135+
136+
# exprtk.hpp(15607): fatal error C1128: number of sections exceeded object file format limit : compile with /bigobj
137+
target_compile_options(libeval PRIVATE "/bigobj")
128138

129139
# Define include directories for exported code.
130140
target_include_directories(shellanything
@@ -134,6 +144,7 @@ target_include_directories(shellanything
134144
${GTEST_INCLUDE_DIR}
135145
rapidassist
136146
glog::glog
147+
libeval
137148
)
138149
target_include_directories(shellext
139150
PUBLIC
@@ -142,7 +153,13 @@ target_include_directories(shellext
142153
rapidassist
143154
glog::glog
144155
)
145-
target_link_libraries(shellanything PRIVATE ${PTHREAD_LIBRARIES} ${GTEST_LIBRARIES} rapidassist glog::glog)
156+
target_include_directories(libeval
157+
PUBLIC
158+
$<INSTALL_INTERFACE:${SHELLANYTHING_INSTALL_INCLUDE_DIR}> # for clients using the installed library.
159+
PRIVATE
160+
${PACKAGE_DOWNLOAD_DIR}/exprtk-master
161+
)
162+
target_link_libraries(shellanything PRIVATE ${PTHREAD_LIBRARIES} ${GTEST_LIBRARIES} rapidassist glog::glog libeval)
146163
target_link_libraries(shellext PRIVATE shellanything rapidassist glog::glog)
147164

148165
# Also add Tinyxml2 include and libraries.
@@ -171,3 +188,9 @@ install(TARGETS shellext
171188
LIBRARY DESTINATION ${SHELLANYTHING_INSTALL_LIB_DIR}
172189
RUNTIME DESTINATION ${SHELLANYTHING_INSTALL_BIN_DIR}
173190
)
191+
install(TARGETS libeval
192+
EXPORT shellanything-targets
193+
ARCHIVE DESTINATION ${SHELLANYTHING_INSTALL_LIB_DIR}
194+
LIBRARY DESTINATION ${SHELLANYTHING_INSTALL_LIB_DIR}
195+
RUNTIME DESTINATION ${SHELLANYTHING_INSTALL_BIN_DIR}
196+
)

src/Context.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ namespace shellanything
7878
std::string selection_filename_ext ;
7979
std::string selection_drive_letter ;
8080
std::string selection_drive_path ;
81+
std::string selection_count ;
82+
std::string selection_files_count ;
83+
std::string selection_directories_count;
8184

8285
// Get the separator string for multiple selection
8386
const std::string & selection_multi_separator = pmgr.GetProperty(Context::MULTI_SELECTION_SEPARATOR_PROPERTY_NAME);
@@ -133,6 +136,14 @@ namespace shellanything
133136
pmgr.SetProperty("selection.filename.extension" , selection_filename_ext );
134137
pmgr.SetProperty("selection.drive.letter" , selection_drive_letter );
135138
pmgr.SetProperty("selection.drive.path" , selection_drive_path );
139+
140+
selection_count = ra::strings::ToString(elements.size());
141+
selection_files_count = ra::strings::ToString(this->GetNumFiles());
142+
selection_directories_count = ra::strings::ToString(this->GetNumDirectories());
143+
144+
pmgr.SetProperty("selection.count" , selection_count );
145+
pmgr.SetProperty("selection.files.count" , selection_files_count );
146+
pmgr.SetProperty("selection.directories.count" , selection_directories_count);
136147
}
137148

138149
void Context::UnregisterProperties() const

src/Validator.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "PropertyManager.h"
2929
#include "DriveClass.h"
3030
#include "Wildcard.h"
31+
#include "libEval.h"
3132
#include "rapidassist/strings.h"
3233
#include "rapidassist/filesystem_utf8.h"
3334

@@ -83,6 +84,7 @@ namespace shellanything
8384
mFileExists = validator.mFileExists ;
8485
mClass = validator.mClass ;
8586
mPattern = validator.mPattern ;
87+
mExprtk = validator.mExprtk ;
8688
mInverse = validator.mInverse ;
8789
}
8890
return (*this);
@@ -158,6 +160,16 @@ namespace shellanything
158160
mPattern = iPattern;
159161
}
160162

163+
const std::string & Validator::GetExprtk() const
164+
{
165+
return mExprtk;
166+
}
167+
168+
void Validator::SetExprtk(const std::string & iExprtk)
169+
{
170+
mExprtk = iExprtk;
171+
}
172+
161173
const std::string & Validator::GetInserve() const
162174
{
163175
return mInverse;
@@ -291,6 +303,16 @@ namespace shellanything
291303
return false;
292304
}
293305

306+
//validate exprtx
307+
const std::string exprtk = pmgr.Expand(mExprtk);
308+
if (!exprtk.empty())
309+
{
310+
bool inversed = IsInversed("exprtk");
311+
bool valid = ValidateExprtk(iContext, exprtk, inversed);
312+
if (!valid)
313+
return false;
314+
}
315+
294316
return true;
295317
}
296318

@@ -570,4 +592,19 @@ namespace shellanything
570592
return true;
571593
}
572594

595+
bool Validator::ValidateExprtk(const Context & context, const std::string & exprtk, bool inversed) const
596+
{
597+
if (exprtk.empty())
598+
return true;
599+
600+
PropertyManager & pmgr = PropertyManager::GetInstance();
601+
602+
bool result = false;
603+
bool evaluated = evaluate(exprtk.c_str(), &result);
604+
if (!evaluated)
605+
return false;
606+
607+
return result;
608+
}
609+
573610
} //namespace shellanything

src/libEval.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**********************************************************************************
2+
* MIT License
3+
*
4+
* Copyright (c) 2018 Antoine Beauchamp
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*********************************************************************************/
24+
25+
#include "libEval.h"
26+
27+
#define _SCL_SECURE_NO_WARNINGS
28+
#include "exprtk.hpp"
29+
30+
namespace shellanything
31+
{
32+
33+
bool evaluate(const char * expression_string, double * result)
34+
{
35+
typedef exprtk::expression<double> expression_t;
36+
typedef exprtk::parser<double> parser_t;
37+
38+
//symbol_table_t symbol_table;
39+
//symbol_table.add_variable("x",x);
40+
//symbol_table.add_variable("y",y);
41+
//symbol_table.add_variable("z",z);
42+
43+
expression_t expression;
44+
45+
parser_t parser;
46+
47+
if (!parser.compile(expression_string,expression))
48+
return false;
49+
50+
if (result)
51+
*result = expression.value();
52+
53+
return true;
54+
}
55+
56+
bool evaluate(const char * expression_string, bool * result)
57+
{
58+
double tmp = 0.0;
59+
bool success = evaluate(expression_string, &tmp);
60+
if (!success)
61+
return false;
62+
63+
if (result)
64+
{
65+
if (tmp != 0.0)
66+
*result = true;
67+
else
68+
*result = false;
69+
}
70+
return true;
71+
}
72+
73+
} //namespace shellanything

src/libEval.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**********************************************************************************
2+
* MIT License
3+
*
4+
* Copyright (c) 2018 Antoine Beauchamp
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*********************************************************************************/
24+
25+
#ifndef SA_LIBEVAL_H
26+
#define SA_LIBEVAL_H
27+
28+
namespace shellanything
29+
{
30+
/// <summary>
31+
/// Evaluates a text expression and calculates the result.
32+
/// </summary>
33+
/// <param name="expression_string">The text expression to evaluate.</param>
34+
/// <param name="output">The output double value of the result expression.</param>
35+
/// <returns>Returns true if the evaluation is successfull. Returns false otherwise.</returns>
36+
bool evaluate(const char * expression_string, double * result);
37+
38+
/// <summary>
39+
/// Evaluates a boolean text expression as a true or false value.
40+
/// </summary>
41+
/// <param name="expression_string">The text expression to evaluate.</param>
42+
/// <param name="output">The output bool value of the result expression.</param>
43+
/// <returns>Returns true if the evaluation is successfull. Returns false otherwise.</returns>
44+
bool evaluate(const char * expression_string, bool * result);
45+
46+
} //namespace shellanything
47+
48+
#endif //SA_LIBEVAL_H

0 commit comments

Comments
 (0)