├── images ├── messabox-unicode1.png ├── messagebox-ansi1.png ├── doxygen-fun-daxpy1.png ├── gui-program-basic1.png ├── doxygen-alias-MathFunc.png ├── doxygen-class-XYChart1.png ├── doxygen-class-XYChart2.png ├── doxygen-class-XYChart3.png ├── doxygen-class-XYChart4.png ├── output-messageboxUTF8.png ├── DebugView-systinternals1.png ├── cmake-project-vs-spdlog.png ├── cmake_console_subsystem1.png ├── cmake_window_subsystem1.png ├── doxygen-alias-MathFuncGen.png ├── doxygen-function-solver1.png ├── gtest-framework-console.png ├── gtest-framework-qtcreator.png ├── windows-console-ansi-mode.png ├── doxygen-enum-MathErrorCodeA.png ├── doxygen-enum-MathErrorCodeB.png ├── gui-program-console-subsystem.png ├── windows-console-unicode-utf8.png ├── DebugView-window-messages-events.png ├── doxygen-fun-GenericNewtonSolver1.png ├── doxygen-fun-GenericNewtonSolver2.png └── solution-explorer-visual-spdlog.png ├── dotnet-cpp-ffi1 ├── hpc.hpp ├── gsl_test.fsx ├── Makefile ├── gsl.cs ├── time1.c ├── wrapper.fsx ├── libc.fsx └── hpc.cpp ├── .gitignore ├── src ├── testing.cpp ├── cppStrings.cpp ├── glibc-version.c ├── dlls │ ├── mymodule_script.py │ └── example-windows1 │ │ ├── client1.cpp │ │ └── testlib.hpp ├── minimal-program1.cpp ├── assert.cpp ├── numberParse.cpp ├── cpp17 │ ├── cpp17-invoke.cpp │ ├── cpp17-any.cpp │ ├── cpp17-filesys1.cpp │ ├── cpp17-structured-bindings.cpp │ ├── fold-expressions1.cpp │ └── optional1.cpp ├── stack-allocation-test.cpp ├── design-patterns │ ├── boolean-bitmask.C │ ├── crtp1.cpp │ ├── property-type-erasure1.cpp │ ├── virtual-constructor1.cpp │ ├── virtual-constructor2.cpp │ ├── singleton1.cpp │ ├── polymorphic-io1.cpp │ ├── type-erasure1.cpp │ ├── visitor2.cpp │ ├── strategy-pattern1.cpp │ ├── interface-class.cpp │ └── property-type-erasure2.cpp ├── minimal-program2.cpp ├── cppClasses1.cpp ├── windows │ ├── console-utf8.cpp │ ├── showProcesses.cpp │ ├── currentProcess.cpp │ ├── GetLogicalDrivers.cpp │ ├── winapi1-utf8.cpp │ ├── winapi-enconding1.cpp │ ├── winlNet-basic.cpp │ ├── client-socket-shell1.cpp │ ├── gui-without-winmain.cpp │ ├── dynamic-loading1.cpp │ └── dynamic-loading2.cpp ├── sfinae_is_printable.cpp ├── basic-io.cpp ├── arraysFun.cpp ├── math │ ├── rand_int_fun.cpp │ └── RandInt.cpp ├── handle-signal.cpp ├── operator-overload2.cpp ├── boost │ ├── boost-shared-memory-logger.cpp │ ├── boost-memory-mapped-file.cpp │ ├── boost-operators.cpp │ └── boost-pointer-container.cpp ├── operator-overloading3.cpp ├── test_terminate.cpp ├── constexpr-function.cpp ├── cppVector2D.cpp ├── insertionExtractionOverload.cpp ├── template-hof1.cpp ├── polymorphism1.C ├── sample-programs │ └── posix-daemon.cpp ├── dataTypeSizes.cpp ├── numerics │ └── decompose_binary32flt.cpp ├── numeric-limits.cpp ├── regex1.cpp ├── cppStlVector.cpp ├── operator-overload1.cpp └── gsl-vector-wrapper.cpp ├── Makefile ├── .gitmodules ├── haskell-ffi1 ├── gsl.hs ├── libcScript.hs └── README.org └── cppEmacs.el /images/messabox-unicode1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/messabox-unicode1.png -------------------------------------------------------------------------------- /images/messagebox-ansi1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/messagebox-ansi1.png -------------------------------------------------------------------------------- /images/doxygen-fun-daxpy1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-fun-daxpy1.png -------------------------------------------------------------------------------- /images/gui-program-basic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/gui-program-basic1.png -------------------------------------------------------------------------------- /images/doxygen-alias-MathFunc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-alias-MathFunc.png -------------------------------------------------------------------------------- /images/doxygen-class-XYChart1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-class-XYChart1.png -------------------------------------------------------------------------------- /images/doxygen-class-XYChart2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-class-XYChart2.png -------------------------------------------------------------------------------- /images/doxygen-class-XYChart3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-class-XYChart3.png -------------------------------------------------------------------------------- /images/doxygen-class-XYChart4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-class-XYChart4.png -------------------------------------------------------------------------------- /images/output-messageboxUTF8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/output-messageboxUTF8.png -------------------------------------------------------------------------------- /images/DebugView-systinternals1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/DebugView-systinternals1.png -------------------------------------------------------------------------------- /images/cmake-project-vs-spdlog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/cmake-project-vs-spdlog.png -------------------------------------------------------------------------------- /images/cmake_console_subsystem1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/cmake_console_subsystem1.png -------------------------------------------------------------------------------- /images/cmake_window_subsystem1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/cmake_window_subsystem1.png -------------------------------------------------------------------------------- /images/doxygen-alias-MathFuncGen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-alias-MathFuncGen.png -------------------------------------------------------------------------------- /images/doxygen-function-solver1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-function-solver1.png -------------------------------------------------------------------------------- /images/gtest-framework-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/gtest-framework-console.png -------------------------------------------------------------------------------- /images/gtest-framework-qtcreator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/gtest-framework-qtcreator.png -------------------------------------------------------------------------------- /images/windows-console-ansi-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/windows-console-ansi-mode.png -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/hpc.hpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | extern "C" { double vector2DNorm(double x, double y); } 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/doxygen-enum-MathErrorCodeA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-enum-MathErrorCodeA.png -------------------------------------------------------------------------------- /images/doxygen-enum-MathErrorCodeB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-enum-MathErrorCodeB.png -------------------------------------------------------------------------------- /images/gui-program-console-subsystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/gui-program-console-subsystem.png -------------------------------------------------------------------------------- /images/windows-console-unicode-utf8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/windows-console-unicode-utf8.png -------------------------------------------------------------------------------- /images/DebugView-window-messages-events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/DebugView-window-messages-events.png -------------------------------------------------------------------------------- /images/doxygen-fun-GenericNewtonSolver1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-fun-GenericNewtonSolver1.png -------------------------------------------------------------------------------- /images/doxygen-fun-GenericNewtonSolver2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/doxygen-fun-GenericNewtonSolver2.png -------------------------------------------------------------------------------- /images/solution-explorer-visual-spdlog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nelsonjchen/C-Cpp-Notes/master/images/solution-explorer-visual-spdlog.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.out 3 | *.bin 4 | bin/* 5 | *.hi 6 | *.o 7 | *.exe 8 | *.so 9 | *.bin 10 | *.o 11 | *.dll 12 | *.jar 13 | theme/* 14 | theme 15 | dist/* 16 | .gdb_history 17 | -------------------------------------------------------------------------------- /src/testing.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int sum(int min, int max){ 5 | return min + max; 6 | } 7 | 8 | int main() 9 | { 10 | assert(sum(0, 2) == 3); 11 | assert(sum(-2, 2) == 0); 12 | assert(sum(3, 7) == 25); 13 | 14 | return 0; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/cppStrings.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | string s; 9 | 10 | s = "hello world c++ string" ; 11 | cout << "s = " << s << endl; 12 | 13 | s += " Append this to string" ; 14 | cout << "s = " << s << endl; 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/gsl_test.fsx: -------------------------------------------------------------------------------- 1 | #r "gsl.dll" 2 | 3 | 4 | 5 | printfn "Gsl.Basic.hypot(80.0, 60.0) = %f " <| Gsl.Basic.hypot(80.0, 60.0) 6 | 7 | let result = Gsl.Poly.polyEval [1.0; 2.0; 3.0 ; 4.0 ] 2.0 8 | in printfn " Gsl.Poly.polyEval [1.0; 2.0; 3.0 ; 4.0 ] 2.0 = %f" <| result 9 | 10 | let cpl = Gsl.gsl_complex_rect2(40.0, 40.0) 11 | in printfn "Gsl.gsl_complex_rect(30., 20.) = %A" (Gsl.gslCplToTuple cpl) 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/glibc-version.c: -------------------------------------------------------------------------------- 1 | /* 2 | Description: Show glibc Version. 3 | OS: Linux only 4 | 5 | Compile with: 6 | 7 | $ gcc glibc-version.c -o glibc-version.bin && ./glibc-version.bin 8 | glibc version: 2.24 9 | 10 | */ 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char *argv[]) { 16 | printf("glibc version: %s\n", gnu_get_libc_version()); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/dlls/mymodule_script.py: -------------------------------------------------------------------------------- 1 | import mymodule as a 2 | 3 | print("\n======>>>> Call function: aexposedFunction <<=== ") 4 | a.exposedFunction() 5 | 6 | print("\n======>>>> Call function: testArguments <<=== ") 7 | 8 | s1 = a.testArguments(False, 100, 10.9361, 0.344, "from Python to C++") 9 | print(" [PYTHON] Received string s1 = ", s1) 10 | 11 | s2 = a.testArguments(True, 90, -0.56e6, 9.344e5, "") 12 | print(" [PYTHON] Received string: s2 = ", s2) 13 | 14 | print("\n===== <<<< END OF PYTHON TEST SCRIPT >>>>> =====") 15 | -------------------------------------------------------------------------------- /src/minimal-program1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | std::cout << "Hello world user" << "\n"; 6 | std::cout << "Enter your name: "; 7 | std::string name; 8 | std::getline(std::cin, name); 9 | std::cout << "Be welcome to C++ land: " << name << "\n"; 10 | 11 | // Wait user type a single character 12 | std::cout << "\n" << "Type RETURN to exit"; 13 | // Read a character from standard input (console) 14 | std::cin.get(); 15 | 16 | // Status code 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Create directory dist containing the orphan branch gh-pages 2 | # The html pages are stored in the gh-pages branch 3 | tree: 4 | git worktree add dist gh-pages 5 | ln -s dist/theme . 6 | 7 | # Compile html pages 8 | build: 9 | scala -save build.scala -make all 10 | 11 | # Upload html pages to github to branch gh-pages 12 | upload: 13 | cd dist && git add * && git commit -a -m "Update site" && git push 14 | 15 | # Copy src/ source code to dist directory. 16 | code: 17 | cp -r -v src dist/ 18 | 19 | # Update html pages images 20 | image: 21 | cp -r -v images dist/ 22 | 23 | clean: 24 | scala -save build.scala -clean 25 | 26 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/Makefile: -------------------------------------------------------------------------------- 1 | lib: hpc.so 2 | 3 | # Build shared library 4 | hpc.so: hpc.cpp 5 | g++ hpc.cpp -Wall -shared -fpic -o hpc.so 6 | # g++ hpc.cpp -o hpc.o -c -g -ggdb -fPIC -rdynamic -shared -lstatic 7 | 8 | # Build fsharp application 9 | app.exe : wrapper.fsx 10 | fsharpc wrapper.fsx --out:app.exe --target:exe 11 | 12 | run: hpc.so app.exe 13 | env LD_LIBRARY_PATH=. mono app.exe 14 | 15 | gsl: gsl.dll 16 | 17 | libGslAdapter.so: gslAdapter.c 18 | gcc gslAdapter.c -o libGslAdapter.so -Wall -shared -fpic -lgsl -lgslcblas -lm 19 | 20 | gsl.dll: gsl.fsx libGslAdapter.so 21 | fsharpc gsl.fsx --out:gsl.dll --target:library 22 | 23 | clean: 24 | rm -rf *.exe *.so *.bin *.dll 25 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/gsl.cs: -------------------------------------------------------------------------------- 1 | class GSL 2 | { 3 | [DllImport("libgsl.so")] 4 | static extern double gsl_sf_bessel_J0(double x); 5 | 6 | [DllImport("libgsl.so")] 7 | static extern double gsl_complex_abs( complex z); 8 | 9 | [DllImport("libgsl.so")] 10 | static extern complex gsl_complex_sin (complex z); 11 | 12 | 13 | public struct complex 14 | { 15 | [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)] 16 | public double[] dat; 17 | 18 | complex(double re, double im) 19 | { 20 | this.dat=new double[] {re,im}; 21 | } 22 | } 23 | 24 | 25 | public static void test() 26 | { 27 | Console.WriteLine(gsl_sf_bessel_J0(0.0)); 28 | 29 | complex c1; 30 | c1.dat=new double[] {3,4}; 31 | Console.WriteLine(gsl_complex_abs(c1)); 32 | 33 | complex c2; 34 | c2=gsl_complex_sin(c1); 35 | 36 | 37 | 38 | Console.WriteLine(c1.dat[0]); 39 | //Console.WriteLine(c2.dat[0]); 40 | 41 | 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/assert.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Description: Assertion demonstration in C++. 3 | // Author: Caio Rodrigues 4 | // File: assert.cpp 5 | // Compile: g++ assert.cpp -o assert.bin 6 | // 7 | 8 | #include // Assertion 9 | #include // Standard library 10 | 11 | int main (int argc, char * argv[]) { 12 | 13 | // Check argc and exit if not enough arguments are provided to avoid segmentation fault. 14 | // 15 | if (argc != 2){ 16 | std::cout << "Usage: ./" << argv[0] << "[n]" << std::endl; 17 | std::cout << "where [n] is a number > 0. If n * n != 25 the assertion fails." << std::endl; 18 | 19 | exit(0); // exit(1) - Return status code 1 - Indicating failure. 20 | } 21 | 22 | int i = atoi(argv[1]); 23 | int j = i * i ; 24 | 25 | assert (j == 25); 26 | 27 | std::cout << "continuing" << std::endl; 28 | 29 | exit(0); // exit(0) - Return status code 0 - Indicating success. 30 | } 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "example-pybind11-vcpkg"] 2 | path = example-pybind11-vcpkg 3 | url = https://github.com/caiorss/example-pybind11-vcpkg 4 | [submodule "winapi-snippets-cmake"] 5 | path = winapi-snippets-cmake 6 | url = https://github.com/caiorss/winapi-snippets-cmake 7 | [submodule "cross-platform-shared-library"] 8 | path = cross-platform-shared-library 9 | url = https://gist.github.com/caiorss/2bba4c50866d9467aaa8c7792b337f71 10 | [submodule "Doxygen-Examples"] 11 | path = Doxygen-Examples 12 | url = https://gist.github.com/caiorss/b04df92734c93e300658285d0b76ed07 13 | [submodule "sample-cpp-plugin"] 14 | path = sample-cpp-plugin 15 | url = https://github.com/caiorss/sample-cpp-plugin 16 | [submodule "Rlang-RcppExamples"] 17 | path = Rlang-RcppExamples 18 | url = https://github.com/caiorss/Rlang-RcppExamples 19 | [submodule "example-project-pybind11"] 20 | path = example-project-pybind11 21 | url = https://github.com/caiorss/example-project-pybind11 22 | -------------------------------------------------------------------------------- /haskell-ffi1/gsl.hs: -------------------------------------------------------------------------------- 1 | -- | Load this file with: 2 | -- 3 | -- $ stack exec -- ghci -lgsl 4 | -- 5 | 6 | :set -XForeignFunctionInterface 7 | :set -XOverloadedStrings 8 | 9 | import Foreign.C.Types 10 | import Foreign.C.String (CString, newCString, castCharToCChar, castCCharToChar) 11 | import Foreign.Storable 12 | import Foreign.Ptr 13 | import Foreign.Marshal.Alloc 14 | import qualified Foreign.Marshal.Array as A 15 | import System.IO.Unsafe (unsafePerformIO) 16 | 17 | -- double gsl_poly_eval(const double c[], const int len, const double x); 18 | foreign import ccall "gsl_poly_eval" gsl_polyEval :: Ptr Double -> Int -> Double -> IO Double 19 | 20 | :{ 21 | {- | Evaluate polynomial 22 | c[0] + c[1] x + c[2] x^2 + ... + c[len-1] x^(len-1) 23 | -} 24 | polyEval :: [Double] -> Double -> Double 25 | polyEval poly x = unsafePerformIO $ do 26 | arr <- A.newArray poly 27 | gsl_polyEval arr (length poly) x 28 | :} 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/numberParse.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Description: atoi, atof, strtol demonstration. 3 | // Note: Convert string to integer, double and long integer. 4 | // Tags: atoi, atof, strtol 5 | // 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | int main (){ 13 | 14 | cout << "\nAtoi - parse int 32 bits" << endl; 15 | 16 | cout << "atoi(\"2342\") = " << atoi("2342") << endl; 17 | cout << "atoi(\"-2323\") = " << atoi("-2323") << endl; 18 | cout << "atoi(\"failed\") = " << atoi("failed") << endl; 19 | cout << "atoi(\"12xy346\") = " << atoi("12xy346") << endl; 20 | 21 | cout << "\nAtof - parse float/double" << endl; 22 | 23 | cout << "atof(\"100.23\") = " << atof("100.23") << endl; 24 | cout << "atof(\"-20.015e3\") = " << atof("-20.015e3") << endl; 25 | cout << "atof(\"100.134354blablah\") = " << atof("100.134354blablah") << endl; 26 | cout << "atof(\"failed0.3123garbage\") = " << atof("failed0.3123garbage") << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/cpp17/cpp17-invoke.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // std::invoke is provide by header functional 6 | #include 7 | 8 | struct Dummy{ 9 | double evalme(double x) { 10 | std::cerr << __FILE__ << ":" << __LINE__ << " I was evaluated ; 2x = " << 2 *x << '\n'; 11 | return 2 * x; 12 | } 13 | double operator()(double x){ 14 | std::cerr << __FILE__ << ":" << __LINE__ << " Call function-operator << 4 * x = " << 4 * x << '\n'; 15 | return 4 * x; 16 | } 17 | }; 18 | 19 | double computeDouble(double x){ 20 | std::cerr << __FILE__ << ":" << __LINE__ << " Computed double of 2x = " << 2 * x << '\n'; 21 | return 2 * x; 22 | } 23 | 24 | int main(){ 25 | std::invoke(computeDouble, 3.0); 26 | Dummy dummy; 27 | std::invoke(dummy, 3.0); 28 | std::invoke(Dummy(), 2.0); 29 | // Call method: .evalme indirectly 30 | std::invoke(&Dummy::evalme, dummy, 3.0); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /src/stack-allocation-test.cpp: -------------------------------------------------------------------------------- 1 | // File: stack-allocation-test 2 | // Brief: Test limits of stack or heap allocation. 3 | // Author: Caio Rodrigues 4 | //------------------------------------------------------ 5 | #include 6 | #include 7 | 8 | #ifndef ARRAY_SIZE 9 | #define ARRAY_SIZE 8000 10 | #endif 11 | 12 | int main(){ 13 | size_t sizeKB = static_cast(ARRAY_SIZE) * sizeof(double) / 1024; 14 | std::cout << " [LOG] Number of elements = " << ARRAY_SIZE << "\n"; 15 | std::cout << " [LOG] Array size in Kbytes = " << sizeKB << "\n"; 16 | #if !defined HEAP || HEAP == 0 17 | // ===> Stack allocation 18 | std::cout << " [LOG] Stack allocation." << "\n"; 19 | double array [ARRAY_SIZE]; 20 | #else 21 | // ===> Heap allocation 22 | std::cout << " [LOG] Heap (dynamic memory) allocation." << "\n"; 23 | // Note: It throws std::bad_alloc exception. 24 | double* array = new double [ARRAY_SIZE]; 25 | delete [] array; 26 | #endif 27 | std::cout << " [LOG] Program ended gracefully OK." << "\n"; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/design-patterns/boolean-bitmask.C: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | #include 3 | #include 4 | #include // Operator: (<<) 5 | #include 6 | 7 | enum class Permissions: unsigned { 8 | executable = 0x01, // decimal = 1 or (1 << 0) 9 | writeable = 0x02, // decimal = 2 or (1 << 1) 10 | readable = 0x04 // decimal = 4 or (1 << 2) 11 | }; 12 | 13 | Permissions operator | (Permissions lhs, Permissions rhs){ 14 | return static_cast(static_cast(lhs) | static_cast(rhs)); 15 | } 16 | bool operator & (Permissions lhs, Permissions rhs){ 17 | return static_cast(lhs) & static_cast(rhs); 18 | } 19 | // Make permissions enum printable. 20 | std::ostream& operator<<(std::ostream& os, const Permissions& p){ 21 | os << std::boolalpha; // Make bool printable as 'true' or 'false' instead of 0 or 1 22 | os << "readable = " << (p & Permissions::readable) << "; " 23 | << "writeable = " << (p & Permissions::writeable) << "; " 24 | << "executable = " << (p & Permissions::executable); 25 | return os; 26 | } 27 | -------------------------------------------------------------------------------- /src/minimal-program2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv, char **environ){ 5 | if(argc < 2){ 6 | std::cerr << "Error: invalid command line argument. Expected -args or -env " 7 | << "\n"; 8 | // Exit immediately (return 1) 9 | return EXIT_FAILURE; 10 | } 11 | 12 | if(std::string(argv[1]) == "-args"){ 13 | std::cout << "Number of command line arguments = " << argc << "\n"; 14 | std::cout << "argv[0] = " << argv[0] << "\n"; 15 | std::cout << "\n"; 16 | std::cout << "Showing command line arguments:" << "\n"; 17 | std::cout << "+-----------------------------+" << "\n"; 18 | for(int i = 0; i < argc; i++) 19 | std::cout << "argv[" << i << "] = " << argv[i] << "\n"; 20 | return EXIT_FAILURE; 21 | } 22 | 23 | if(std::string(argv[1]) == "-env"){ 24 | std::cout << "Show environment variables" << "\n"; 25 | char** env = environ; 26 | while(*(env++) != nullptr) 27 | std::cout << " => env = " << *env << "\n"; 28 | return EXIT_FAILURE; 29 | } 30 | std::cerr << "Error: invalid argument <" << argv[1] << "> " <<"\n"; 31 | // return 0 32 | return EXIT_SUCCESS; 33 | }; 34 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/time1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void showTm(struct tm info){ 5 | printf("tm.tm_year = %d\n", info.tm_year + 1900); 6 | printf("tm.tm_gmtoff = %d\n", info.tm_gmtoff); 7 | printf("tm.tzone = %s\n", info.tm_zone); 8 | printf("Current local time and date: %s", asctime(&info)); 9 | } 10 | 11 | int main () 12 | { 13 | time_t rawtime; 14 | time_t rawtime2; 15 | struct tm *info; 16 | struct tm *info2; 17 | char buffer[80]; 18 | 19 | time( &rawtime ); 20 | 21 | printf("rawtime = %d\n", rawtime); 22 | 23 | info = localtime( &rawtime ); 24 | showTm(*info); 25 | 26 | rawtime2 = 0; 27 | info2 = localtime(&rawtime2); 28 | showTm(*info2); 29 | 30 | printf("--------------------\n\n"); 31 | rawtime2 = time(NULL); 32 | printf("rawtime2 = %d\n", rawtime2); 33 | info2 = localtime(&rawtime2); 34 | showTm(*info2); 35 | 36 | 37 | printf("--------------------\n\n"); 38 | rawtime2 = 1496843850; 39 | printf("rawtime2 = %d\n", rawtime2); 40 | info2 = localtime(&rawtime2); 41 | showTm(*info2); 42 | 43 | printf("x = %d", sizeof(struct tm)); 44 | 45 | return(0); 46 | } 47 | -------------------------------------------------------------------------------- /src/cppClasses1.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | 5 | class Date 6 | { 7 | public: 8 | int year, month, day; 9 | 10 | // ---- Public Class Members ----- // 11 | 12 | void showDate(); 13 | void showDate2(); 14 | int getYear(); 15 | int getDay(); 16 | int getMonth(); 17 | }; 18 | 19 | 20 | void Date::showDate(){ 21 | cout << "Date = " << this->year << "-" << this->month << "-" << this->day << endl; 22 | } 23 | 24 | void Date::showDate2(){ 25 | cout << "Date = " << year << "-" << month << "-" << day << endl; 26 | } 27 | 28 | int Date::getYear(){ 29 | return year; 30 | } 31 | 32 | int Date::getMonth(){ 33 | return month; 34 | } 35 | 36 | int Date::getDay(){ 37 | return day; 38 | } 39 | 40 | Date makeDate (int y, int m, int d){ 41 | Date date; 42 | date.year = y ; 43 | date.month = m ; 44 | date.day = d ; 45 | return date; 46 | } 47 | 48 | void printDate(Date d){ 49 | cout << "Date is " << d.year << "-" << d.month << "-" << d.day << endl; 50 | } 51 | 52 | 53 | int main(){ 54 | Date d; 55 | d.day = 10; 56 | d.month = 4; 57 | d.year = 1998; 58 | 59 | cout << "Date (YMD) is = " << d.year << "-" << d.month << "-" << d.day << endl; 60 | d.showDate(); 61 | d.showDate2(); 62 | printDate(d); 63 | 64 | cout << "Year of date d is = " << d.getYear() << endl; 65 | cout << "Month of date d is = " << d.getMonth() << endl; 66 | 67 | printDate(makeDate(1996, 8, 20)); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/design-patterns/crtp1.cpp: -------------------------------------------------------------------------------- 1 | // File: crtp1.cpp 2 | // Brief: Demonstration of curious recurring template 3 | // Author: Caio Rodrigues 4 | //-------------------------------------------------------// 5 | #include 6 | 7 | template 8 | class IntervalSummation{ 9 | public: 10 | // Get reference to implementation 11 | Implementation& self(){ 12 | return *static_cast(this); 13 | } 14 | // Overload method 15 | const Implementation& self() const { 16 | return *static_cast(this); 17 | } 18 | double summation(int lower, int upper) const { 19 | double sum = 0; 20 | for(int i = lower; i <= upper; i++) 21 | sum += self().stepFn(i); 22 | return sum; 23 | } 24 | }; 25 | 26 | class SumOfSquares: public IntervalSummation{ 27 | public: 28 | double stepFn(double x) const { return x * x; } 29 | }; 30 | 31 | class SumOfCubes: public IntervalSummation{ 32 | public: 33 | double stepFn(double x) const { return x * x * x; } 34 | }; 35 | 36 | template 37 | void clientCode(const IntervalSummation& obj){ 38 | std::cout << "Summation at [0, 15] = " << obj.summation(0, 15) << std::endl; 39 | } 40 | 41 | int main(){ 42 | SumOfSquares sq; 43 | SumOfCubes sc; 44 | std::cout << "Sum of squares in [0, 10] = " << sq.summation(0, 10) << std::endl; 45 | std::cout << "Sum of cubes in [0, 10] = " << sc.summation(0, 10) << std::endl; 46 | clientCode(sq); 47 | clientCode(sc); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /src/design-patterns/property-type-erasure1.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Property class without type erasure. 3 | //----------------------------------------------- 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /** Class that encapsulate get/set properties 11 | * @tparam - Type default constructible, copiable and equality-comparable 12 | */ 13 | template 14 | class TProperty 15 | { 16 | std::string m_name; 17 | T m_value; 18 | std::type_info const& m_tinfo; 19 | public: 20 | TProperty(std::string name, T const& init = T{}) 21 | : m_name(std::move(name)) 22 | , m_value(init) 23 | , m_tinfo(typeid(T)) 24 | { } 25 | 26 | std::string Name() const 27 | { 28 | return m_name; 29 | } 30 | 31 | const std::type_info& Type() 32 | { 33 | return m_tinfo; 34 | } 35 | TProperty Get() const 36 | { 37 | return m_value; 38 | } 39 | TProperty& Set(T const& value) 40 | { 41 | std::cerr << " [TRACE] Property [" << m_name << "] set to value = " 42 | << value << std::endl; 43 | m_value = value; 44 | } 45 | 46 | friend std::ostream& operator<<(std::ostream& os, TProperty const& rhs) 47 | { 48 | return os << " Property{ Name = " << std::quoted(rhs.m_name) 49 | << " ; Value = " << rhs.m_value << " }"; 50 | } 51 | }; 52 | 53 | int main() 54 | { 55 | TProperty p1("count", 100); 56 | TProperty p2("range", 5.6); 57 | TProperty p3("name", "Box"); 58 | 59 | std::cout << "p1 = " << p1 << "\n"; 60 | std::cout << "p2 = " << p2 << "\n"; 61 | std::cout << "p3 = " << p3 << "\n"; 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /src/windows/console-utf8.cpp: -------------------------------------------------------------------------------- 1 | // File: console-utf8.cpp 2 | // Brief: Sets Windows Console to UTF8 3 | // Author: Caio Rodrigues 4 | //------------------------------------------------------------- 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // Uses RAII for setting console to UTF8 11 | // and restoring its previous settings. 12 | class ConsoleUTF8{ 13 | public: 14 | // Constructor saves context 15 | ConsoleUTF8(){ 16 | m_config = ::GetConsoleOutputCP(); 17 | ::SetConsoleOutputCP(CP_UTF8); 18 | std::perror(" [TRACE] Console set to UTF8"); 19 | } 20 | // Destructor restores context 21 | ~ConsoleUTF8(){ 22 | std::perror(" [TRACE] Console restored."); 23 | ::SetConsoleOutputCP(m_config); 24 | } 25 | private: 26 | unsigned int m_config; 27 | }; 28 | 29 | // RAII for asking user to hit RETURN to exit 30 | // to block program from exiting immediately when 31 | // the executable is clicked. 32 | struct ExitPrompt{ 33 | ~ExitPrompt(){ 34 | std::puts(" >>> Enter RETURN to exit"); 35 | std::cin.get(); 36 | } 37 | }; 38 | 39 | int main(){ 40 | #ifdef UTF8 41 | auto utf8Console = ConsoleUTF8(); 42 | #endif 43 | //auto codePage = ::SetConsoleOutputCP(CP_UTF8); 44 | 45 | auto exitPrompt = ExitPrompt(); 46 | std::puts("Testing Console output with UTF8"); 47 | std::puts("--------------------------------"); 48 | 49 | std::puts("Text with UTF8 - SÃO JOÃO - "); 50 | std::puts("Japanese Kanji - 漢字 ; Japanese Hiragrama - 平仮名 "); 51 | std::puts("Cyrllic Script - Sputnik = Спутник-1"); 52 | std::puts("Greek/Latin Script = Α α, Β β, Γ γ, Δ δ, Ε ε, Ζ ζ, Η η, Θ θ"); 53 | 54 | //::SetConsoleOutputCP(codePage); 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/sfinae_is_printable.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Checks whether type is printable with insertion operator (<<) 3 | // Tags: template metaprogramming sfinae 4 | //-------------------------------------------------------------------------- 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // std::ostream& operator<<(std::ostream& os, const RHS& rhs); 12 | 13 | /** @brief Checks whether type is printable, or supports the insertion operator (<<). 14 | * @details 15 | * This metafunction tests whether type supports the operator (<<) or 16 | * std::ostream& operator<<(std::ostream& os, const RHS& rhs) 17 | * 18 | * @tparam - Any type, int, char, class, std::string, std::vector ... 19 | */ 20 | template 21 | struct IsPrintable{ 22 | 23 | template())> 24 | static auto check(void*) -> char; 25 | 26 | template 27 | static auto check(...) -> long; 28 | 29 | static constexpr bool value = 30 | std::is_same(nullptr)), char>::value; 31 | }; 32 | 33 | struct SomeClass{ 34 | }; 35 | 36 | struct Point{ 37 | int x; 38 | int y; 39 | friend auto operator<<(std::ostream& os, Point const& p) -> std::ostream& { 40 | return os << "Point{ " << p.x << " " << p.y << "} \n"; 41 | } 42 | }; 43 | 44 | int main(){ 45 | std::cout << std::boolalpha; 46 | std::cout << " IsPrintable = " << IsPrintable::value << "\n"; 47 | std::cout << "IsPrintable = " << IsPrintable::value << "\n"; 48 | std::cout << " IsPrintable = " << IsPrintable::value << "\n"; 49 | std::cout << " IsPrintable = " << IsPrintable::value << "\n"; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/cpp17/cpp17-any.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | struct Point{ 9 | double x; 10 | double y; 11 | Point(double x, double y): x(x), y(y) {} 12 | 13 | // Copy constructor 14 | Point(const Point& p){ 15 | std::cerr << " -->> Copy constructor" << '\n'; 16 | x = p.x; 17 | y = p.y; 18 | } 19 | }; 20 | 21 | std::ostream& operator<<(std::ostream& os, const Point& p){ 22 | os << "Point(" << p.x << ", " << p.y << ") "; 23 | return os; 24 | } 25 | 26 | template 27 | auto printInfo(std::any x) -> void{ 28 | std::cout << " x.type = " << x.type().name() 29 | << " ; value(x) = " 30 | << std::any_cast(x) 31 | << '\n'; 32 | } 33 | 34 | int main(){ 35 | // Print boolean as 'true', 'false', instead of 0 or 1 36 | std::cout << std::boolalpha; 37 | std::any x = 1; 38 | printInfo(x); 39 | x = 10.233; 40 | printInfo(x); 41 | x = 'k'; 42 | printInfo(x); 43 | x = "hello world"; 44 | printInfo(x); 45 | x = std::string("hello world"); 46 | printInfo(x); 47 | x = Point(100.0, 20.0); 48 | printInfo(x); 49 | std::cout << "Has value: x.has_value() = " << x.has_value() << '\n'; 50 | x.reset(); 51 | std::cout << "Has value: x.has_value() = " << x.has_value() << '\n'; 52 | std::cout << "Try casting " << std::endl; 53 | x = "testing type casting"; 54 | try{ 55 | std::any_cast(x); 56 | } catch (const std::bad_any_cast& ex) { 57 | std::cerr << " >>> Exception: what = " << ex.what() << '\n'; 58 | } 59 | std::cerr << " >>> End the program gracefully" << '\n'; 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /src/basic-io.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(){ 7 | // Everything is initialized as zero 8 | double price, sum, min, max; 9 | std::vector dataset; 10 | sum = 0.0; 11 | min = 1e10; 12 | max = -1e10; 13 | 14 | // Print float point numbers with 2 decimal places and fixed notation 15 | std::cout << std::setprecision(2) << std::fixed; 16 | std::cout << "Enter the prices and type CTRL+D you are done." << "\n"; 17 | 18 | // Execute this code block while there is any error on the stream. 19 | // It means, the user did not type any bad input or 20 | // CTRL + D (Send EOF End of File - signal) 21 | int n = 0; 22 | while(std::cin.good()){ 23 | // (i++) Post increment i, increment variable i after it is print. 24 | std::cout << " => price[" << n++ << "] = "; 25 | // Read the price from stdin (standard input or console). 26 | std::cin >> price; 27 | if(!std::cin.good()){ 28 | std::cerr << " [LOG] " << "User typed invalid input. Exit loop." << "\n"; 29 | // Force exiting the loop 30 | break; 31 | } 32 | sum += price; 33 | // Save 34 | dataset.push_back(price); 35 | if(price > max) 36 | max = price; 37 | if(price < min) 38 | min = price; 39 | } 40 | // Clear stream error flag 41 | std::cin.clear(); 42 | 43 | std::cout << "Sum = " << sum << "\n"; 44 | std::cout << "Mean = " << (sum / n) << "\n"; 45 | std::cout << "Min = " << min << "\n"; 46 | std::cout << "Max = " << max << "\n"; 47 | 48 | std::cout << "Dataset = [ "; 49 | for(size_t i = 0; i < dataset.size(); i++) 50 | std::cout << " " << dataset[i] ; 51 | std::cout << "] \n"; 52 | 53 | #ifdef _WIN32 54 | std::cout << "\n" << "Type RETURN to quit." << "\n"; 55 | std::cin.clear(); 56 | std::cin.ignore(10, '\n'); 57 | // Wait for single character 58 | std::cin.get(); 59 | #endif 60 | 61 | return EXIT_SUCCESS; 62 | }; 63 | -------------------------------------------------------------------------------- /src/windows/showProcesses.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------- 2 | // Brief: Show all processes in current machine. 3 | // Author: Caio Rodrigues. 4 | //--------------------------------------------- 5 | 6 | // C++ Headers 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // Windows Headers 13 | #include 14 | #include 15 | 16 | auto showProcessInfo(std::ostream& os) -> int; 17 | 18 | int main(){ 19 | // Log file 20 | auto plog = std::ofstream("process-log.txt"); 21 | // Print all processes to stdout. 22 | showProcessInfo(std::cout); 23 | // Write all processes to file 24 | showProcessInfo(plog); 25 | // Flush buffer - force data to be written to file. 26 | plog.flush(); 27 | 28 | std::cout << "\n ==> Type return to exit." << std::endl; 29 | std::cin.get(); 30 | return 0; 31 | } 32 | 33 | //=======================/// 34 | 35 | // Show all processes in current machine 36 | auto showProcessInfo(std::ostream& os) -> int { 37 | // Get snapshot with process listing. 38 | HANDLE hProcessSnapShot = 39 | CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 40 | // Instnatiate process' entry structure. 41 | PROCESSENTRY32 ProcessEntry = { 0 }; 42 | ProcessEntry.dwSize = sizeof( ProcessEntry ); 43 | BOOL Return = FALSE; 44 | Return = Process32First( hProcessSnapShot, &ProcessEntry ); 45 | // Returns -1 if process failed 46 | if(!Return ) { return -1;} 47 | do { // print process' data 48 | os << "EXE File = " << ProcessEntry.szExeFile << "\n" 49 | << "PID = " << ProcessEntry.th32ProcessID << "\n" 50 | << "References = " << ProcessEntry.cntUsage << "\n" 51 | << "Thread Count = " << ProcessEntry.cntThreads << "\n" 52 | << "-----------------------------------------------\n"; 53 | } 54 | while( Process32Next( hProcessSnapShot, &ProcessEntry )); 55 | // Close handle releasing resource. 56 | CloseHandle( hProcessSnapShot ); 57 | return 1; 58 | } 59 | -------------------------------------------------------------------------------- /src/arraysFun.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include // Basic IO functions 3 | #include // C-math functions such as sqrt, pow ... 4 | #include // Assertions 5 | 6 | using namespace std; 7 | 8 | // Function prototypes 9 | //---------------------------------// 10 | 11 | double scalarProduct (double [], double [], int); 12 | double vectorSum (double [], int); 13 | double vectorNorm (double [], int); 14 | void printVectorVert (double xs[], int size); 15 | 16 | // Main function 17 | //------------------------------- 18 | 19 | int main() 20 | { 21 | int size = 4 ; 22 | double v1[] = {1.0, 2.0, 3.0, 4.0} ; 23 | double v2[] = {3.0, 4.0, 5.0, 6.0} ; 24 | 25 | cout << "\n\nVector v1 = " << endl ; 26 | printVectorVert(v1, size); 27 | 28 | cout << "\n\nVector v2 = " << endl ; 29 | printVectorVert(v2, size); 30 | 31 | cout << "\n\nScalar product is = " << scalarProduct(v1, v2, size) << endl; 32 | 33 | cout << "Vector v1 sum is = " << vectorSum(v1, size) << endl; 34 | 35 | cout << "Vector v2 Norm is = " << vectorNorm(v1, size) << endl; 36 | 37 | assert(scalarProduct(v1, v2, size) == 50.0); 38 | 39 | return 0 ; // Return 0 as status code. 40 | } 41 | 42 | // Functions Implementations 43 | // -------------------------------- // 44 | 45 | double scalarProduct(double xs[], double ys[], int size){ 46 | double sum = 0.0; 47 | 48 | for (int i = 0; i <= size -1; i++){ 49 | sum = sum + xs[i] * ys[i]; 50 | } 51 | return sum; 52 | } 53 | 54 | double vectorSum(double xs[], int size){ 55 | double sum = 0.0 ; 56 | 57 | for (int i = 0; i <= size - 1; i++){ 58 | sum = sum + xs[i]; 59 | } 60 | return sum; 61 | } 62 | 63 | 64 | double vectorNorm(double xs[], int size){ 65 | double sum = 0.0 ; 66 | 67 | for (int i = 0; i <= size - 1; i++){ 68 | sum = sum + xs[i] * xs[i]; 69 | } 70 | return sqrt(sum); 71 | } 72 | 73 | 74 | void printVectorVert(double xs[], int size){ 75 | for (int i = 0; i <= size -1; i++){ 76 | cout << "v[" << i << "] = " << xs[i] << endl ; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/windows/currentProcess.cpp: -------------------------------------------------------------------------------- 1 | // Brief: Get information about current process 2 | // Author: Caio Rodrigues 3 | //------------------------------------------------------ 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // Return true if program was launched by clicking on it, 11 | // return false if this program was launched from command line. 12 | auto isInOwnConsole() -> bool { 13 | DWORD procIDs[2]; 14 | DWORD maxCount = 2; 15 | DWORD result = GetConsoleProcessList((LPDWORD)procIDs, maxCount); 16 | return result != 1; 17 | } 18 | 19 | auto ExecutablePath = [](int pid){ 20 | HANDLE hProc = OpenProcess( PROCESS_QUERY_INFORMATION 21 | | PROCESS_VM_READ, FALSE, pid ); 22 | // Get process file path 23 | std::string process_path(MAX_PATH, 0); 24 | DWORD size = MAX_PATH; 25 | QueryFullProcessImageNameA(hProc, 0, &process_path[0], &size); 26 | process_path.resize(size); 27 | CloseHandle(hProc); 28 | return process_path; 29 | }; 30 | 31 | auto CurrentDirectory = []{ 32 | DWORD size = ::GetCurrentDirectory(0, nullptr); 33 | assert(size != 0); 34 | std::string path(size + 1, 0x00); 35 | size = ::GetCurrentDirectory(path.size(), &path[0]); 36 | path.resize(size); 37 | return path; 38 | }; 39 | 40 | int main(){ 41 | // Get current process ID 42 | DWORD pid = GetCurrentProcessId(); 43 | // Return module handle of current process 44 | HMODULE hProc = GetModuleHandleA(nullptr); 45 | // Get process module 46 | 47 | std::cout << "=========== Current Process Info ========" << std::endl; 48 | std::cout << "PID = " << pid << std::endl; 49 | std::cout << "hProc = 0x" << hProc << std::endl; 50 | std::cout << "Executable path = " << ExecutablePath(pid) << std::endl; 51 | std::cout << "Current path = " << CurrentDirectory() << std::endl; 52 | 53 | // Copy itself to Desktop 54 | CopyFile(ExecutablePath(pid).c_str(), "C:\\Users\\archbox\\Desktop\\appinfo.exe", false) ; 55 | 56 | // Stop program from exiting if it was launched by clicking on it. 57 | if(!isInOwnConsole()){ 58 | std::cout << "\n ==> Type RETURN to exit." << std::endl; 59 | std::cin.get(); 60 | } 61 | return EXIT_SUCCESS; 62 | } 63 | -------------------------------------------------------------------------------- /haskell-ffi1/libcScript.hs: -------------------------------------------------------------------------------- 1 | :set -XForeignFunctionInterface 2 | :set -XOverloadedStrings 3 | 4 | import Foreign.C.Types 5 | import Foreign.C.String (CString, newCString, castCharToCChar, castCCharToChar) 6 | import Foreign.Storable 7 | import Foreign.Ptr 8 | import Foreign.Marshal.Alloc 9 | import qualified Foreign.Marshal.Array as A 10 | 11 | ---- ============ Pure Functions ==================== ----- 12 | 13 | -- double cbrt(double x); 14 | foreign import ccall "cbrt" cbrt :: Double -> Double 15 | 16 | -- double hypot(double x, double y); 17 | foreign import ccall "hypot" hypot :: Double -> Double -> Double 18 | 19 | 20 | ---- ============ Functions with Side Effects ======== ---- 21 | 22 | -- int puts(const char *s); 23 | foreign import ccall "puts" cputs :: CString -> IO () 24 | puts s = newCString s >>= cputs 25 | 26 | -- pid_t getpid(void); 27 | foreign import ccall "getpid" getpid :: IO Int 28 | 29 | -- Execute Shell command and return after the command has been completed. 30 | -- 31 | -- int system(const char *command); 32 | foreign import ccall "system" csystem :: CString -> IO Int 33 | system cmd = newCString cmd >>= csystem 34 | 35 | -- int gethostname(char *name, size_t len); 36 | -- 37 | foreign import ccall "gethostname" c_gethostname :: (Ptr CChar) -> Int -> IO Int 38 | 39 | :{ 40 | gethostname :: IO String 41 | gethostname = do 42 | -- Allocate 255 bytes (C- char Characters) 43 | ptrChar <- A.mallocArray 255 44 | c_gethostname ptrChar 255 45 | -- Get all array CChar array elements until the null character \0 46 | name <- A.peekArray0 (castCharToCChar '\0') ptrChar 47 | -- Convert [CChar] to [Char] or String 48 | return $ map castCCharToChar name 49 | :} 50 | 51 | :{ 52 | testLibc :: IO () 53 | testLibc = do 54 | hname <- gethostname 55 | putStrLn "\n\n\nLibC FFI Tests\n---------------------" 56 | puts "Hello world São Paulo city" 57 | putStrLn $ "Hostname = " ++ hname 58 | system "uname -a" 59 | system "wrong" 60 | putStrLn $ "cbrt 27.0 = " ++ show (cbrt 27.0) 61 | putStrLn $ "hypot 80.0 60.0 = " ++ show (hypot 80.0 60.0) 62 | 63 | :} 64 | 65 | testLibc 66 | -------------------------------------------------------------------------------- /src/design-patterns/virtual-constructor1.cpp: -------------------------------------------------------------------------------- 1 | // File: virtual-consructor1.cpp 2 | // Brief: Demonstration of a simple implementation of virtual copy constructor. 3 | // Author: Caio Rodrigues 4 | // ------------------------------------------------------------------ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class IBase{ 11 | public: 12 | // Destructor always virtual to avoid memory leak, 13 | virtual ~IBase() = default; 14 | // "virtual copy constructor" 15 | virtual auto clone() const -> IBase* = 0; 16 | // "virtual default constructor" 17 | virtual auto create() const -> IBase* = 0; 18 | virtual auto getID() const -> std::string = 0; 19 | virtual auto setID(std::string id) -> void = 0; 20 | virtual auto show() const -> void = 0; 21 | }; 22 | 23 | class DerivedA: public IBase{ 24 | private: 25 | std::string _id; 26 | public: 27 | DerivedA() 28 | : _id("unnamed-A"){ } 29 | 30 | DerivedA(std::string id) 31 | : _id{std::move(id)}{ } 32 | 33 | auto clone() const -> IBase* { 34 | // Invoke copy constructor 35 | return new DerivedA(*this); 36 | } 37 | auto create() const -> IBase* { 38 | // Invoke default constructor 39 | return new DerivedA(); 40 | } 41 | auto getID() const -> std::string { 42 | return _id; 43 | } 44 | auto setID(std::string id) -> void { 45 | _id = id; 46 | } 47 | auto show() const -> void { 48 | std::cout << " => Class DerivedA - id = " << _id << "\n"; 49 | } 50 | }; 51 | 52 | 53 | class DerivedB: public IBase{ 54 | private: 55 | std::string _id; 56 | public: 57 | DerivedB() 58 | : _id("unnamed-B"){ } 59 | 60 | DerivedB(std::string id) 61 | : _id{std::move(id)}{ } 62 | 63 | auto clone() const -> IBase* { 64 | // Invoke copy constructor 65 | return new DerivedB(*this); 66 | } 67 | auto create() const -> IBase* { 68 | // Invoke default constructor 69 | return new DerivedB(); 70 | } 71 | auto getID() const -> std::string { 72 | return _id; 73 | } 74 | auto setID(std::string id) -> void { 75 | _id = std::move(id); 76 | } 77 | auto show() const -> void { 78 | std::cout << " => Class DerivedB - id = " << _id << "\n"; 79 | } 80 | }; 81 | 82 | int main(){ 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /src/math/rand_int_fun.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // FUNCTION OVERLOAD 1 7 | //----------------------- 8 | // Note: The return type of this function must not be set to std::function 9 | // or that will have a performance penalty as this container uses type erasure and heap allocation. 10 | // This function returns lambda or an anonymous callable object, in other words, an object that overloads 11 | // the operator()(), generated by the compiler. 12 | template 13 | auto make_uniform_random_distribution(TInt a, TInt b, long seed) 14 | { 15 | // std::default_random_engine engine(seed); 16 | std::mt19937 engine(seed); 17 | std::uniform_int_distribution dist(a, b); 18 | // std::cout << " [INFO] seed = " << seed << std::endl; 19 | return [=]() mutable -> TInt { return dist(engine); }; 20 | } 21 | 22 | // FUNCTION OVERLOADING 2 23 | //---------------------------- 24 | template 25 | auto make_uniform_random_distribution(TInt a, TInt b) 26 | { 27 | std::random_device rd; 28 | return make_uniform_random_distribution(a, b, rd()) ; 29 | } 30 | 31 | int main() 32 | { 33 | #if 1 34 | std::cout << "\n ===== Random numbers with a random seed ====" 35 | << std::endl; 36 | { 37 | auto rnd = make_uniform_random_distribution(1, 10); 38 | for(int i = 0; i < 15; i++){ 39 | auto field = std::string(" x[") + std::to_string(i) + "] = "; 40 | std::cout << std::setw(10) 41 | << field 42 | << std::setw(5) << rnd() << std::endl; 43 | } 44 | } 45 | #endif 46 | 47 | std::cout << "\n ===== Random numbers with a non-random seed ====" 48 | << std::endl; 49 | { 50 | // Initialize Random generator object with known and fixed 51 | // seed to reproduce computation results. 52 | unsigned int seed = 1195785783; 53 | auto rnd = make_uniform_random_distribution(1, 10, seed); 54 | 55 | /* Expected sequence: 6, 10, 2, 4, 1, 9, 10, 3, 6, ... */ 56 | for(int i = 0; i < 15; i++) 57 | { 58 | auto field = std::string(" x[") + std::to_string(i) + "] = "; 59 | std::cout << std::setw(10) 60 | << field 61 | << std::setw(5) << rnd() << std::endl; 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /cppEmacs.el: -------------------------------------------------------------------------------- 1 | ;; C++/ Emacs helper functions and commands. 2 | ;; 3 | ;; Load this file with 'M-x load-file cppEmacs.el' 4 | ;; 5 | ;;----------------------------------------------- 6 | 7 | 8 | (defun cpp/compile-run-buffer () 9 | "Compile and run current c++ buffer (single-file C++ code). 10 | Example: By running M-x cpp/compile-buffer-run at current buffer (file code1.cpp) 11 | will run $ g++ code1.cpp -o code1.bin && ./code1.bin" 12 | (interactive) 13 | (let* ((file-name (file-name-nondirectory (buffer-file-name))) 14 | ;; Change file name extension to .bin 15 | (output (concat (file-name-base file-name) ".bin"))) 16 | (save-buffer) 17 | (compile (format "g++ %s -o %s && ./%s" 18 | file-name 19 | output 20 | output 21 | )))) 22 | 23 | 24 | (defun cpp/compile-run-dired () 25 | "Compile single c++ file at point in dired mode. 26 | Usage: Position the cursor at the file to be compiled and 27 | run M-x cpp/compile-dired 28 | " 29 | (interactive) 30 | (let* ((file-name (file-name-nondirectory (dired-file-name-at-point))) 31 | ;; Change file name extension to .bin 32 | (output (concat (file-name-base file-name) ".bin"))) 33 | (save-buffer) 34 | (compile (format "g++ %s -o %s && ./%s" 35 | file-name 36 | output 37 | output 38 | )))) 39 | 40 | 41 | (defun cpp/template-main () 42 | "Insert C++ body template at the top of file." 43 | (interactive) 44 | (save-excursion ;; Save cursor position 45 | (goto-char (point-min)) ;; Got to top of buffer 46 | (insert ;; Insert template 47 | "#include 48 | using namespace std; 49 | 50 | int main(){ 51 | 52 | return 0; 53 | 54 | } 55 | " ))) 56 | 57 | (defun cpp/open-include () 58 | "Open /usr/include directory (Linux only)." 59 | (interactive) 60 | (dired "/usr/include")) 61 | 62 | (defun cpp/open-include-cpp () 63 | "Open /usr/include/c++ (Linux only)" 64 | (interactive) 65 | (dired "/usr/include/c++")) 66 | 67 | (defun cpp/share-libraries () 68 | "Show shared libraries in the system. (Linux only)" 69 | (interactive) 70 | (shell-command "strings -n5 /etc/ld.so.cache" 71 | "*shared-libs*" 72 | )) 73 | -------------------------------------------------------------------------------- /src/handle-signal.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Test signal handling in C++. 3 | //------------------------------------------------- 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // Unix specific (not valid for MS-Windows) 13 | #include // Import getpid() 14 | 15 | 16 | class Dummy{ 17 | public: 18 | Dummy(){ 19 | std::cerr << " [TRACE] Program initialized OK " << "\n"; 20 | } 21 | ~Dummy(){ 22 | std::cerr << " [TRACE] All objects destroyed. Program End OK. " << "\n"; 23 | } 24 | }; 25 | 26 | Dummy dummyGlobal; 27 | 28 | void signal_handler(int signal) 29 | { 30 | // static auto logger = []{ 31 | // auto log = std::ofstream("signals.log"); 32 | // log << " [INFO] Initialized Logger OK." << std::endl; 33 | // return log; 34 | // }(); 35 | 36 | auto& logger = std::cerr; 37 | 38 | const static std::map signalDatabse = { 39 | {SIGINT, "SIGINT"} 40 | ,{SIGABRT, "SIGABRT"} 41 | ,{SIGSEGV, "SIGSEV"} 42 | ,{SIGFPE, "SIGFPE"} 43 | ,{SIGTSTP, "SIGTSTP"} 44 | ,{SIGTERM, "SIGTERM"} 45 | ,{SIGQUIT, "SIGQUIT"} 46 | }; 47 | 48 | // std::cin.ignore(1000); 49 | std::cin.clear(); 50 | 51 | std::string sigName; 52 | 53 | auto it = signalDatabse.find(signal); 54 | if(it != signalDatabse.end()) 55 | sigName = it->second; 56 | else 57 | sigName = "UNKNOWN"; 58 | 59 | logger << "\n [INFO] " << __FUNCTION__ << "() " 60 | << " Received singal = {" << sigName << "} => code = " << signal << std::endl; 61 | } 62 | 63 | int main() 64 | { 65 | pid_t pid = ::getpid(); 66 | std::cout << " Process ID = " << pid << "\n"; 67 | std::cout << " Attach to it with $ gdb --tui --pid=" << pid << "\n"; 68 | 69 | std::signal(SIGINT, &signal_handler); 70 | std::signal(SIGFPE, &signal_handler); 71 | std::signal(SIGTERM, signal_handler); 72 | std::signal(SIGTSTP, signal_handler); 73 | std::signal(SIGQUIT, signal_handler); 74 | 75 | int n = 0; 76 | char ch = 0; 77 | 78 | std::string line; 79 | 80 | while(std::cin.good()){ 81 | std::cout << " Variable n = " << n++ << "\n"; 82 | std::cout << " => Input = "; 83 | std::getline(std::cin, line); 84 | 85 | // Simulate float-point exception 86 | if(line == "sigfpe"){ 87 | std::cout << " 10.0 / 0.0 = " << 10.0 / 0.0 << "\n"; 88 | } 89 | } 90 | 91 | return EXIT_SUCCESS; 92 | } 93 | -------------------------------------------------------------------------------- /src/design-patterns/virtual-constructor2.cpp: -------------------------------------------------------------------------------- 1 | // File: virtual-consructor2.cpp 2 | // Brief: Enhanced virtual constructor idiom with CRTP design pattern. 3 | // Author: Caio Rodrigues 4 | // ------------------------------------------------------------------ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class IBase{ 11 | public: 12 | // Destructor always virtual to avoid memory leak, 13 | virtual ~IBase() = default; 14 | // "virtual copy constructor" 15 | virtual auto clone() const -> std::unique_ptr = 0; 16 | // "virtual default constructor" 17 | virtual auto create() const -> std::unique_ptr = 0; 18 | virtual auto getID() const -> std::string = 0; 19 | virtual auto setID(std::string id) -> void = 0; 20 | virtual auto show() const -> void = 0; 21 | }; 22 | 23 | /** Remember: Template always in header files. */ 24 | template 25 | class Copyable: public Base{ 26 | private: 27 | inline auto self() const -> const Derived& { 28 | return *static_cast(this); 29 | } 30 | public: 31 | virtual ~Copyable() = default; 32 | auto clone() const -> std::unique_ptr { 33 | // Invoke copy constructor 34 | return std::make_unique(this->self()); 35 | } 36 | auto create() const -> std::unique_ptr { 37 | // Invoke default constructor 38 | return std::make_unique(); 39 | } 40 | }; 41 | 42 | class DerivedA: public Copyable{ 43 | private: 44 | std::string _id; 45 | public: 46 | DerivedA() 47 | : _id("unnamed-A"){ } 48 | 49 | DerivedA(std::string id) 50 | : _id{std::move(id)}{ } 51 | 52 | auto getID() const -> std::string { 53 | return _id; 54 | } 55 | auto setID(std::string id) -> void { 56 | _id = id; 57 | } 58 | auto show() const -> void { 59 | std::cout << " => Class DerivedA - id = " << _id << "\n"; 60 | } 61 | }; 62 | 63 | class DerivedB: public Copyable{ 64 | private: 65 | std::string _id; 66 | public: 67 | DerivedB() 68 | : _id("unnamed-B"){ } 69 | 70 | DerivedB(std::string id) 71 | : _id{std::move(id)}{ } 72 | 73 | auto getID() const -> std::string { 74 | return _id; 75 | } 76 | auto setID(std::string id) -> void { 77 | _id = std::move(id); 78 | } 79 | auto show() const -> void { 80 | std::cout << " => Class DerivedB - id = " << _id << "\n"; 81 | } 82 | }; 83 | 84 | int main(){ 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/windows/GetLogicalDrivers.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------- 2 | // File: GetLogicalDrivers.cpp 3 | // Description: Enumerate all logical drivers in the computer. 4 | // Author: Caio Rodrigues 5 | //-------------------------------------------------------------- 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using DriverEnumerator = std::function void>; 16 | auto EnumerateLogicalDriver(DriverEnumerator Consumer) -> void; 17 | 18 | template class Container = std::vector> 19 | auto LogicalDriverList() 20 | -> Container>; 21 | 22 | int main(){ 23 | std::puts("Logical Drivers or Disks found in the current installation"); 24 | std::puts("------------------------------------------------"); 25 | 26 | EnumerateLogicalDriver( 27 | [](const std::string& name){ 28 | std::cout << "Driver = " << name << std::endl; 29 | }); 30 | 31 | auto driverList1 = LogicalDriverList(); 32 | std::cout << " *=> Driver list in STL container std::deque = "; 33 | for(const auto& d: driverList1){ std::cout << d << ", "; } 34 | std::cout << std::endl;; 35 | 36 | auto driverList2 = LogicalDriverList(); 37 | std::cout << " *=> Driver list in STL container std::vector = "; 38 | for(const auto& d: driverList2){ std::cout << d << ", "; } 39 | std::cout << std::endl;; 40 | 41 | return 0; 42 | } 43 | 44 | //---------------------------------------------------// 45 | 46 | using DriverEnumerator = std::function void>; 47 | 48 | auto EnumerateLogicalDriver(DriverEnumerator Consumer) -> void 49 | { 50 | size_t size = ::GetLogicalDriveStringsA(0, nullptr); 51 | std::string buffer(size, 0x00); 52 | ::GetLogicalDriveStringsA(buffer.size(), &buffer[0]); 53 | std::stringstream ss{buffer}; 54 | while(std::getline(ss, buffer, '\0') && !buffer.empty()) 55 | Consumer(buffer); 56 | } 57 | 58 | // Remember: Template always in header files 59 | // The user can choose the type of container used to return 60 | // the computer drivers. 61 | template class Container = std::vector> 62 | auto LogicalDriverList() 63 | -> Container> 64 | { 65 | Container> list{}; 66 | EnumerateLogicalDriver( 67 | [&](const std::string& name){ 68 | list.push_back(name); 69 | }); 70 | return list; 71 | } 72 | -------------------------------------------------------------------------------- /src/operator-overload2.cpp: -------------------------------------------------------------------------------- 1 | // File: operator-overload2.cpp 2 | // Brief: Arithmetic operator overloading as non-member functions. 3 | // Author: Caio Rodrigues 4 | //-------------------------------------------- 5 | 6 | #include 7 | #include 8 | 9 | //---- file Vector2D.h - Declaration: --------------// 10 | 11 | /** A struct is just a class with everything public by default. */ 12 | struct Vector2D{ 13 | double x, y; 14 | Vector2D(); 15 | Vector2D(double x, double y); 16 | }; 17 | 18 | std::ostream& operator<<(std::ostream& os, const Vector2D& vec); 19 | Vector2D operator+ (const Vector2D& lhs, const Vector2D& rhs); 20 | 21 | /** C++11 Notation */ 22 | auto operator- (Vector2D const& lhs, Vector2D const& rhs) -> Vector2D; 23 | auto operator-(const Vector2D& lhs) -> Vector2D; 24 | 25 | Vector2D operator*(double k, const Vector2D& rhs); 26 | Vector2D operator*(const Vector2D& rhs, double k); 27 | 28 | auto operator/(const Vector2D& lhs, double k) -> Vector2D; 29 | 30 | 31 | //-------- Main functions ------------------// 32 | 33 | int main(){ 34 | Vector2D v1{3, 5}; 35 | Vector2D v2{5, 6}; 36 | 37 | std::cout << " v1 = " << v1 << std::endl; 38 | std::cout << " v2 = " << v2 << std::endl; 39 | std::cout << " 3 * v2 = " << 3 * v2 << std::endl; 40 | std::cout << "3 * v2 + 4 * v1 = " << 3 * v2 + 4 * v1 << std::endl; 41 | std::cout << "v2 * 3 + v1 * 4 = " << 3 * v2 + 4 * v1 << std::endl; 42 | std::cout << "v2 / 10 + v1 / 100 = " << v1 / 10 + v2 / 100 << std::endl; 43 | return 0; 44 | } 45 | 46 | //------ File: Vector2D.cpp -- Implementations ---------------// 47 | 48 | Vector2D::Vector2D(): x(0.0), y(0.0) 49 | { 50 | } 51 | 52 | Vector2D::Vector2D(double x, double y): x(x), y(y) 53 | { 54 | } 55 | 56 | std::ostream& operator<<(std::ostream& os, const Vector2D& vec) 57 | { 58 | return os << "Vector2D{ x = " << vec.x << " ; " 59 | << " y = " << vec.y << " } "; 60 | } 61 | 62 | Vector2D operator+ (const Vector2D& lhs, const Vector2D& rhs) 63 | { 64 | return Vector2D(lhs.x + rhs.x, lhs.y + rhs.y); 65 | } 66 | 67 | auto operator- (Vector2D const& lhs, Vector2D const& rhs) -> Vector2D 68 | { 69 | return Vector2D(lhs.x - rhs.x, lhs.y - rhs.y); 70 | } 71 | 72 | auto operator-(const Vector2D& lhs) -> Vector2D 73 | { 74 | return { - lhs.x, -lhs.y }; 75 | } 76 | 77 | Vector2D operator*(double k, const Vector2D& rhs) 78 | { 79 | return {k * rhs.x, k * rhs.y}; 80 | } 81 | 82 | Vector2D operator*(const Vector2D& rhs, double k) 83 | { 84 | return {k * rhs.x, k * rhs.y}; 85 | } 86 | 87 | auto operator/(const Vector2D& lhs, double k) -> Vector2D 88 | { 89 | return {lhs.x / k, lhs.y / k}; 90 | } 91 | -------------------------------------------------------------------------------- /src/boost/boost-shared-memory-logger.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Caio Rodrigues 3 | // Brief: Sample logging system for shared memory using boost interprocess 4 | //----------------------------------------------------------------------- 5 | #include 6 | #include 7 | #include 8 | 9 | #include // strok 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace bi = boost::interprocess; 19 | 20 | int main(int argc, char** argv) 21 | { 22 | // Create shared memory wrapper object 23 | auto shm = bi::shared_memory_object{ 24 | bi::open_or_create, 25 | "logger_shm", 26 | bi::read_write 27 | }; 28 | // Set size of the shared memory segment in Kb (kbytes = 1024 bytes) 29 | shm.truncate(4096); // 4kb (kbytes) 30 | // Map the shared memory segment to current process 31 | auto region = bi::mapped_region{shm, bi::read_write}; 32 | // Pointer to shared memory 33 | void* pMem = region.get_address(); 34 | 35 | // Create mutex Object 36 | bi::named_mutex amutex(bi::open_or_create, "logger_mutex"); 37 | 38 | if(argc < 2){ 39 | std::cout << "$ " << argv[0] << " [-client|-server]" << "\n"; 40 | return EXIT_SUCCESS; 41 | } 42 | 43 | std::string cmd = argv[1]; 44 | 45 | if(cmd == "-server"){ 46 | char* pMessage = (char*) pMem; 47 | while(true) 48 | { 49 | std::cerr << " [TRACE] Waiting logging message " << std::endl; 50 | // Acquire mutex lock blocking this thread 51 | amutex.lock(); 52 | // Print logging memssage from shared memory 53 | std::cout << pMessage << std::endl; 54 | } 55 | return EXIT_SUCCESS; 56 | } 57 | 58 | if(cmd == "-client") 59 | { 60 | // Interpret shared memory as a pointer an null-terminated 61 | // array of characters 62 | char* pMessage = (char*) pMem; 63 | std::string line; 64 | while(true) 65 | { 66 | std::cout << " => Enter line: "; 67 | std::getline(std::cin, line); 68 | std::stringstream ss; 69 | auto now = std::chrono::system_clock::now(); 70 | std::time_t ttp = std::chrono::system_clock::to_time_t(now); 71 | ss << " [INFO] " << strtok(std::ctime(&ttp), "\n") << " - " << line; 72 | // Print to shared memory (pointer by pMessage) 73 | std::sprintf(pMessage, "%s", ss.str().c_str()); 74 | // Release mutex lock 75 | amutex.unlock(); 76 | } 77 | return EXIT_SUCCESS; 78 | } 79 | 80 | return EXIT_SUCCESS; 81 | } 82 | -------------------------------------------------------------------------------- /src/design-patterns/singleton1.cpp: -------------------------------------------------------------------------------- 1 | // File: singleton1.cpp 2 | // Brief: Singleton design pattern demonstration. 3 | // Author: Caio Rodrigues 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | //------ It should be in file: FileRepository.hpp -----// 10 | 11 | // Singleton is a design pattern with a single instance 12 | // It implements a file repository, there can be only one instance 13 | // of this object. 14 | // 15 | class FileRepository 16 | { 17 | private: 18 | std::deque _files; 19 | // Forbid client code instating a new instance. 20 | FileRepository(){ 21 | std::cerr << " [LOG] File Respository Initialized." << "\n"; 22 | } 23 | // Forbid client code from creating a copy or using the 24 | // copy constructor. 25 | FileRepository(const FileRepository&){} 26 | public: 27 | ~FileRepository(); 28 | 29 | // Return a reference to not allow client code 30 | // to delete object. 31 | static auto getInstance() -> FileRepository&; 32 | 33 | // Use old C++ 'member function' syntax. 34 | void addFile(std::string fname); 35 | void clearFiles(); 36 | // C++11 member function declaration looks better. 37 | auto showFiles() -> void; 38 | }; 39 | 40 | //------ It should be in file: FileRepository.cpp -----// 41 | 42 | FileRepository::~FileRepository(){ 43 | std::cerr << " [LOG] File Respository Deleted. Ok." << "\n"; 44 | } 45 | 46 | // Static method 47 | auto FileRepository::getInstance() -> FileRepository& { 48 | static auto instance = std::unique_ptr{nullptr}; 49 | // Initialized once - lazy initialization 50 | if(!instance) 51 | instance.reset(new FileRepository); 52 | return *instance.get(); 53 | } 54 | 55 | void FileRepository::addFile(std::string fname){ 56 | _files.push_back(std::move(fname)); 57 | } 58 | 59 | void FileRepository::clearFiles(){ 60 | _files.clear(); 61 | } 62 | 63 | auto FileRepository::showFiles() -> void { 64 | for(const auto& file: _files) 65 | std::cout << " File = " << file << std::endl; 66 | } 67 | 68 | 69 | //---- It should be file: main.cpp -------------// 70 | 71 | int main(){ 72 | 73 | FileRepository& repo1 = FileRepository::getInstance(); 74 | repo1.addFile("CashFlowStatement.txt"); 75 | repo1.addFile("Balance-Sheet.dat"); 76 | repo1.addFile("Sales-Report.csv"); 77 | 78 | FileRepository& repo2 = FileRepository::getInstance(); 79 | 80 | std::cout << std::boolalpha << "Same object? (&repo == &repo1 ?) = " 81 | << (&repo1 == &repo2) 82 | << "\n"; 83 | std::cout << "Repository files" << std::endl; 84 | repo2.showFiles(); 85 | 86 | std::cout << "Add more files" << std::endl; 87 | repo2.addFile("fileX1.pdf"); 88 | repo2.addFile("fileX2.pdf"); 89 | repo2.addFile("fileX3.pdf"); 90 | repo2.showFiles(); 91 | 92 | return EXIT_SUCCESS; 93 | } 94 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/wrapper.fsx: -------------------------------------------------------------------------------- 1 | open System 2 | open System.Runtime.InteropServices 3 | 4 | 5 | 6 | [] 7 | extern double vector2DNorm(double a, double b) 8 | 9 | [] 10 | extern double arrayNorm(double [], int) 11 | 12 | [] 13 | extern double vectorNorm(double [], int) 14 | 15 | 16 | [] 17 | extern IntPtr c_genArray(int) 18 | 19 | [] 20 | extern void c_genArray2(double [], int) 21 | 22 | [] 23 | extern double vectorSum(double [], int) 24 | 25 | 26 | let genArray n = 27 | let ptr = c_genArray n 28 | let arr = Array.create n 0.0 29 | Marshal.Copy(ptr, arr, 0, n) 30 | arr 31 | 32 | let genArray2 n = 33 | let arr = Array.create n 0.0 34 | let ptr = c_genArray2(arr, n) 35 | arr 36 | 37 | 38 | module Circle = 39 | 40 | // The accessiblity qualifier "private" makes the function 41 | // circleNew private to module 42 | // 43 | [] 44 | extern void* private circleNew(double radius) 45 | 46 | [] 47 | extern void private circleDelete(void*) 48 | 49 | [] 50 | extern double private circleGetArea(void*) 51 | 52 | let getArea r = 53 | let circle = circleNew(r) 54 | let area = circleGetArea(circle) 55 | circleDelete(circle) 56 | area 57 | 58 | 59 | let computeArrayNorm() = 60 | let arr = [| 1.0; 2.0; 3.0; 4.0 |] 61 | arrayNorm(arr, arr.Length) 62 | 63 | let arrayNormWrapper (xs: float []): float = 64 | arrayNorm(xs, xs.Length) 65 | 66 | 67 | let testVectorNorm() = 68 | let v = [| 1.0 ; 2.0; 3.0; 4.0 |] 69 | vectorNorm(v, v.Length) 70 | 71 | [] 72 | let main(args) = 73 | printfn "\n\n" 74 | printfn "getArea 10.0 = %f" <| Circle.getArea 10.0 75 | printfn "getArea [10.0; 20.0 ; 30; 40.0] = %A" <| List.map Circle.getArea [10.0; 20.0 ; 30.0; 40.0] 76 | printfn "vector2DNorm(30.0, 40.0) = %f" <| vector2DNorm(30.0, 40.0) 77 | printfn "computeArrayNorm() = %f" <| computeArrayNorm() 78 | printfn "arrayNormWrapper([|1.0; 2.0; 3.0; 4.0 |] = %f" <| arrayNormWrapper [|1.0; 2.0; 3.0; 4.0 |] 79 | printfn "testVectorNorm() = %f" <| testVectorNorm() 80 | 81 | printfn "genArray 5 = %A" <| genArray 5 82 | printfn "genArray2 5 = %A" <| genArray2 5 83 | printfn "sumArray([1.0; 2.0; 3.0; 4.0], 4) = %A" <| vectorSum([| 1.0; 2.0; 3.0; 4.0 |], 4) 84 | 0 85 | -------------------------------------------------------------------------------- /src/windows/winapi1-utf8.cpp: -------------------------------------------------------------------------------- 1 | // File: winapi1-utf8.cpp 2 | // Brief: Demonstration about how to use Windows API wiht Unicode UTF-8 3 | // Author: Caio Rodrigues 4 | // 5 | // Dependencies: user32.lib, advapi32.lib 6 | //======================================================================= 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // MSVC directive to link dependencies 16 | // #pragma comment(lib, "user32.lib") 17 | // #pragma comment(lib, "advapi32.lib") 18 | 19 | // UTF8 to Unicode Wide wchar_t (UTF16) functions 20 | // taken from the (CREDITS) https://gist.github.com/pezy/8571764 21 | auto utf8_encode(const std::wstring &wstr) -> std::string; 22 | auto utf8_decode(const std::string &str) -> std::wstring; 23 | 24 | auto messageBox(const std::string& title, const std::string& text) -> void; 25 | auto getUserName() -> std::string; 26 | 27 | 28 | int main(){ 29 | std::cout << "USER NAME = " << getUserName() << std::endl; 30 | 31 | std::string message = "Text with unicode UTF8 - 读写汉字1 - Если указан параметр "; 32 | std::string title = "Title in UTF8 الْحُرُوف الْعَرَبِيَّة"; 33 | messageBox(title, message); 34 | 35 | return 0; 36 | } 37 | 38 | // ======== Implementations =================// 39 | 40 | // Requires: , and 41 | auto getUserName() -> std::string 42 | { 43 | DWORD size = UNLEN + 1; 44 | std::wstring buffer(size, 0x00); 45 | //BOOL GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer); 46 | GetUserNameW(&buffer[0], &size); 47 | buffer.resize(size - 1); 48 | return utf8_encode(buffer); 49 | } 50 | 51 | auto messageBox(const std::string& title, const std::string& text) -> void 52 | { 53 | DWORD const infoboxOptions = 54 | MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND; 55 | ::MessageBoxW( 56 | 0 57 | ,utf8_decode(text).c_str() 58 | ,utf8_decode(title).c_str() 59 | ,infoboxOptions 60 | ); 61 | } 62 | 63 | // Convert a wide Unicode string to an UTF8 string 64 | // Credits: https://gist.github.com/pezy/8571764 65 | auto utf8_encode(const std::wstring &wstr) -> std::string 66 | { 67 | int size_needed = WideCharToMultiByte( 68 | CP_UTF8, 0, &wstr[0], 69 | (int)wstr.size(), NULL, 0, NULL, NULL); 70 | std::string strTo(size_needed, 0); 71 | WideCharToMultiByte( 72 | CP_UTF8, 0, &wstr[0], 73 | (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); 74 | return strTo; 75 | } 76 | 77 | // Convert an UTF8 string to a wide Unicode String 78 | // Credits: https://gist.github.com/pezy/8571764 79 | auto utf8_decode(const std::string &str) -> std::wstring 80 | { 81 | int size_needed = MultiByteToWideChar( 82 | CP_UTF8, 0, 83 | &str[0], (int)str.size(), NULL, 0); 84 | std::wstring wstrTo(size_needed, 0); 85 | MultiByteToWideChar( 86 | CP_UTF8, 0, &str[0], 87 | (int) str.size(), &wstrTo[0], size_needed); 88 | return wstrTo; 89 | } 90 | -------------------------------------------------------------------------------- /src/cpp17/cpp17-filesys1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // C++17 - Requires compiler linking flag: -lstdc++fs on CLang or GCC. 7 | #include 8 | 9 | namespace fs = std::filesystem; 10 | 11 | /** Iterate over first N entries of a file system iterator. */ 12 | template 13 | auto dotimes(size_t n, Range&& iterable, Function fun){ 14 | size_t i = 0; 15 | auto it = fs::begin(iterable); 16 | auto end = fs::end(iterable); 17 | while(i < n && it != end ){ 18 | fun(it); 19 | ++it; 20 | i++; 21 | } 22 | } 23 | 24 | int main(){ 25 | 26 | std::cout << std::boolalpha; 27 | 28 | std::cout << "\n EXPERIMENT 1 ===== Checking files in the system." << std::endl; 29 | fs::path p1 = "/etc/iscsi/initiatorname.iscsi"; 30 | std::cout << " p1 = " << p1 << std::endl; 31 | std::cout << "p1.string() = " << p1.string() << std::endl; 32 | std::cout << "p1 ? exists = " << fs::exists(p1) << std::endl; 33 | std::cout << "p1 ? is File = " << fs::is_regular_file(p1) << std::endl; 34 | std::cout << "p1 ? is Dir = " << fs::is_directory(p1) << std::endl; 35 | 36 | fs::path p2 = "/boot"; 37 | std::cout << " p2 = " << p2 << std::endl; 38 | std::cout << "p2.string() = " << p2.string() << std::endl; 39 | std::cout << "p2 ? exists = " << fs::exists(p2) << std::endl; 40 | std::cout << "p2 ? is File = " << fs::is_regular_file(p2) << std::endl; 41 | std::cout << "p2 ? is Dir = " << fs::is_directory(p2) << std::endl; 42 | 43 | fs::path p3 = "/boot/does/not/exist"; 44 | std::cout << " p3 = " << p3 << std::endl; 45 | std::cout << "p3.string() = " << p3.string() << std::endl; 46 | std::cout << "p3 ? exists = " << fs::exists(p3) << std::endl; 47 | std::cout << "p3 ? is File = " << fs::is_regular_file(p3) << std::endl; 48 | std::cout << "p3 ? is Dir = " << fs::is_directory(p3) << std::endl; 49 | 50 | 51 | std::cout << "\n EXPERIMENT 2 ===== Listing directory /etc =====" << std::endl; 52 | // Show first 10 files of directory /etc 53 | dotimes(10, fs::directory_iterator("/etc"), 54 | [](auto p){ 55 | auto path = p->path(); 56 | std::cout << std::left 57 | << std::setw(0) << path.filename().string() 58 | << " " << std::setw(35) 59 | << std::right << std::setw(40) << path 60 | << std::endl; 61 | }); 62 | 63 | std::cout << "\n EXPERIMENT 3 = Listing directory /etc (recursive) =====" << std::endl; 64 | dotimes(20, fs::recursive_directory_iterator("/etc/"), 65 | [](auto p){ 66 | std::cout << std::right 67 | << std::setw(10) << fs::is_directory(p->path()) 68 | << std::setw(10) << fs::is_regular_file(p->path()) 69 | << std::setw(10) << fs::is_symlink(p->path()) 70 | << std::setw(10) << " " 71 | << std::setw(5) << std::left << p->path() 72 | << std::endl; 73 | }); 74 | 75 | return EXIT_SUCCESS; 76 | } 77 | -------------------------------------------------------------------------------- /src/math/RandInt.cpp: -------------------------------------------------------------------------------- 1 | /* File: RandInt.cpp 2 | * Author: Caio Rodrigues 3 | * Description: Class for simplification and easy use of C++11 uniform distribution 4 | ********************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | template 12 | class RandInt { 13 | private: 14 | std::random_device m_nextSeed; 15 | unsigned int m_seed; 16 | std::default_random_engine m_engine; 17 | std::uniform_int_distribution m_dist; 18 | public: 19 | using TSeed = long; 20 | 21 | // Intialize with a known seed 22 | RandInt(TInt min, TInt max, unsigned int seed) 23 | : m_seed(seed), m_engine(seed), m_dist(min, max) 24 | { 25 | } 26 | 27 | // Initialize with a random seed 28 | RandInt(TInt min, TInt max) 29 | : m_nextSeed{}, 30 | m_seed(m_nextSeed()), 31 | m_engine(m_seed), 32 | m_dist(min, max) 33 | { 34 | } 35 | TInt Min() const { return m_dist.min(); } 36 | TInt Max() const { return m_dist.max(); } 37 | TSeed Seed() const { return m_seed; } 38 | void Seed(TSeed seed) 39 | { 40 | m_seed = seed; 41 | m_engine.seed(seed); 42 | } 43 | // Set seed to a new random (non-deterministic) value and return it 44 | TSeed NextSeed() 45 | { 46 | m_seed = m_nextSeed(); 47 | m_engine.seed(m_seed); 48 | return m_seed; 49 | } 50 | // Get NExt random 51 | TInt operator()() 52 | { 53 | return m_dist(m_engine); 54 | } 55 | }; 56 | 57 | 58 | int main() 59 | { 60 | std::cout << "\n ===== Random numbers with a random seed ====" 61 | << std::endl; 62 | { 63 | RandInt rnd(1, 10); 64 | std::cout << " => rnd.Seed() = " << rnd.Seed() << std::endl; 65 | std::cout << " => rnd.Min() = " << rnd.Min() << std::endl; 66 | std::cout << " => rnd.Max() = " << rnd.Max() << std::endl; 67 | 68 | for(int i = 0; i < 15; i++){ 69 | auto field = std::string(" x[") + std::to_string(i) + "] = "; 70 | std::cout << std::setw(10) 71 | << field 72 | << std::setw(5) << rnd() << std::endl; 73 | } 74 | } 75 | 76 | std::cout << "\n ===== Random numbers with a non-random seed ====" 77 | << std::endl; 78 | { 79 | // Initialize Random generator object with known and fixed 80 | // seed to reproduce computation results. 81 | long seed = 1195785783; 82 | RandInt rnd(1, 10, seed); 83 | std::cout << " => rnd.Seed() = " << rnd.Seed() << std::endl; 84 | std::cout << " => rnd.Min() = " << rnd.Min() << std::endl; 85 | std::cout << " => rnd.Max() = " << rnd.Max() << std::endl; 86 | 87 | /* Expected sequence: 7, 10, 9, 2, 2, 1, 3, 1, 6, 5, 1, 2, 3, 2 ... */ 88 | for(int i = 0; i < 15; i++){ 89 | auto field = std::string(" x[") + std::to_string(i) + "] = "; 90 | std::cout << std::setw(10) 91 | << field 92 | << std::setw(5) << rnd() << std::endl; 93 | } 94 | } 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /src/operator-overloading3.cpp: -------------------------------------------------------------------------------- 1 | // File: operator-overload3.cpp 2 | // Brief: Arithmetic operator overloading as friend functions. 3 | // Author: Caio Rodrigues 4 | //-------------------------------------------- 5 | 6 | #include 7 | #include 8 | 9 | //---- file Vector2D.h - Declaration: --------------// 10 | 11 | class Vector2D{ 12 | private: 13 | double m_x, m_y; 14 | public: 15 | Vector2D(); 16 | Vector2D(double x, double y); 17 | double X() const; 18 | double Y() const; 19 | friend std::ostream& operator<<(std::ostream& os, const Vector2D& vec); 20 | friend Vector2D operator+ (const Vector2D& lhs, const Vector2D& rhs); 21 | 22 | /** C++11 Notation */ 23 | friend auto operator- (Vector2D const& lhs, Vector2D const& rhs) -> Vector2D; 24 | friend auto operator-(const Vector2D& lhs) -> Vector2D; 25 | 26 | friend Vector2D operator*(double k, const Vector2D& rhs); 27 | friend Vector2D operator*(const Vector2D& rhs, double k); 28 | friend auto operator/(const Vector2D& lhs, double k) -> Vector2D; 29 | }; 30 | 31 | 32 | //-------- Main functions ------------------// 33 | 34 | int main(){ 35 | Vector2D v1{3, 5}; 36 | Vector2D v2{5, 6}; 37 | 38 | std::cout << " v1 = " << v1 << std::endl; 39 | std::cout << " v2 = " << v2 << std::endl; 40 | std::cout << " 3 * v2 = " << 3 * v2 << std::endl; 41 | std::cout << "3 * v2 + 4 * v1 = " << 3 * v2 + 4 * v1 << std::endl; 42 | std::cout << "v2 * 3 + v1 * 4 = " << 3 * v2 + 4 * v1 << std::endl; 43 | std::cout << "v2 / 10 + v1 / 100 = " << v1 / 10 + v2 / 100 << std::endl; 44 | return 0; 45 | } 46 | 47 | //------ File: Vector2D.cpp -- Implementations ---------------// 48 | 49 | Vector2D::Vector2D(): m_x(0.0), m_y(0.0) 50 | { 51 | } 52 | 53 | Vector2D::Vector2D(double x, double y): m_x(x), m_y(y) 54 | { 55 | } 56 | 57 | double Vector2D::X() const { 58 | return this->m_x; 59 | } 60 | 61 | double Vector2D::Y() const { 62 | return this->m_y; 63 | } 64 | 65 | std::ostream& operator<<(std::ostream& os, const Vector2D& vec) 66 | { 67 | return os << "Vector2D{ x = " << vec.m_x << " ; " 68 | << " y = " << vec.m_y << " } "; 69 | } 70 | 71 | Vector2D operator+ (const Vector2D& lhs, const Vector2D& rhs) 72 | { 73 | return Vector2D(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); 74 | } 75 | 76 | auto operator- (Vector2D const& lhs, Vector2D const& rhs) -> Vector2D 77 | { 78 | return Vector2D(lhs.m_x - rhs.m_x, lhs.m_y - rhs.m_y); 79 | } 80 | 81 | auto operator-(const Vector2D& lhs) -> Vector2D 82 | { 83 | return { - lhs.m_x, -lhs.m_y }; 84 | } 85 | 86 | Vector2D operator*(double k, const Vector2D& rhs) 87 | { 88 | return {k * rhs.m_x, k * rhs.m_y}; 89 | } 90 | 91 | Vector2D operator*(const Vector2D& rhs, double k) 92 | { 93 | return {k * rhs.m_x, k * rhs.m_y}; 94 | } 95 | 96 | auto operator/(const Vector2D& lhs, double k) -> Vector2D 97 | { 98 | return {lhs.m_x / k, lhs.m_y / k}; 99 | } 100 | -------------------------------------------------------------------------------- /src/test_terminate.cpp: -------------------------------------------------------------------------------- 1 | /* File: test_terminate.cpp 2 | * Author: Caio Rodrigues 3 | * Brief: Override std::termiante_handler for understanding what happens during abnormal program termination. 4 | *----------------------------------------------------------------------------------------------*/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class DummyClass{ 12 | public: 13 | DummyClass() 14 | { 15 | std::puts(" [INFO] Object ctor => Constructor called."); 16 | } 17 | ~DummyClass() 18 | { 19 | std::puts(" [INFO] Object dtor => Destructor called."); 20 | } 21 | }; 22 | 23 | 24 | int main(int argc, char** argv) 25 | { 26 | DummyClass cls; 27 | 28 | const char* option = std::getenv("TERMINATE"); 29 | if(option != nullptr && std::string(option) == "true") 30 | { 31 | 32 | std::puts(" [TRACE] Override std::terminate handler."); 33 | // Overrides the function called by std::terminate (std::abort by default). 34 | // 35 | // It accepts function pointer or a non-capturing lambda. 36 | // Override std::termiante setting std::terminate_handler callback 37 | std::set_terminate([](){ 38 | std::cerr << " [FATAL] std::terminate() called; SIGABRT signal abort sent." 39 | << std::endl; 40 | // terminate current process sending abrt 41 | std::abort(); 42 | }); 43 | } 44 | 45 | // Register function to be called when the program exits. 46 | // Note: It does not override the normal termination behavior. 47 | std::atexit([](){ 48 | std::cerr << " [INFO] Normal termination. Ok." << std::endl; 49 | }); 50 | 51 | 52 | if(argc < 2) { 53 | std::puts(" [ERROR] Missing command. Shutdown"); 54 | return 1; 55 | } 56 | std::string cmd = argv[1]; 57 | 58 | if(cmd == "terminate_normal1") 59 | { 60 | std::puts(" [TRACE] Nothing."); 61 | } 62 | else if(cmd == "terminate_normal2") 63 | { 64 | std::puts(" [TRACE] Call std::exit(int status_code);"); 65 | std::exit(2); 66 | } 67 | else if (cmd == "terminate_except") 68 | { 69 | std::puts(" [TRACE] Before throwing exception"); 70 | throw std::runtime_error("Invalid input domain"); 71 | std::puts(" [TRACE] After throwing exception"); 72 | 73 | } else if (cmd == "terminate_thread") 74 | { 75 | using namespace std::chrono_literals; 76 | std::puts(" [TRACE] Joinable thread out of scope without calling .join() or detach"); 77 | 78 | std::thread th{ [](){ 79 | while(true) { 80 | std::puts(" [TRACE] Thread running ...."); 81 | std::this_thread::sleep_for(1s); 82 | } 83 | }}; 84 | 85 | // Missing thread::join() or thread::detach method call 86 | // => The runtime calls std::terminate() 87 | } 88 | 89 | std::cout << " [TRACE] End of main function" << std::endl; 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /src/constexpr-function.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Basic demonstration of constexpr function 3 | //------------------------------------------------------------- 4 | 5 | #include 6 | 7 | using BigInt = unsigned long; 8 | 9 | // ====== Recursive template metaprogramming (Wikipedia) ==== 10 | // Code taken from Wikipedia: 11 | // + https://en.wikipedia.org/wiki/Template_metaprogramming 12 | 13 | template 14 | struct Factorial 15 | { 16 | enum { value = N * Factorial::value }; 17 | }; 18 | 19 | template <> 20 | struct Factorial<0> 21 | { 22 | enum { value = 1 }; 23 | }; 24 | 25 | 26 | // =================== Constexpr C++11 =========================== // 27 | // Limitations: No loops, no for-loops, while-loops, no std::cout, std::cerr, 28 | // no std::sin, std::cos or other math functions computed at runtime. 29 | 30 | // Version A => 31 | constexpr BigInt factorialA(BigInt n){ 32 | return n == 1 ? 1 : n * factorialA(n - 1); 33 | } 34 | 35 | // =================== Constexpr C++14 =========================== // 36 | // Limitations: no std::cout, std::cerr, no std::sin, std::cos or 37 | // other math functions computed at runtime. 38 | 39 | 40 | // Version B => Since C++14 (Not possible in C++11) 41 | constexpr BigInt factorialB(BigInt n) 42 | { 43 | BigInt acc = 1; 44 | for(size_t i = 1; i <= n; i++) 45 | acc = acc * i; 46 | return acc; 47 | } 48 | 49 | // Version C => Since C++14 50 | constexpr auto factorialC(BigInt n) -> BigInt 51 | { 52 | BigInt acc = 1; 53 | for(size_t i = 1; i <= n; i++) 54 | acc = acc * i; 55 | return acc; 56 | } 57 | 58 | void showNumber() 59 | 60 | int main() 61 | { 62 | std::cout << " ======== Old C++ ============= " << "\n"; 63 | 64 | std::cout << "Factorial(4) = " << Factorial<4>::value << "\n"; 65 | std::cout << "Factorial(5) = " << Factorial<5>::value << "\n"; 66 | 67 | static_assert(Factorial<4>::value == 24, "Error: result supposed to be equal to 24"); 68 | static_assert(Factorial<5>::value == 120, ""); 69 | static_assert(Factorial<6>::value == 720, ""); 70 | 71 | std::cout << " ======== New C++ >= C++11 ============= " << "\n"; 72 | 73 | constexpr BigInt factA4 = factorialA(4); 74 | constexpr BigInt factA5 = factorialA(5); 75 | constexpr BigInt factB4 = factorialB(4); 76 | constexpr BigInt factB5 = factorialB(5); 77 | 78 | std::cout << "factorialA(4) = " << factA4 << "\n"; 79 | std::cout << "factorialA(5) = " << factA5 << "\n"; 80 | std::cout << "factorialB(4) = " << factB4 << "\n"; 81 | std::cout << "factorialB(5) = " << factB5 << "\n"; 82 | 83 | // Note: factorial(6) will not is not computed at compile-time. 84 | // Instead, it is be computed at runtime, and the compiler 85 | // generates an ordinary function named factorialB 86 | std::cout << "factorialB(6) = " << factorialB(6) << "\n"; 87 | 88 | // Generates compilation error when false 89 | static_assert(factorialA(4) == 24, ""); 90 | static_assert(factorialA(5) == 120, ""); 91 | static_assert(factorialB(4) == 24, ""); 92 | static_assert(factorialB(5) == 120, ""); 93 | static_assert(factorialC(6) == 720, ""); 94 | static_assert(factorialC(7) == 7 * 720, ""); 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /src/windows/winapi-enconding1.cpp: -------------------------------------------------------------------------------- 1 | // File: winapi-enconding1.cpp 2 | // Brief: Test Windows API character enconding features. 3 | // Author: Caio Rodrigues 4 | //----------------------------------------------------------------- 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Enable Unicode version of Windows API compile with -DWITH_UNICODE 11 | #ifdef WITH_UNICODE 12 | #define UNICODE 13 | #define _UNICODE 14 | #endif 15 | 16 | #include 17 | #include 18 | 19 | int main(){ 20 | // ===========> EXPERIMENT 1 - Print to Console ============// 21 | 22 | std::cout << "\n ===>>> EXPERIMENT 1: Print to terminal [ANSI/UTF8] <<<=== " << std::endl; 23 | { 24 | std::cout << " [COUT] Some text example - указан - 读写汉字1 " << "\n"; 25 | std::wcout << L" [WCOUT] Some text example - указан - 读写汉字1 " << L"\n"; 26 | } 27 | 28 | // ===========> EXPERIMENT 2 - Print to File ============// 29 | std::cout << "\n ===>>> EXPERIMENT 2: Write non ANSI Chars to File <<<=== " << "\n"; 30 | std::stringstream ss; 31 | ss << " Text in Cyrllic Script: Если указан параметр " << "\n" 32 | << " Text in Chinese Script: 读写汉字1 " << "\n" 33 | << "\n"; 34 | 35 | auto dfile = std::ofstream("logging.txt"); 36 | dfile << ss.str() << std::flush; 37 | 38 | 39 | // ===========> EXPERIMENT 4 - WinAPI - CreateDirectory ============// 40 | std::cout << "\n ===>>> EXPERIMENT 3: WinAPI CreateDirectory <<<=== " << std::endl; 41 | 42 | { // -- ANSI Version of CreateDirectory API 43 | bool res; 44 | res = CreateDirectoryA("directoryANSI-读写汉字1", NULL); 45 | std::cout << "Successful 1 ?= " << std::boolalpha << res << std::endl; 46 | } 47 | 48 | { // -- Unicode (UTF16) - Wide character version of CreateDirectory API 49 | bool res; 50 | res = CreateDirectoryW(L"directoryWCHAR-读写汉字", NULL); 51 | std::cout << "Successful 2 ?= " << std::boolalpha << res << std::endl; 52 | } 53 | { 54 | // -- TCHAR Version Wide character version of CreateDirectory API 55 | bool res; 56 | 57 | #ifdef UNICODE 58 | std::cout << " [INFO] UNICODE (UTF16) CreateDirectory expanded to CreateDirectoryW" << std::endl; 59 | #else 60 | std::cout << " [INFO] ANSI CreateDirectory expanded to CreateDirectoryA" << std::endl; 61 | #endif 62 | res = CreateDirectory(_T("directoryTCHAR-读写汉字"), NULL); 63 | std::cout << "Successful 3 ?= " << std::boolalpha << res << std::endl; 64 | } 65 | 66 | 67 | // ===========> EXPERIMENT 4 - WinAPI - MessageBox ============// 68 | std::cout << "\n ===>>> EXPERIMENT 4: MessageBox <<<=== " << std::endl; 69 | 70 | DWORD const infoboxOptions = MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND; 71 | // Text in UTF8 => Note => Windows API doesn't work with UTF8 72 | // or multi-byte characters as the API treats the chars as they were ANSI. 73 | char narrowText [] = "Some chinese text não inglês 读写汉字 - 学中文"; 74 | // Unicode text in UTF16 75 | wchar_t wideText [] = L"Some chinese text não inglês 读写汉字 - 学中文"; 76 | MessageBoxA( 0, narrowText, "ANSI (narrow) text:", infoboxOptions ); 77 | MessageBoxW( 0, wideText, L"Unicode (wide) text:", infoboxOptions ); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /src/windows/winlNet-basic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include //Provides URLDownloadToFileW 8 | #include 9 | #include 10 | 11 | // Only for MSVC 12 | #pragma comment(lib, "urlmon.lib") 13 | #pragma comment(lib, "wininet.lib") 14 | 15 | auto launchedFromConsole() -> bool; 16 | 17 | // Simple C++ wrapper for the function: URLDownloadToFileA 18 | HRESULT downloadFile(std::string url, std::string file); 19 | 20 | void testHTTPRequest(); 21 | 22 | int main(){ 23 | // ================== File Download ========================= // 24 | // 25 | HRESULT hr; 26 | 27 | hr = downloadFile("http://httpbin.org/image/jpeg", "image.jpeg"); 28 | if(SUCCEEDED(hr)) 29 | std::cout << "Download successful OK." << '\n'; 30 | else 31 | std::cout << "Download failed." << '\n'; 32 | 33 | hr = downloadFile("httpxpabin.org/image/jpeg-error", "image2.jpeg"); 34 | if(SUCCEEDED(hr)) 35 | std::cout << "Download sucessful OK." << '\n'; 36 | else 37 | std::cout << "Download failed." << '\n'; 38 | 39 | //=============== HTTP Protocol ===================================// 40 | // 41 | testHTTPRequest(); 42 | 43 | if(!launchedFromConsole()){ 44 | std::cout << "Type RETURN to exit" << std::endl; 45 | std::cin.get(); 46 | } 47 | return 0; 48 | } 49 | 50 | auto launchedFromConsole() -> bool { 51 | DWORD procIDs[2]; 52 | DWORD maxCount = 2; 53 | DWORD result = GetConsoleProcessList((LPDWORD)procIDs, maxCount); 54 | return result != 1; 55 | } 56 | 57 | HRESULT downloadFile(std::string url, std::string file){ 58 | HRESULT hr = URLDownloadToFileA( 59 | // (pCaller) Pointer to IUknown instance (not needed) 60 | NULL 61 | // (szURL) URL to the file that will be downloaded 62 | ,url.c_str() 63 | // (szFileName) File name that the downloaded file will be saved. 64 | ,file.c_str() 65 | // (dwReserved) Reserverd - always 0 66 | ,0 67 | // (lpfnCB) Status callback 68 | ,NULL 69 | ); 70 | return hr; 71 | } 72 | 73 | void testHTTPRequest(){ 74 | // Reference: http://www.cplusplus.com/forum/beginner/75062/ 75 | HINTERNET hConnect = InternetOpen("Fake browser",INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0); 76 | if(!hConnect){ 77 | std::cerr << "Error: Connection Failure."; 78 | return; 79 | } 80 | 81 | HINTERNET hAddr = InternetOpenUrl( 82 | hConnect 83 | ,"http://www.httpbin.org/get" 84 | ,NULL 85 | ,0 86 | ,INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION 87 | ,0 88 | ); 89 | 90 | if ( !hAddr ) 91 | { 92 | DWORD errorCode = GetLastError(); 93 | std::cerr << "Failed to open URL" << '\n' << "Error Code = " << errorCode; 94 | InternetCloseHandle(hConnect); 95 | return; 96 | } 97 | 98 | // Buffer size - 4kb or 4096 bytes 99 | char bytesReceived[4096]; 100 | DWORD NumOfBytesReceived = 0; 101 | while(InternetReadFile(hAddr, bytesReceived, 4096, &NumOfBytesReceived) && NumOfBytesReceived ) 102 | { 103 | std::cout << bytesReceived; 104 | } 105 | 106 | InternetCloseHandle(hAddr); 107 | InternetCloseHandle(hConnect); 108 | 109 | } // --- EoF testHTTPRequest() --- // 110 | -------------------------------------------------------------------------------- /src/cpp17/cpp17-structured-bindings.cpp: -------------------------------------------------------------------------------- 1 | // Brief: C++17 Structured bindings experiments. 2 | // Author: Caio Rodrigues 3 | //-------------------------------------------------- 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(){ 14 | 15 | { 16 | std::puts("\n=== EXPERIMENT 1: Decompose: pair - binding - pair ====="); 17 | auto p = std::pair("C++", 17); 18 | auto [name, version] = p; 19 | std::cout << " name = " << name << " ; version = " << version << std::endl; 20 | } 21 | 22 | { 23 | std::puts("\n=== EXPERIMENT 2: Decompose: map / 'hash-table' - ====="); 24 | auto database = std::map{{"c++", 17}, {"rust", 10}, {"Forth", 200}}; 25 | for(const auto& [key, value] : database) 26 | std::cout << "key = " << key << " ; value = " << value << std::endl; 27 | } 28 | 29 | { 30 | std::puts("\n=== EXPERIMENT 3: Decompose: tuple - ====="); 31 | using DatabaseRow = std::tuple; 32 | auto database = std::vector{ 33 | {100, "Fried tasty fresh cheese", 3.45}, 34 | {400, "Super hot toasted coffee.", 6.25}, 35 | {500, "Fresh Orange Juice", 4.50}, 36 | }; 37 | 38 | for(const auto& [id, name, price]: database) 39 | std::cout << " ROW=> id = " << id 40 | << " ; name = " << name 41 | << " ; price = " << price 42 | << std::endl; 43 | } 44 | 45 | { 46 | std::puts("\n=== Decompose: tuple with Reference - ====="); 47 | using DatabaseRow = std::tuple; 48 | auto row = DatabaseRow{200, "Coffee", 4.5}; 49 | auto& [id, name, price] = row; 50 | 51 | std::printf(" [BEFORE] => Product{ id = %d ; name = %s ; price = %f }\n", 52 | std::get<0>(row), std::get<1>(row).c_str(), std::get<2>(row)); 53 | 54 | id = 500, name = "italian-sytle coffee", price = 10.60; 55 | 56 | std::printf(" [AFTER] => Product{ id = %d ; name = %s ; price = %f }\n", 57 | std::get<0>(row), std::get<1>(row).c_str(), std::get<2>(row)); 58 | } 59 | 60 | { 61 | std::puts("\n=== EXPERIMENT 4: Decompose: Structs - ====="); 62 | struct GeoCoordinate{ 63 | std::string name; 64 | double latitude; 65 | double longitude; 66 | }; 67 | auto geoDatabase = std::deque{ 68 | {"Bogota", 4.7110, -74.0721} 69 | ,{"Beijing", 39.9042, 116.4074} 70 | ,{"Gauteng", -26.2708, 28.1123} 71 | ,{"Buenos Aires", -34.6037, -58.3816} 72 | ,{"Brasilia", -15.8267, -47.9218} 73 | }; 74 | std::cout << std::setprecision(3); 75 | std::for_each(geoDatabase.begin(), geoDatabase.end(), 76 | [](const auto& city){ 77 | const auto& [name, lat, lon] = city; 78 | std::cout << std::setw(15) << std::left << name 79 | << std::setw(8) << std::right << lat 80 | << std::setw(8) << lon 81 | << "\n"; 82 | 83 | }); 84 | } 85 | 86 | { 87 | std::puts("\n=== EXPERIMENT 5: Decompose: C-Array - ====="); 88 | double array [3] = {10.23, 90.23, 100.0}; 89 | auto [x, y, z] = array; 90 | std::printf(" array { x = %.3f ; y = %.3f ; z = %.3f }", x, y, z); 91 | 92 | } 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /src/cppVector2D.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class vector2D 8 | { 9 | private: 10 | // Private members 11 | double x; 12 | double y; 13 | 14 | public: 15 | 16 | // Class constructors 17 | vector2D(); 18 | vector2D(double vX, double vY); 19 | 20 | // Getters 21 | double getX() const; 22 | double getY() const; 23 | 24 | void print() const; 25 | 26 | void move(double dx, double dy); 27 | 28 | void setPos(double vX, double vY); 29 | 30 | //-- Operators (Binary Functions/ Class members) -- // 31 | 32 | vector2D operator+ (vector2D B); 33 | vector2D operator- (vector2D B); 34 | 35 | vector2D operator* (double factor); 36 | vector2D operator/ (double factor); 37 | 38 | }; 39 | 40 | vector2D::vector2D() { 41 | x = 0.0; 42 | y = 0.0; 43 | } 44 | 45 | vector2D::vector2D(double vX, double vY){ 46 | x = vX; 47 | y = vY; 48 | } 49 | 50 | double vector2D::getX() const{ 51 | return x; 52 | } 53 | 54 | double vector2D::getY() const{ 55 | return y; 56 | } 57 | 58 | 59 | void vector2D::move(double dx, double dy){ 60 | x = x + dx; 61 | y = y + dy; 62 | } 63 | 64 | 65 | void vector2D::setPos(double vX, double vY) 66 | { 67 | x = vX; 68 | y = vY; 69 | } 70 | 71 | void vector2D::print() const 72 | { 73 | cout << "Vector2D (X = " << x << ", Y = " << y << ")" << endl; 74 | } 75 | 76 | vector2D vector2D::operator + (vector2D B){ 77 | vector2D res; 78 | res.x = x + B.x; 79 | res.y = y + B.y; 80 | return res; 81 | } 82 | 83 | 84 | vector2D vector2D::operator - (vector2D B){ 85 | vector2D res; 86 | res.x = x - B.x; 87 | res.y = y - B.y; 88 | return res; 89 | } 90 | 91 | 92 | vector2D vector2D::operator * (double factor){ 93 | vector2D res; 94 | res.x = x * factor; 95 | res.y = y * factor; 96 | return res; 97 | } 98 | 99 | 100 | vector2D vector2D::operator / (double factor){ 101 | vector2D res; 102 | res.x = x / factor; 103 | res.y = y / factor; 104 | return res; 105 | } 106 | 107 | 108 | 109 | int main(){ 110 | 111 | vector2D vA = vector2D(); 112 | vector2D vB = vector2D(10.23, -8.63); 113 | 114 | vA.print(); 115 | vA.move(2.0, 3.0); 116 | vA.print(); 117 | 118 | vB.print(); 119 | vB.move(2.0, 3.0); 120 | vB.print(); 121 | 122 | cout << "\n(1) Vc = vA + vB = " << endl; 123 | vector2D vC = vA + vB; 124 | vC.print(); 125 | 126 | cout << "\n(2) Vc = vA + vB = " << endl; 127 | (vA + vB).print(); 128 | 129 | cout << "\n(3) vB * 3.0 = " << endl; 130 | (vB * 3.0).print(); 131 | 132 | cout << "\n(4) (vA + vB) / 2.0 = " << endl; 133 | vector2D vD = (vB + vB) / 2.0 ; 134 | vD.print(); 135 | 136 | 137 | // ----------- Pointer Tests ------------------ // 138 | 139 | vector2D * vp ; 140 | 141 | vp = & vB ; // Assign pointer to address of vector vB. 142 | 143 | cout << "\n\nPointer address = " << vp << endl ; 144 | 145 | 146 | cout << "\nvp->print() = " << endl; 147 | vp->print(); 148 | 149 | cout << "\n(*vp).print() = " << endl; 150 | (*vp).print(); 151 | 152 | cout << "\nvector2D m = *vp; m.print(); = " << endl; 153 | vector2D m = *vp; 154 | m.print(); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /src/windows/client-socket-shell1.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // File: client-socket-shell1.cpp 3 | // Brief: Basic Winsocket (Windows socket) echo client shell in C++. 4 | // Author: Caio Rodrigues 5 | //----------------------------------------------------------------- 6 | 7 | #include 8 | #include 9 | #include 10 | #pragma comment (lib, "Ws2_32.lib") 11 | // #pragma comment (lib, "Mswsock.lib") 12 | // #pragma comment (lib, "AdvApi32.lib") 13 | 14 | int main(int argc, char** argv){ 15 | if(argc < 3){ 16 | std::cerr << "Usage: " << argv[0] << " [HOSTNAME or ADDRESS] [PORT]" << std::endl; 17 | return EXIT_FAILURE; 18 | } 19 | 20 | // Client configuration 21 | const char* host = argv[1]; 22 | unsigned int port = std::stoi(argv[2]); 23 | 24 | //Start up Winsock… 25 | WSADATA wsadata; 26 | int error = WSAStartup(0x0202, &wsadata); 27 | if(error){ 28 | std::cerr << "Error: failed to initialize WinSock." << std::endl; 29 | return EXIT_FAILURE; 30 | } 31 | 32 | // Create client socket 33 | SOCKET client = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 34 | if(client == INVALID_SOCKET){ 35 | std::cerr << "Error, I cannot create socket" << std::endl; 36 | return EXIT_FAILURE; 37 | } 38 | SOCKADDR_IN addr; 39 | memset(&addr, 0, sizeof(addr)); 40 | addr.sin_family = AF_INET; 41 | addr.sin_addr.s_addr = inet_addr(host); 42 | addr.sin_port = htons(port); 43 | 44 | // Attemp to connect to server and exit on failure. 45 | int connval = connect(client, reinterpret_cast(&addr), sizeof(addr)); 46 | if(connval == SOCKET_ERROR){ 47 | std::cerr << "Error: cannot connect to server." << std::endl; 48 | //Returns status code other than zero 49 | return EXIT_FAILURE; 50 | } 51 | 52 | std::string msgClientConnect = " [CLIENT] Connected to server OK.\n"; 53 | ::send(client, msgClientConnect.c_str(), msgClientConnect.size(), 0); 54 | 55 | std::string msg = " [CLIENT SHELL]>> "; 56 | std::string echo; 57 | 58 | bool flag = true; 59 | while(flag){ 60 | ::send(client, msg.c_str(), msg.size(), 0); 61 | // Create a buffer with 2024 bytes or 2kb 62 | std::string buffer(2024, 0); 63 | //Returns the number of received bytes 64 | int n = ::recv(client, &buffer[0], buffer.size()-1, 0); 65 | echo = " => [ECHO] " + buffer + "\n"; 66 | ::send(client, echo.c_str(), echo.size(), 0); 67 | if(WSAGetLastError() == SOCKET_ERROR){ 68 | std::cerr << "Disconnected OK." << std::endl; 69 | flag = false; 70 | break; 71 | } else { 72 | buffer.resize(n); 73 | if(buffer == "exit\n" ){ 74 | std::string exitMessage = " [CLIENT] Disconnect gracefully - OK.\n"; 75 | ::send(client, exitMessage.c_str(), exitMessage.size(), 0); 76 | std::cerr << "[LOG] I got an exit message. Shutdowing socket now!" << "\n"; 77 | std::cerr << "[LOG] Gracefully disconnecting application" << "\n"; 78 | std::cerr.flush(); 79 | break; 80 | } 81 | std::cout << " [SERVER SENT] >> " << buffer ; //<< std::endl; 82 | // Force writing buffer to the stdout 83 | std::cout.flush(); 84 | } 85 | } 86 | std::cerr << "Finished." << std::endl; 87 | ::closesocket(client); 88 | ::WSACleanup(); 89 | // Returns status code 0 90 | return EXIT_SUCCESS; 91 | } 92 | -------------------------------------------------------------------------------- /src/boost/boost-memory-mapped-file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace bi = boost::interprocess; 12 | 13 | /** @brief Returns true if exists. */ 14 | bool fileExists(std::string const& fileName) 15 | { 16 | auto fs = std::ifstream(fileName); 17 | return fs.good(); 18 | } 19 | 20 | /** Generic Memory-mapped file allocator */ 21 | template 22 | using MMFAllocator = bi::allocator ; 23 | 24 | /** Generic STL vector allocated in memory-mapped file */ 25 | template 26 | using MMFVector = std::vector> ; 27 | 28 | int main() 29 | { 30 | constexpr const char* fileName = "memory-dump.dat"; 31 | constexpr size_t fileSize = 4096; // 4 kbytes 32 | bool flagFileExists = fileExists(fileName); 33 | 34 | // Manged file mapping object => Creates the file if it does not exists 35 | auto mf = bi::managed_mapped_file{bi::open_or_create, fileName, fileSize}; 36 | 37 | if(!flagFileExists){ 38 | // Executed when the file did not exist 39 | std::cout << " [INFO] Setting file data" << std::endl; 40 | mf.construct("NumberOfNodes")(100); 41 | mf.construct("Speed")(200.0); 42 | mf.construct("Text")("'Allocated text in memory mapped file'"); 43 | 44 | // Allocate std::vector 45 | MMFAllocator aloc1(mf.get_segment_manager()); 46 | MMFVector* pVector = mf.construct>("AVector")(aloc1); 47 | pVector->reserve(20); 48 | pVector->push_back(40.5); 49 | pVector->push_back(98.10); 50 | pVector->push_back(-50.45); 51 | pVector->push_back(10); 52 | 53 | return EXIT_SUCCESS; 54 | } 55 | 56 | // ======= Executed when file already exists =========// 57 | 58 | std::cout << " [INFO] Retrieving objects from memory mapped file" << std::endl; 59 | 60 | // Retrieve variable NumberOfNodes with very explicitly and verbose notation 61 | std::pair pairResult1 = mf.find("NumberOfNodes"); 62 | if(pairResult1.first == nullptr){ 63 | std::cerr << " [ERROR] I cannot find the object 'NumberOfNodes'" << std::endl; 64 | return EXIT_FAILURE; 65 | } 66 | std::cout << "Number of nodes = " << *pairResult1.first << "\n"; 67 | (*pairResult1.first)++; 68 | 69 | // Retrieve variable text 70 | auto [pText, _size1 ] = mf.find("Text"); 71 | assert(pText != nullptr); 72 | std::cout << "Text = " << *pText << "\n"; 73 | 74 | // Retrieve variable speed 75 | auto [pSpeed, _size2 ] = mf.find("Speed"); 76 | assert(pSpeed != nullptr); 77 | std::cout << "Speed = " << *pSpeed << "\n"; 78 | std::cout << " => Set new speed := "; 79 | std::cin >> *pSpeed; 80 | 81 | // Rerieve vector 82 | auto [pVector, _size3] = mf.find>("AVector"); 83 | assert(pVector != nullptr); 84 | std::cout << "\n pVector->size() = " << pVector->size() << std::endl; 85 | size_t idx = 0; 86 | for(auto const& x: *pVector) 87 | std::cout << " pVector[" << idx++ << "] = " << x << std::endl ; 88 | 89 | pVector->push_back(*pSpeed); 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /src/design-patterns/polymorphic-io1.cpp: -------------------------------------------------------------------------------- 1 | // File: polymorphic-io1.cpp 2 | // Brief: Demonstration about how to write polymorphic IO code or I/O agnostic code. 3 | // Author: Caio Rodrigues 4 | //------------------------------------------------------------------------------------- 5 | 6 | #include 7 | #include // std::ostream -> Root Output class 8 | #include // std::istream -> Root Input class 9 | #include // File. 10 | #include // string stream 11 | #include 12 | #include 13 | #include 14 | 15 | namespace VectorIO{ 16 | /** Write vector of doubles to any output stream. */ 17 | auto writeVector(std::ostream& os, const std::vector& xs ) -> void; 18 | // Version with R-value reference can accept temporary objects. 19 | auto writeVector(std::ostream&& os, const std::vector& xs) -> void; 20 | 21 | /** Read vector of doubles from any input stream. */ 22 | auto readVector(std::istream& is) -> std::vector; 23 | auto readVector(std::istream&& is) -> std::vector; 24 | } 25 | 26 | int main(){ 27 | using VectorIO::writeVector; 28 | using VectorIO::readVector; 29 | 30 | std::vector vtest = {2.0, 4.0, 5.0, 10.0, 3.45, 9.5}; 31 | 32 | std::cout << "\n TEST1 Writing to stdout (Standard output stream) " << "\n"; 33 | writeVector(std::cout, vtest); 34 | 35 | std::cout << "\n TEST2 Writing to stderr (Standard error stream) " << "\n"; 36 | writeVector(std::cerr, vtest); 37 | 38 | std::cout << "\n TEST3 Writing to std::stringstream " << "\n"; 39 | std::stringstream fakeFile; 40 | writeVector(fakeFile, vtest); 41 | std::cout << "fakeFile = " << fakeFile.str() << "\n"; 42 | 43 | std::cout << "\n TEST4 Reading from std::stringstream " << "\n"; 44 | auto out1 = readVector(fakeFile); 45 | writeVector(std::cout, out1); 46 | 47 | std::cout << "\n TEST5 Write to a file" << "\n"; 48 | // Note: It is not possible without R-value reference. 49 | writeVector(std::ofstream("vector.txt"), vtest); 50 | 51 | std::cout << "\n TEST6 Read from file - Version 1" << "\n"; 52 | // Call R-value reference version 53 | auto out2 = readVector(std::ifstream("vector.txt")); 54 | writeVector(std::cout, out2); 55 | 56 | std::cout << "\n TEST7 Read from file - Version 2" << "\n"; 57 | std::ifstream fd{"vector.txt"}; 58 | // Call L-value reference version of readVector 59 | auto out3 = readVector(fd); 60 | writeVector(std::cout, out3); 61 | } 62 | 63 | namespace VectorIO{ 64 | auto writeVector(std::ostream& os, const std::vector& xs) -> void 65 | { 66 | os << "VECTOR"; 67 | os << " "; 68 | for(auto x: xs) 69 | os << x << " "; 70 | os << "\n"; 71 | os.flush(); 72 | } 73 | auto writeVector(std::ostream&& os, const std::vector& xs) -> void 74 | { 75 | std::cerr << " [LOG] (writeVector) R-value reference" << "\n"; 76 | writeVector(os, xs); 77 | } 78 | auto readVector(std::istream& is) -> std::vector 79 | { 80 | std::vector xlist; 81 | std::string label; 82 | is >> label; 83 | if(label != "VECTOR") 84 | throw std::runtime_error("Error: wrong file layout."); 85 | double x; 86 | while(is.good() && !is.eof()){ 87 | is >> x; 88 | xlist.push_back(x); 89 | } 90 | return xlist; 91 | } 92 | auto readVector(std::istream&& is) -> std::vector 93 | { 94 | std::cerr << " [LOG] (readVector) R-value reference" << "\n"; 95 | return readVector(is); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/insertionExtractionOverload.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define DBG_DISP(expr) std::cerr << __FILE__ << ":" << __LINE__ << ":" \ 8 | << " ; " << #expr << " = " << (expr) << std::endl 9 | 10 | // === file: Product.hpp - interface ====================// 11 | 12 | class Product{ 13 | private: 14 | int m_id; 15 | std::string m_name; 16 | double m_price; 17 | public: 18 | Product(); 19 | Product(int id, std::string const& name, double price); 20 | int Id() const; 21 | std::string Name() const; 22 | double Price() const; 23 | void showProduct() const; 24 | 25 | friend 26 | auto operator<<(std::ostream& os, Product const& prod) -> std::ostream&; 27 | 28 | friend 29 | auto operator>>(std::istream& is, Product& prod) -> std::istream&; 30 | }; 31 | 32 | // === file: main.cpp ==================================// 33 | 34 | int main(){ 35 | Product p1{200, "Arabica Coffee", 4.50}; 36 | Product p2{300, "Orange 1kg ", 10.0}; 37 | Product p3{126, "XYWZ soft drink", 15.60}; 38 | 39 | std::puts(" >>> EXPERIMENT 1 == Print Products ==========="); 40 | std::cout << "Product p1 = {" << p1 << " }" << std::endl; 41 | std::cout << "Product p2 = {" << p2 << " }" << std::endl; 42 | std::cout << "Product p3 = {" << p3 << " }" << std::endl; 43 | 44 | std::puts(" >>> EXPERIMENT 2 == Print Products to memory stream (memory file) ===="); 45 | std::stringstream ss; 46 | ss << p1 << "\n" << p2 << "\n" << p3; 47 | std::cout << "ss = \n" << ss.str() << std::endl; 48 | 49 | std::puts(" >>> EXPERIMENT 3 == Read products from memory stream ===="); 50 | Product pr; 51 | ss >> pr; 52 | std::cout << " pr1 = " << pr << std::endl; 53 | ss >> pr; 54 | std::cout << " pr2 = " << pr << std::endl; 55 | ss >> pr; 56 | std::cout << " pr3 = " << pr << std::endl; 57 | 58 | std::puts(" >>> EXPERIMENT 4 == Read products from console ===="); 59 | Product prod; 60 | while(!std::cin.eof()){ 61 | std::cout << "Enter product: "; 62 | std::cin >> prod; 63 | std::cout << " prod = " << prod << " ; " 64 | << " price = " << prod.Price() 65 | << std::endl; 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | // ==== file: Product.cpp - Implementation ===============// 72 | 73 | Product::Product(int id, std::string const& name, double price): 74 | m_id(id), m_name(name), m_price(price) 75 | { 76 | } 77 | 78 | Product::Product(): Product(-1, "unnamed", 0.0) 79 | { 80 | } 81 | 82 | void Product::showProduct() const 83 | { 84 | std::cout << "Product{ " 85 | << "; id = " << m_id 86 | << " ; name = " << m_name 87 | << " ; price = " << m_price 88 | << " }\n" ; 89 | } 90 | 91 | int Product::Id() const 92 | { 93 | return m_price; 94 | } 95 | 96 | std::string Product::Name() const 97 | { 98 | return m_name; 99 | } 100 | 101 | double Product::Price() const 102 | { 103 | return m_price; 104 | } 105 | 106 | auto operator<<(std::ostream& os, Product const& prod) -> std::ostream& 107 | { 108 | os << " " << prod.m_id 109 | << " " << std::quoted(prod.m_name) 110 | << " " << prod.m_price; 111 | return os; 112 | } 113 | 114 | auto operator>>(std::istream& is, Product& prod) -> std::istream& 115 | { 116 | return is >> prod.m_id >> std::quoted(prod.m_name) >> prod.m_price; 117 | } 118 | -------------------------------------------------------------------------------- /src/template-hof1.cpp: -------------------------------------------------------------------------------- 1 | /** File: template-hof1.cpp 2 | * Brief: Shows how to implement template higher order functions which operates on containers. 3 | * Features: Template metaprogramming, C++11, functional programming and STL. 4 | ****************************************************************************/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /** Apply a function to every element of a container */ 14 | template class CONTAINER> 15 | void forRange1(CONTAINER& cont, std::function fn){ 16 | for(auto i = std::begin(cont); i != std::end(cont); i++) 17 | fn(*i); 18 | } 19 | 20 | /** Apply a function to every element of a container */ 21 | template 22 | void forRange2(CONTAINER& cont, std::function fn){ 23 | for(auto i = std::begin(cont); i != std::end(cont); i++) 24 | fn(*i); 25 | } 26 | 27 | /** Template for folding over a container in a similar way to the higher order function fold. 28 | * Note: 29 | * + CONTAINER parameter accepts any argument which has .begin() and .end() methods 30 | * returning iterators. 31 | * + STEPFN type parameters accepts any function-object, function pointer or lambda 32 | * whith the following signature: (ACC, X) => ACC where ACC is the accumulator type 33 | * and X is the type of the container element. 34 | */ 35 | template 36 | auto foldRange(CONTAINER& cont, const ACC& init, STEPFN fn) -> ACC { 37 | ACC acc{init}; 38 | for(auto i = std::begin(cont); i != std::end(cont); i++) 39 | acc = fn(*i, acc); 40 | return acc; 41 | } 42 | 43 | int main(){ 44 | std::ios_base::sync_with_stdio(false); 45 | 46 | std::vector vec{1, 2, 400, 100}; 47 | std::list lst{1, 2, 400, 100}; 48 | 49 | // Requires template argument 50 | std::cout << "===== EXPERIMENT 1 =================\n"; 51 | std::cout << "forRange1 - Vector" << "\n"; 52 | forRange1(vec, [](int x){ std::cout << std::setw(5) << x << " "; }); 53 | std::cout << "\n"; 54 | std::cout << "forRange1 - List" << "\n"; 55 | forRange1(lst, [](int x){ std::cout << std::setw(5) << x << " "; }); 56 | std::cout << "\n"; 57 | 58 | // Doesn't require the template argument as the compiler can infer its type. 59 | std::cout << "===== EXPERIMENT 2 =================\n"; 60 | std::cout << "forRange1 - Vector" << "\n"; 61 | forRange2(vec, [](int x){ std::cout << std::setw(5) << x << " "; }); 62 | std::cout << "\n"; 63 | std::cout << "forRange1 - list" << "\n"; 64 | forRange2(lst, [](int x){ std::cout << std::setw(5) << x << " "; }); 65 | std::cout << "\n"; 66 | 67 | std::cout << "===== EXPERIMENT 3 =================\n"; 68 | int result1 = foldRange(vec, 0, [](int x, int acc){ 69 | return x + acc; 70 | }); 71 | std::cout << "sum(vec1) = " << result1 << "\n" ; 72 | int result2 = foldRange(lst, 0, std::plus()); 73 | std::cout << "sum(lst) = " << result2 << "\n" ; 74 | 75 | std::cout << "product(lst) = " << foldRange(lst, 1, std::multiplies()) << "\n" ; 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /src/polymorphism1.C: -------------------------------------------------------------------------------- 1 | // CLING/ROOT Script for testing OOP polymorphism in C++ 2 | // Author: Caio Rodrigues 3 | //------------------------------------------------------- 4 | #include 5 | #include 6 | #include 7 | 8 | class Base{ 9 | public: 10 | Base(){} 11 | // Copy constructor 12 | Base(const Base& rhs){ 13 | std::cerr << " [TRACE] " << __FILE__ << ":" << __LINE__ << " " 14 | << " Base copy constructor invoked." << "\n"; 15 | } 16 | // Copy assignment operator 17 | Base& operator= (const Base& rhs){ 18 | std::cerr << " [TRACE] " << __FILE__ << ":" << __LINE__ << " " 19 | << " Base copy assignment operator invoked." << "\n"; 20 | return *this; 21 | } 22 | // The base class always need a virtual 23 | // destructor 24 | virtual ~Base() = default; 25 | 26 | virtual std::string getType() const { 27 | return "Base"; 28 | } 29 | std::string getType2() const { 30 | return "Base"; 31 | } 32 | void showType(){ 33 | //OR: std::cout << "Class type = " << getType() << "\n"; 34 | std::cout << "Class type = " << this->getType() << "\n"; 35 | } 36 | }; 37 | 38 | class DerivedA: public Base{ 39 | public: 40 | DerivedA(){} 41 | std::string getType() const { 42 | return "DerivedA"; 43 | } 44 | std::string getType2() const { 45 | return "DerivedA"; 46 | } 47 | }; 48 | 49 | class DerivedB: public Base{ 50 | public: 51 | DerivedB(){} 52 | std::string getType() const { 53 | return "DerivedB"; 54 | } 55 | std::string getType2() const { 56 | return "DerivedB"; 57 | } 58 | }; 59 | 60 | // Pass by value 61 | void printClassNameValue(Base obj){ 62 | std::cout << "Object type is: " << obj.getType() << "\n"; 63 | } 64 | // Pass by pointer 65 | void printClassNamePtr(const Base* obj){ 66 | std::cout << "Object type is: " << obj->getType() << "\n"; 67 | } 68 | // Pass by reference 69 | void printClassNameRef(const Base& obj){ 70 | std::cout << "Object type is: " << obj.getType() << "\n"; 71 | } 72 | 73 | // This factory functon will fail due to object slicing 74 | Base factoryFunctionValue(const std::string& type){ 75 | if(type == "base") 76 | return Base(); 77 | if(type == "da") 78 | return DerivedA(); 79 | if(type == "db") 80 | return DerivedB(); 81 | throw std::runtime_error("Error: class type not found."); 82 | } 83 | 84 | // Fails because the object p is destroyed when 85 | // it goes out of scope. Any attempt to use the 86 | // returned reference results in segmentation fault. 87 | Base& factoryFunctionRef(const std::string& type){ 88 | Base p; 89 | if(type == "base") 90 | p = Base(); 91 | else if(type == "da") 92 | p = DerivedA(); 93 | else if(type == "db") 94 | p = DerivedB(); 95 | else throw std::runtime_error("Error: class type not found."); 96 | return p; 97 | } 98 | 99 | // Works, however this version returning a raw pointer 100 | // is prone to memory leaks. 101 | Base* factoryFunctionRawPointer(const std::string& type){ 102 | if(type == "base") 103 | return new Base(); 104 | else if(type == "da") 105 | return new DerivedA(); 106 | if(type == "db") 107 | return new DerivedB(); 108 | return nullptr; 109 | } 110 | 111 | // Requires header: 112 | std::unique_ptr factoryFunctionSafe(const std::string& type){ 113 | if(type == "base") 114 | return std::make_unique(); 115 | else if(type == "da") 116 | return std::make_unique(); 117 | if(type == "db") 118 | return std::make_unique(); 119 | return nullptr; 120 | } 121 | -------------------------------------------------------------------------------- /src/cpp17/fold-expressions1.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // File: fold-expressions1.cpp 3 | // Brief: Demonstrations of C++17 Fold Expressions 4 | // - https://caiorss.github.io/C-Cpp-Notes/index.html 5 | //--------------------------------------------------- 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | template 16 | auto multiply(Args ... args) 17 | { 18 | return (args * ...); 19 | } 20 | 21 | template 22 | void printArguments(Args&& ... args ) 23 | { 24 | ((std::cout << typeid(args).name() << " " << args << std::endl), ...); 25 | } 26 | 27 | template 28 | std::vector 29 | GetTypesFromArgs1(){ 30 | std::vector tinfo; 31 | std::cout << "Received " << sizeof...(Args) 32 | << " types arguments" << std::endl; 33 | ((tinfo.push_back(&typeid(Args))), ...) ; 34 | return tinfo; 35 | } 36 | 37 | template 38 | std::vector 39 | GetTypesFromArgs2(Args const& ... args){ 40 | std::cout << "Received " << sizeof...(Args) 41 | << " types arguments" << std::endl; 42 | return {&typeid(args) ...}; 43 | } 44 | 45 | // Experimental: Still does not work, in some compilers, the index is not incremented. 46 | // It still falls in the undefined behavior. 47 | #ifdef EANBLE_EXPERIMENTAL 48 | template 49 | auto TypeErasureFunction(R funptr (Args ...)) 50 | -> std::function&)> 51 | { 52 | return [funptr](std::vector xs) -> std::any 53 | { 54 | int idx = -1; 55 | std::any res; 56 | res = funptr((idx++, std::any_cast(xs[idx])) ...); 57 | return res; 58 | }; 59 | } 60 | 61 | int someFunction(int x, double w, const char* name) 62 | { 63 | std::cout << " Call someFunction()" 64 | << " x = " << x 65 | << " w = " << w 66 | << " name = " << name 67 | << std::endl; 68 | return 0; 69 | } 70 | #endif 71 | 72 | 73 | int main() 74 | { 75 | std::cout << "\n ======= EXPERIMENT 1 ===============\n"; 76 | std::cout << " => Result 1 = " << multiply(1, 2, 3, 4, 5, 6) << std::endl; 77 | std::cout << " => Result 2 = " << multiply(3.5, 1.65, 0.25, 10.98, 100.5, 6) << std::endl; 78 | 79 | std::cout << "\n ======= EXPERIMENT 2 ===============\n"; 80 | printArguments(10, 200.5, "hello world", 'x'); 81 | 82 | std::cout << "\n ======= EXPERIMENT 3 ===============\n"; 83 | auto tinfo = GetTypesFromArgs1(); 84 | for(auto const& t: tinfo) 85 | { 86 | std::cout << "Name = " << t->name() 87 | << " - id = " << t->hash_code() 88 | << std::endl; 89 | } 90 | 91 | std::cout << "\n ======= EXPERIMENT 4 ===============\n"; 92 | auto tinfo2 = GetTypesFromArgs2(200, 'x', 9.87, std::string("hello world"), "CPP17"); 93 | for(auto const& t: tinfo2) 94 | { 95 | std::cout << "Name = " << t->name() 96 | << " - id = " << t->hash_code() 97 | << std::endl; 98 | } 99 | 100 | #ifdef EANBLE_EXPERIMENTAL 101 | std::cout << "\n ======= EXPERIMENT 5 ===============\n"; 102 | std::vector args = {200, 87.5, "'C++17 type erasure'" }; 103 | auto erased_someFunction = TypeErasureFunction(&someFunction); 104 | erased_someFunction(args); 105 | #endif 106 | 107 | return 0; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/boost/boost-operators.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Demonstration of Boost.Operators library for simplifying operator overloading. 3 | // Boost Operator Docs: https://www.boost.org/doc/libs/1_69_0/libs/utility/operators.htm#ordering 4 | //---------------------------------------------------------------- 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // ============ Pseudo-file: Vec3D.hpp ================= 12 | 13 | class Vec3D: public boost::less_than_comparable 14 | , public boost::addable 15 | { 16 | private: 17 | double m_x, m_y, m_z; 18 | public: 19 | Vec3D(double x, double y, double z); 20 | double norm() const; 21 | 22 | // Stream insertion operator => Make class printable 23 | friend std::ostream& operator<<(std::ostream& os, Vec3D const& vec); 24 | 25 | // Required by: boost::less_than_comparable 26 | // From this operator, boost implements the operators (<=), (>), (>=) 27 | friend bool operator<(Vec3D const& lhs, Vec3D const& rhs); 28 | 29 | // Required by: boost::addable 30 | // Boost implements: operator+(Vec3D, double) and operator+(double, Vec3D) 31 | friend Vec3D& operator+=(Vec3D& lhs, double rhs); 32 | }; 33 | 34 | // ============ Pseudo-file: main.cpp ================= 35 | 36 | template 37 | void disp(const char* variableName, variable_t const& value) 38 | { 39 | std::cout << " =>> " << variableName << " = " << value << "\n"; 40 | } 41 | 42 | int main(){ 43 | 44 | Vec3D v1 = {3, 5, 6}; 45 | Vec3D v2 = {12, 5, 9}; 46 | std::cout << std::boolalpha; 47 | disp("v1", v1); disp("v2", v2); 48 | disp("v1.norm()", v1.norm()); 49 | disp("v2.norm()", v2.norm()); 50 | 51 | std::cout << "\n EXPERIMENT 1 boost::less_than_comparable" << "\n"; 52 | std::cout << "--------------------------------------------------" << "\n"; 53 | 54 | std::cout << "[a] v1 < v2 = " << (v1 < v2) << "\n"; 55 | std::cout << "[b] v1 < v2 = " << operator<(v1, v2) << "\n\n"; 56 | 57 | std::cout << "[a] v1 <= v2 = " << (v1 <= v2) << "\n"; 58 | std::cout << "[b] v1 <= v2 = " << operator<=(v1, v2) << "\n\n"; 59 | 60 | std::cout << "[a] v1 > v2 = " << (v1 > v2) << "\n"; 61 | std::cout << "[b] v1 > v2 = " << operator>(v1, v2) << "\n\n"; 62 | 63 | std::cout << "[a] v1 >= v2 = " << (v1 >= v2) << "\n"; 64 | std::cout << "[b] v1 >= v2 = " << operator>=(v1, v2) << "\n\n"; 65 | 66 | std::cout << "\n EXPERIMENT 2 boost::less_than_comparable" << "\n"; 67 | std::cout << "--------------------------------------------------" << "\n"; 68 | disp("v1 + 5.0", v1 + 5.0); 69 | disp("operator+(v1, 5.0)", operator+(v1, 5.0)); 70 | disp("5.0 + v1", 5.0 + v1); 71 | disp("operator+(5.0, v1", operator+(5.0, v1)); 72 | disp("v1", v1); 73 | 74 | return 0; 75 | } 76 | 77 | // ============ Pseudo-file: Vec3D.cpp ================= 78 | 79 | Vec3D::Vec3D(double x, double y, double z) 80 | : m_x(x), m_y(y), m_z(z) 81 | { 82 | } 83 | 84 | double 85 | Vec3D::norm() const 86 | { 87 | return std::sqrt(m_x * m_x + m_y * m_y + m_z * m_z); 88 | } 89 | 90 | std::ostream& 91 | operator<<(std::ostream& os, Vec3D const& vec) 92 | { 93 | return os << "Vec3D{ " 94 | << " x = " << vec.m_x 95 | << " ; y = " << vec.m_y 96 | << " ; z = " << vec.m_z 97 | << " } "; 98 | } 99 | 100 | bool 101 | operator<(Vec3D const& lhs, Vec3D const& rhs) 102 | { 103 | return lhs.norm() < rhs.norm(); 104 | } 105 | 106 | Vec3D& 107 | operator+=(Vec3D& lhs, double rhs) 108 | { 109 | double d = rhs; 110 | lhs = {lhs.m_x + d, lhs.m_y + d, lhs.m_z + d}; 111 | return lhs; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/sample-programs/posix-daemon.cpp: -------------------------------------------------------------------------------- 1 | // File: posix-daemon.cpp 2 | // Brief: Sample Posix Daemon encapsulated in a class with syslog. 3 | // Author: Caio Rodrigues 4 | //------------------------------------------------------------------- 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include // Smart pointer 15 | 16 | #include 17 | #include 18 | #include // string.h 19 | #include 20 | 21 | //------ U*nix only ----// 22 | #include 23 | #include 24 | #include 25 | #include 26 | // Syslog 27 | #include 28 | 29 | 30 | class PosixDaemon{ 31 | public: 32 | using Action = std::function; 33 | 34 | PosixDaemon(std::string path, std::string pidfile, Action action) 35 | : m_path(std::move(path)), 36 | m_pidfile(std::move(pidfile)), 37 | m_action(action) { } 38 | ~PosixDaemon(){} 39 | 40 | // Disable copy constructor in order to forbid copy 41 | PosixDaemon(const PosixDaemon&) = delete; 42 | // Disable copy-assignment operator to make the class non-copiable. 43 | PosixDaemon& operator= (const PosixDaemon&) = delete; 44 | 45 | auto run() -> void { 46 | // Make child process 47 | pid_t child_pid = fork(); 48 | if(child_pid < 0){ 49 | std::cerr << "Error: failed to fork this process." << "\n"; 50 | return; 51 | } 52 | if(child_pid > 0){ 53 | std::cout << "Process ID of child process = " << child_pid << "\n"; 54 | return; 55 | } 56 | // Umask file mode 57 | ::umask(0); 58 | // Set new session 59 | pid_t sid = ::setsid(); 60 | if(sid < 0) 61 | return; 62 | //------ Code of Forked Process ---------// 63 | // Set path of forked process (daemon) 64 | ::chdir(m_path.c_str()); 65 | 66 | // Check whether there is a running process of this program 67 | auto fs = std::ifstream(m_pidfile); 68 | if(fs.good()){ 69 | int pid; 70 | fs >> pid; 71 | std::cerr << " [LOG] Kill process of PID = " << pid << "\n"; 72 | ::kill(-pid, SIGTERM); 73 | fs.close(); 74 | } 75 | auto fo = std::ofstream(m_pidfile); 76 | if(fo.good()){ 77 | int pid = ::getpid(); 78 | std::cerr << "Child PID = " << pid << "\n"; 79 | fo << pid << std::flush; 80 | } else { 81 | std::cerr << " [LOG] Error: could not open PID file " << m_pidfile << "\n"; 82 | return; 83 | } 84 | // Close stdin, stdout and stderr file descriptors. 85 | close(STDIN_FILENO); 86 | close(STDOUT_FILENO); 87 | close(STDERR_FILENO); 88 | while(m_action()); 89 | } 90 | private: 91 | std::string m_path; 92 | std::string m_pidfile; 93 | Action m_action; 94 | // Action m_onExit; 95 | }; 96 | 97 | int main(int argc, char** argv){ 98 | 99 | std::random_device rdng; 100 | auto randomGen = std::bind( 101 | std::uniform_real_distribution(10.0, 60.0), 102 | std::default_random_engine(rdng()) 103 | ); 104 | 105 | setlogmask (LOG_UPTO (LOG_INFO)); 106 | openlog ("price-service", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); 107 | 108 | PosixDaemon daemon{ 109 | "/", 110 | "/tmp/price-server.pid", 111 | [&randomGen](){ 112 | // Action executed in the child process (daemon) 113 | std::stringstream ss; 114 | ss << std::setprecision(3) << std::fixed; 115 | ss << "Price = " << randomGen() << " path = " << getcwd(nullptr, 0) ; 116 | syslog (LOG_INFO, "%s", ss.str().c_str()); 117 | // 1 seconds delay 118 | std::this_thread::sleep_for(std::chrono::seconds(1)); 119 | return true; 120 | } 121 | }; 122 | 123 | daemon.run(); 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/libc.fsx: -------------------------------------------------------------------------------- 1 | /// 2 | /// Linux LibC FFI wrappers examples. 3 | /// 4 | /// 5 | open System 6 | open System.Runtime.InteropServices 7 | 8 | 9 | /// Linux LibC FFI 10 | /// 11 | 12 | 13 | // int puts(const char *s); 14 | [] 15 | extern void puts(string) 16 | 17 | // int gethostname(char *name, size_t len); 18 | [] 19 | extern int private c_getHostname(System.Text.StringBuilder, int len) 20 | 21 | // double cbrt(double x); 22 | [] 23 | extern double cbrt(double) 24 | 25 | /// #include 26 | /// 27 | /// On success, these functions return the length of a right-angled 28 | /// triangle with sides of length x and y 29 | /// 30 | /// double hypot(double x, double y); 31 | [] 32 | extern double hypot(double, double) 33 | 34 | 35 | (** 36 | Header: time.h 37 | 38 | struct tm { 39 | int tm_sec; /* Seconds (0-60) */ 40 | int tm_min; /* Minutes (0-59) */ 41 | int tm_hour; /* Hours (0-23) */ 42 | int tm_mday; /* Day of the month (1-31) */ 43 | int tm_mon; /* Month (0-11) */ 44 | int tm_year; /* Year - 1900 */ 45 | int tm_wday; /* Day of the week (0-6, Sunday = 0) */ 46 | int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ 47 | int tm_isdst; /* Daylight saving time */ 48 | }; 49 | 50 | 51 | *) 52 | [] 53 | [] 54 | type UnixTm = 55 | struct 56 | val tm_sec: int; 57 | val tm_min: int; 58 | val tm_hour: int; 59 | val tm_mday: int; 60 | val tm_mon: int; 61 | val tm_year: int; 62 | val tm_wday: int; 63 | val tm_yday: int; 64 | val tm_isdst: int 65 | val tm_gmtoff: int; 66 | 67 | [] 68 | val tm_zone: string; 69 | //val tm_zone: IntPtr; 70 | end 71 | 72 | 73 | /// Returns an Unix timestamp 74 | /// 75 | /// Note: time_t is an 32 bits integer on 32 bits machines 76 | /// and 64 bits on a 64-bits machine or OS. 77 | // 78 | /// time_t time(time_t *t) 79 | /// time_t time(NULL) 80 | /// 81 | /// 82 | [] 83 | extern System.Int64 ctime() 84 | 85 | // Note: When the *timep pointer is null. It returns 86 | // the current time. 87 | // 88 | // struct tm *localtime(const time_t *timep); 89 | // 90 | [] 91 | extern UnixTm c_localtime(System.Int64&) 92 | 93 | [] 94 | extern IntPtr c_localtime2(System.Int64&) 95 | 96 | 97 | let localtime time = 98 | let mutable tref = time 99 | c_localtime(&tref) 100 | 101 | let localtime2(): UnixTm = 102 | let mutable tref = 0L 103 | let ptr = c_localtime2(&tref) 104 | Marshal.PtrToStructure(ptr) 105 | 106 | let getHostName () = 107 | let sb = new System.Text.StringBuilder(64) 108 | ignore <| c_getHostname(sb, 64) 109 | sb.ToString() 110 | 111 | let testLibc() = 112 | puts "\n\nHello world!! It works!!" 113 | printfn "getHostName() = %s" <| getHostName() 114 | printfn "Array.map Libc.cbrt [| 1.0 ; 8.0; 27.0; 64 |] = %A" <| Array.map cbrt [| 1.0 ; 8.0; 27.0; 64.0|] 115 | 116 | 117 | let showTm(tm: UnixTm) = 118 | printfn "tm.tm_year = %d" tm.tm_year 119 | printfn "tm.tm_day = %d" tm.tm_mday 120 | 121 | let testTime() = 122 | let size = Marshal.SizeOf(typeof) 123 | printfn "sizeof(struct tm) = %d" size 124 | showTm <| localtime 1496843850L 125 | 126 | testTime() 127 | 128 | -------------------------------------------------------------------------------- /src/design-patterns/type-erasure1.cpp: -------------------------------------------------------------------------------- 1 | // File: type-erasure.cpp 2 | // Brief: Basic type erasure implementation example. 3 | // Objective: Demonstrate how type erasure works. 4 | // Author: Caio Rodrigues 5 | //------------------------------------------------------- 6 | #include 7 | #include 8 | #include 9 | #include // Smart pointers 10 | 11 | class TypeErasure{ 12 | private: 13 | // --- Forward declarations ---- 14 | class Concept; 15 | template class Model; 16 | 17 | // --- Member Variables ----- // 18 | std::shared_ptr _concept_ptr; 19 | // Optional: 20 | // RTTI (runtime type information) for recovering wrapped type 21 | // by downcasting 22 | const std::type_info& _tinfo; 23 | public: 24 | template 25 | TypeErasure(const T& obj) 26 | : _concept_ptr(std::make_shared>(obj)) 27 | ,_tinfo(typeid(T)) 28 | { 29 | } 30 | 31 | auto getName() const -> std::string { 32 | return _concept_ptr->getName(); 33 | } 34 | 35 | // Recover reference to wrapped type 36 | template 37 | auto recover() -> T { 38 | if(typeid(T) != _tinfo) 39 | throw std::runtime_error("Error: cannot cast to this type"); 40 | // Note: static_cast downcasting to wrong type has undefined behavior, 41 | // use with care! 42 | return static_cast*>(_concept_ptr.get())->_obj; 43 | } 44 | 45 | template 46 | auto hasType() -> bool { 47 | return _tinfo == typeid(T); 48 | } 49 | private: 50 | // Concept class defines the interface to be enforced 51 | // In general, it is an interface class, a class with only pure virtual 52 | // methods (abstract methods), in other words methods without implementation. 53 | class Concept{ 54 | public: 55 | virtual auto getName() const -> std::string = 0; 56 | virtual ~Concept() = default; 57 | }; 58 | 59 | // Adapt the wrapped type (T) to the concept 60 | template 61 | class Model: public Concept { 62 | public: 63 | // Instance of the wrapped type 64 | T _obj; 65 | // Initialize _opj by copying the parameter 66 | Model(const T& obj): _obj(obj){} 67 | auto getName() const -> std::string { 68 | return _obj.getName(); 69 | } 70 | }; 71 | }; 72 | 73 | 74 | class A{ 75 | public: 76 | std::string getName() const { 77 | return "class A"; 78 | } 79 | void sayA(){ 80 | std::cout << "I am the class A" << "\n"; 81 | } 82 | }; 83 | 84 | class B{ 85 | public: 86 | std::string getName() const { 87 | return "class B"; 88 | } 89 | void sayB(){ 90 | std::cout << "I am the class B" << "\n"; 91 | } 92 | }; 93 | 94 | class C{ 95 | public: 96 | std::string getName() const { 97 | return "class C"; 98 | } 99 | void sayC() const { 100 | std::cout << "I am the class C" << "\n"; 101 | } 102 | }; 103 | 104 | int main(){ 105 | auto tlist = std::deque(); 106 | tlist.emplace_back(A()); 107 | tlist.emplace_back(B()); 108 | tlist.emplace_back(C()); 109 | 110 | std::cout << "\n" << "EXPERIMENT 1 ============" << "\n"; 111 | for(const auto& t: tlist) { 112 | std::cout << "Class type = " << t.getName() << "\n"; 113 | } 114 | 115 | // Note: It is a copy! 116 | A objA = tlist.at(0).recover(); 117 | objA.sayA(); 118 | 119 | std::cout << "\n" << "EXPERIMENT 2 ============" << "\n"; 120 | 121 | // Simulate downcasting failure 122 | try { 123 | B objB = tlist.at(0).recover(); 124 | objB.sayB(); 125 | } catch(const std::runtime_error& ex){ 126 | std::cout << " [FAILURE]" << ex.what() << "\n"; 127 | } 128 | 129 | B objB = tlist.at(1).recover(); 130 | objB.sayB(); 131 | 132 | auto objC = tlist.at(2).recover(); 133 | objC.sayC(); 134 | 135 | return EXIT_SUCCESS; 136 | } 137 | -------------------------------------------------------------------------------- /haskell-ffi1/README.org: -------------------------------------------------------------------------------- 1 | * Haskell Foreign Function Interface 2 | ** Example - Interface Linux/ C-library 3 | 4 | Description: It provides complete working examples about Haskell FFI 5 | interfacing Linux GlibC (Linux C-Library). 6 | 7 | 8 | - File: [[file:libcScript.hs][file:libcScript.hs ]] 9 | 10 | 11 | Running: 12 | 13 | #+BEGIN_SRC sh 14 | $ stack ghci 15 | Configuring GHCi with the following packages: 16 | GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help 17 | Wellcome to Haskell 18 | it :: () 19 | Loaded GHCi configuration from /home/archbox/.ghci 20 | Loaded GHCi configuration from /tmp/ghci32017/ghci-script 21 | > 22 | > :script libcScript.hs 23 | cbrt :: Double -> Double 24 | hypot :: Double -> Double -> Double 25 | cputs :: CString -> IO () 26 | puts :: String -> IO () 27 | getpid :: IO Int 28 | csystem :: CString -> IO Int 29 | system :: String -> IO Int 30 | c_gethostname :: Ptr CChar -> Int -> IO Int 31 | gethostname :: IO String 32 | testLibc :: IO () 33 | 34 | 35 | 36 | LibC FFI Tests 37 | --------------------- 38 | Hello world São Paulo city 39 | Hostname = ghostpc 40 | Linux ghostpc 4.9.27-1-MANJARO #1 SMP PREEMPT Mon May 8 08:48:50 UTC 2017 x86_64 GNU/Linux 41 | sh: wrong: command not found 42 | cbrt 27.0 = 3.0000000000000004 43 | hypot 80.0 60.0 = 100.0 44 | it :: () 45 | > 46 | 47 | #+END_SRC 48 | ** Bookmarks 49 | *** Haskell FFI - Documentation 50 | 51 | Haskell Documentation: 52 | 53 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign.html][Foreign]] - A collection of data types, classes, and functions for 54 | interfacing with another programming language. 55 | 56 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-C.html][Foreign.C]] - Bundles the C specific FFI library functionality 57 | 58 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-C-Error.html][Foreign.C.Error]] 59 | 60 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-C-String.html][Foreign.C.String]] - Utilities for primitive marshalling of C strings. 61 | 62 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-C-Types.html][Foreign.C.Types]] - Mapping of C types to corresponding Haskell types. 63 | 64 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-Marshal.html][Foreign.Marshal]] - Marshalling support 65 | 66 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-Marshal-Alloc.html][Foreign.Marshal.Alloc]] - The module Foreign.Marshal.Alloc provides 67 | operations to allocate and deallocate blocks of raw memory. 68 | 69 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-Marshal-Array.html][Foreign.Marshal.Array]] - Marshalling support: routines allocating, 70 | storing, and retrieving Haskell lists that are represented as 71 | arrays in the foreign language. 72 | 73 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/Foreign-Marshal-Utils.html][Foreign.Marshal.Utils]] 74 | 75 | - [[https://hackage.haskell.org/package/base-4.9.1.0/docs/System-IO-Unsafe.html][System.IO.Unsafe]] 76 | 77 | *** Haskell Wiki 78 | 79 | - [[https://wiki.haskell.org/Category:FFI][Category:FFI - HaskellWiki]] 80 | 81 | - [[https://wiki.haskell.org/Cxx_foreign_function_interface][Cxx foreign function interface - HaskellWiki]] 82 | 83 | - [[https://wiki.haskell.org/FFI_complete_examples][FFI complete examples - HaskellWiki]] 84 | 85 | - [[https://wiki.haskell.org/CPlusPlus_from_Haskell][CPlusPlus from Haskell - HaskellWiki]] 86 | 87 | - [[https://wiki.haskell.org/FFI_cook_book][FFI cook book - HaskellWiki]] 88 | 89 | *** Tutorials 90 | 91 | - [[http://book.realworldhaskell.org/read/interfacing-with-c-the-ffi.html][Chapter 17. Interfacing with C: the FFI]] 92 | 93 | - [[https://en.wikibooks.org/wiki/Haskell/FFI][Haskell/FFI - Wikibooks, open books for an open world]] 94 | 95 | - 96 | 97 | - 98 | -------------------------------------------------------------------------------- /src/dlls/example-windows1/client1.cpp: -------------------------------------------------------------------------------- 1 | // File: client.cpp 2 | // Brief: Sample C++ client code for DLL testlib.dll 3 | // Author: Caio Rodrigues 4 | //--------------------------------------------------------------- 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "testlib.hpp" 12 | 13 | 14 | #define WindbgTrace(text) \ 15 | { std::stringstream ss; \ 16 | ss << __FILE__ << ":" << __LINE__ << ": <" << __FUNCTION__ "> " \ 17 | << text << std::endl;\ 18 | OutputDebugString(ss.str().c_str()); \ 19 | } 20 | 21 | #define DbgTrace(text) \ 22 | { std::cerr << __FILE__ << ":" << __LINE__ << ": <" << __FUNCTION__ << "> " \ 23 | << text << std::endl; } 24 | 25 | #define DbgDisp(expr) \ 26 | { std::cerr << __FILE__ << ":" << __LINE__ << ": <" << __FUNCTION__ << "> " \ 27 | << #expr << " = " << (expr) << std::endl; } 28 | 29 | extern "C" hVectorD testlib_vectorD_make0(size_t n, double); 30 | extern "C" hVectorD testlib_vectorD_make1(size_t n, double array []); 31 | extern "C" void testlib_vectorD_delete(hVectorD hv); 32 | 33 | int main(){ 34 | 35 | #ifndef DISABLE 36 | std::cout << "\n=== EXPERIMENT 1 ===> Import C++ functions from DLL" << std::endl; 37 | 38 | DbgTrace("Main process starts here."); 39 | std::vector xs{1.0, 2.0, 3.0, 4.0, 5.0}; 40 | std::cout << " => Linalg::norm(xs) " << Linalg::norm(xs) << std::endl; 41 | std::cout << "=> xs = "; Linalg::printVector(std::cout, xs); std::cout << std::endl; 42 | 43 | std::cout << "=== EXPERIMENT 2 ===> Import class from DLL" << std::endl; 44 | auto cls = SampleClass("Dummy"); 45 | cls.set(100); 46 | std::cout << "cls.getName() = " << cls.getName() << std::endl; 47 | std::cout << " cls.get() = " << cls.get() << std::endl; 48 | #endif // -- eof DISABLE flag 49 | 50 | //=========>> Load functions and classes using C-interface ==============// 51 | 52 | std::cout << "\n== EPERIMENT 3 ===> Import C-functions from DLL - C-interface" << std::endl; 53 | 54 | double arr [] = {1, 2, 3, 4, 5}; 55 | hVectorD v1 = testlib_vectorD_make1(5, arr); 56 | testlib_vectorD_Linalg_printVector("v1", v1); 57 | std::cout << "norm(v1) = " << testlib_vectorD_Linalg_norm(v1) << std::endl; 58 | 59 | testlib_vectorD_delete(v1); 60 | 61 | std::cout << "\n== EPERIMENT 4 ===> Non-polymorphic class with C-interface " << std::endl; 62 | 63 | hSampleClass hcls = testlib_SampleClass_make1("[EXPERIMENT4]ClassHandle-OOP-C-API"); 64 | std::cout << "[EXPERIMENT 4] hcls.getName() = " << testlib_SampleClass_getName(hcls) << std::endl; 65 | testlib_SampleClass_set(hcls, 100); 66 | std::cout << "[EXPERIMENT 4] hcls.get() = " << testlib_SampleClass_get(hcls) << std::endl; 67 | testlib_SampleClass_set(hcls, 200); 68 | std::cout << "[EXPERIMENT 4] hcls.get() = " << testlib_SampleClass_get(hcls) << std::endl; 69 | 70 | testlib_SampleClass_delete(hcls); 71 | 72 | 73 | std::cout << "\n== EPERIMENT 5 ===> Load polymorphic classes from DLL " << std::endl; 74 | 75 | InterfaceClass* hinstA = teslib_InterfaceClass_factory("ImplementationA"); 76 | InterfaceClass* hinstB = teslib_InterfaceClass_factory("ImplementationB"); 77 | 78 | std::cout << " => hinstA->getID() = " << hinstA->getID() << std::endl; 79 | std::cout << " => hinstA->getID() = " << hinstB->getID() << std::endl; 80 | hinstA->setName("ClassA-implA"); 81 | hinstB->setName("ClassB-implB"); 82 | std::cout << " => hinstA->getName() = " << hinstA->getID() << std::endl; 83 | std::cout << " => hinstB->getName() = " << hinstB->getID() << std::endl; 84 | 85 | // Note: If delete is used directly to delete hinstA and hinstB, 86 | // a segmentatin fault will happen whenc compiling with Mingw/GCC 87 | testlib_InterfaceClass_delete(hinstA); 88 | testlib_InterfaceClass_delete(hinstB); 89 | 90 | std::cout << " [INFO] After deleting instances" << std::endl; 91 | 92 | DbgTrace("Program ended OK."); 93 | return 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/windows/gui-without-winmain.cpp: -------------------------------------------------------------------------------- 1 | // File: gui-without-winmain.cpp 2 | // Brief: Minimal Windows GUI Program for Win32 API without WinMain. 3 | // Author: Caio Rodrigues 4 | //-------------------------------------------------------------------------------------- 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | LRESULT windowProcedure( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 12 | 13 | int main(int argc, char** argv){ 14 | //---- Get WinMain Parameters ----// 15 | 16 | HINSTANCE hInstance = GetModuleHandle(NULL); 17 | STARTUPINFO si; 18 | GetStartupInfo(&si); 19 | int nCmdShow = si.wShowWindow; 20 | 21 | // -------------------------// 22 | OutputDebugString("Starting WinMain Application"); 23 | std::puts("Starting WinMain Application"); 24 | 25 | //Window class name must be unique 26 | const char wincClassName [] = "NameOfWindow"; 27 | 28 | // Win32 Window class structure 29 | WNDCLASSEX wc; 30 | // Win32 message structure 31 | MSG Msg; 32 | 33 | wc.lpszClassName = wincClassName; 34 | wc.lpfnWndProc = windowProcedure; 35 | wc.cbSize = sizeof(WNDCLASSEX); 36 | wc.style = 0; 37 | wc.cbClsExtra = 0; 38 | wc.cbWndExtra = 0; 39 | wc.hInstance = hInstance; 40 | wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 41 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); 42 | wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // (HBRUSH) CreateSolidBrush(RGB(10, 20, 30)); // 43 | wc.lpszMenuName = NULL; 44 | wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 45 | 46 | if(!RegisterClassEx(&wc)) { 47 | MessageBox(NULL, 48 | "Window Registration Failed!", 49 | "Error!", 50 | MB_ICONEXCLAMATION | MB_OK); 51 | //Error status code 52 | return -1; 53 | } 54 | 55 | std::cout << "Class Registered" << std::endl; 56 | int width = 500, height = 400; 57 | int pos_left = 400, pos_top = 100; 58 | 59 | HWND hwnd = CreateWindowA( 60 | wc.lpszClassName, 61 | "Title of Window", 62 | WS_OVERLAPPEDWINDOW, 63 | pos_left, 64 | pos_top, 65 | width, 66 | height, 67 | nullptr, 68 | nullptr, 69 | hInstance, 70 | nullptr 71 | ); 72 | 73 | constexpr size_t buttonID = 1001; 74 | 75 | OutputDebugString(" [INFO] Window created OK"); 76 | if(hwnd == NULL){ 77 | MessageBox(NULL, 78 | "Error: Failure to create Window", 79 | "Error Report", 80 | MB_ICONEXCLAMATION | MB_OK); 81 | return -1; 82 | } 83 | ShowWindow(hwnd, nCmdShow); 84 | UpdateWindow(hwnd); 85 | 86 | //---- Message Loop ----------// 87 | while(GetMessage(&Msg, NULL, 0, 0) > 0 ){ 88 | TranslateMessage(&Msg); 89 | DispatchMessage(&Msg); 90 | } 91 | // Success status code 92 | return 0; 93 | } 94 | // ------------ End of Main ------------------------- // 95 | 96 | 97 | // Window Procedure - Process window messages or events 98 | LRESULT windowProcedure ( 99 | HWND hwnd // Window Handle (Window object) 100 | ,UINT msg // Window Message 101 | ,WPARAM wParam // Additional message information 102 | ,LPARAM lParam // Additional message information 103 | ){ 104 | 105 | // Process messages 106 | switch(msg) 107 | { 108 | case WM_CREATE: 109 | break; 110 | case WM_CLOSE: 111 | DestroyWindow(hwnd); 112 | break; 113 | case WM_DESTROY: 114 | PostQuitMessage(0); 115 | break; 116 | case WM_MOVE: 117 | break; 118 | case WM_PAINT: 119 | { 120 | // GDI - Graphics Devices Interface Here 121 | //-------------------------------------------- 122 | PAINTSTRUCT ps; 123 | HDC hdc; 124 | // std::cerr << " [INFO] Windown painting" << std::endl; 125 | hdc = BeginPaint(hwnd, &ps); 126 | std::string text = "Hello world Window!"; 127 | TextOutA(hdc, 125, 200, text.c_str(), text.size()); 128 | Ellipse(hdc, 100, 100, 160, 160); 129 | Rectangle(hdc, 100, 100, 160, 160); 130 | EndPaint(hwnd, &ps); 131 | } 132 | break; 133 | default: 134 | return DefWindowProc(hwnd, msg, wParam, lParam); 135 | } 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /src/windows/dynamic-loading1.cpp: -------------------------------------------------------------------------------- 1 | // File: dynamic-loading1.cpp 2 | // Brief: Dynamically loads a DLL - shared library at runtime. 3 | // Note: Demonstration of WINAPIs LoadLibrary, FreeLibrary, GetProcAddress 4 | // Author: Caio Rodrigues 5 | //--------------------------------------------------------------------------- 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | int main(){ 12 | 13 | /** Reference: https://msdn.microsoft.com/en-us/ie/ms775123(v=vs.94) 14 | Function Signature: 15 | 16 | HRESULT URLDownloadToFile( 17 | LPUNKNOWN pCaller, 18 | LPCTSTR szURL, 19 | LPCTSTR szFileName, 20 | _Reserved_ DWORD dwReserved, 21 | LPBINDSTATUSCALLBACK lpfnCB 22 | ); 23 | 24 | ---------------------------------------------- */ 25 | 26 | // Wide-unicode strings 27 | std::wstring fileURL = L"http://httpbin.org/image/jpeg"; 28 | std::wstring file1 = L"download-file1.jpeg"; 29 | std::wstring file2 = L"download-file2.jpeg"; 30 | 31 | // Wide unicode version for LoadLibrary API 32 | HMODULE hLib = ::LoadLibraryW(L"urlmon.dll"); 33 | if(hLib == nullptr){ 34 | std::cerr << " [ERROR] Error: failed to load shared library" << std::endl; 35 | // Early return on Error. 36 | return EXIT_FAILURE; 37 | } 38 | std::cerr << " [INFO] DLL Loaded OK" << std::endl; 39 | 40 | std::cout << "============ EXPERIMENT 1 ===================" << std::endl; 41 | 42 | // The function pointer must have the same 43 | // signature of the function to be dynamically loaded 44 | // 45 | // Note: Windows function pointer should include calling convention 46 | // If omitted, the default calling convention is __cdcel 47 | // Possible Calling Conventions: __cdcel, __stdcall, __fastcall and so on. 48 | //--------------------------- 49 | 50 | // C+11 type alias for function pointer 51 | using FunptrType = 52 | HRESULT (__cdecl *)(LPUNKNOWN, LPCWSTR, LPCWSTR, DWORD, LPBINDSTATUSCALLBACK); 53 | 54 | 55 | // Alternative 2 for type alias (C++98/03) 56 | typedef HRESULT (__cdecl * FunptrTypeTypedef)(LPUNKNOWN, LPCWSTR, LPCWSTR, DWORD, LPBINDSTATUSCALLBACK); 57 | 58 | 59 | FARPROC hFunc = ::GetProcAddress(hLib, "URLDownloadToFileW"); 60 | if(hFunc == nullptr){ 61 | std::cerr << " [Error] Failed to load function from DLL" << std::endl; 62 | return EXIT_FAILURE; 63 | } 64 | std::cerr << " [INFO] Function loaded OK" << std::endl; 65 | 66 | // Functin Pointer 67 | FunptrType URLDownloadToFileFunPTR = reinterpret_cast(hFunc); 68 | 69 | HRESULT result1 = URLDownloadToFileFunPTR(nullptr, fileURL.c_str(), file1.c_str(), 0, nullptr); 70 | if(SUCCEEDED(result1)) 71 | std::cerr << " [INFO] Download successful OK. " << std::endl; 72 | else 73 | std::cerr << " [ERROR] Download failure. " << std::endl; 74 | 75 | 76 | std::cout << "============ EXPERIMENT 2 ===================" << std::endl; 77 | // Same cast as reinterpret_cast 78 | void* hFunc2 = (void*) ::GetProcAddress(hLib, "URLDownloadToFileW"); 79 | // Omit error checking if(hFunct2 == nullptr){ ... } 80 | 81 | // Note: Calling convention __cdecl can be omitted 82 | using URLDownloadToFileW_t = 83 | auto __cdecl (LPUNKNOWN, LPCWSTR, LPCWSTR, DWORD, LPBINDSTATUSCALLBACK) -> HRESULT; 84 | // auto (LPUNKNOWN, LPCWSTR, LPCWSTR, DWORD, LPBINDSTATUSCALLBACK) -> HRESULT; 85 | 86 | auto DownloadFile = reinterpret_cast(hFunc2); 87 | 88 | HRESULT hresult2 = DownloadFile(nullptr, fileURL.c_str(), file2.c_str(), 0, nullptr); 89 | if(SUCCEEDED(result1)) 90 | std::cerr << " [INFO] Download successful OK. " << std::endl; 91 | else 92 | std::cerr << " [ERROR] Download failure. " << std::endl; 93 | 94 | // WARNING: Code NOT Safe - prone to resource leaking 95 | // in case of exception or forget to call this function. 96 | ::FreeLibrary(hLib); 97 | std::cerr << " [INFO] Application ended gracefully. OK." << std::endl; 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /src/design-patterns/visitor2.cpp: -------------------------------------------------------------------------------- 1 | // Brief: Generic visitor pattern implemented with template metaprogramming. 2 | // Author: Caio Rodrigues 3 | //------------------------------------------------------------------ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // Shape interface - The base class must define the method accept 12 | class IShape{ 13 | public: 14 | virtual ~IShape() = default; 15 | }; 16 | 17 | // ============ Concrete shapes ======= // 18 | 19 | // Generic Visitor with CRTP (Curious Recurring Template) 20 | // REMINDER: Template classes must always be 21 | // in header files (*.h or *.hpp) 22 | template 23 | class VisitableShape: public IShape{ 24 | public: 25 | /** Accept any visitor class which implements 26 | * the method: 27 | * void Visitor::visit(Implementation& impl); 28 | *********************************************/ 29 | template 30 | void accept(Visitor&& v) { 31 | v.visit(static_cast(*this)); 32 | } 33 | }; 34 | 35 | 36 | class Circle: public VisitableShape { 37 | public: 38 | double radius; 39 | Circle(double radius): radius(radius) { } 40 | }; 41 | 42 | class Square: public VisitableShape { 43 | public: 44 | double side; 45 | Square(double side): side(side) { } 46 | }; 47 | 48 | class Blob: public VisitableShape { 49 | public: 50 | Blob(){} 51 | }; 52 | 53 | // ======== Generic Visitor =============// 54 | 55 | // Note: This idea can be generalized even further by using variable 56 | // templates and recursion. 57 | template 58 | class FunctionAdapter{ 59 | // Lambda function are used for adding new behavior to the object. 60 | template using Func = std::function; 61 | Result _res; 62 | Func _fn_circle; 63 | Func _fn_square; 64 | Func _fn_blob; 65 | public: 66 | Result get(){ return _res; } 67 | FunctionAdapter(Func fnCircle, Func fnSquare, Func fnBlob) 68 | : _res{} 69 | , _fn_circle{fnCircle} 70 | , _fn_square{fnSquare} 71 | , _fn_blob{fnBlob} 72 | { 73 | } 74 | void visit(Circle& sh) { _res = _fn_circle(sh); } 75 | void visit(Square& sh) { _res = _fn_square(sh);} 76 | void visit(Blob& sh) { _res = _fn_blob(sh); } 77 | 78 | template 79 | Result operator()(Visitable& visitable){ 80 | this->visit(visitable); 81 | return this->get(); 82 | } 83 | }; 84 | 85 | auto visitorGetName = FunctionAdapter{ 86 | [](Circle& ){ return "circle"; }, 87 | [](Square& ){ return "square"; }, 88 | [](Blob& ){ return "blob"; }, 89 | }; 90 | 91 | // Creates operation to compute shape perimeter 92 | auto visitorGetArea = FunctionAdapter{ 93 | [](Circle& s){ return 2 * 3.1415 * s.radius * s.radius ; }, 94 | [](Square& s){ return 4.0 * s.side; }, 95 | [](Blob& ){ return -100.0; }, 96 | }; 97 | 98 | int main() 99 | { 100 | // Sample shapes 101 | auto s1 = Circle(3.0); 102 | auto s2 = Square(4.0); 103 | auto s3 = Blob(); 104 | 105 | #if 1 106 | std::cout << "===> Experiment 1: FunctionAdapter " << "\n"; 107 | // Creates operation to get shape name as string 108 | 109 | s1.accept(visitorGetName); 110 | std::cout << "Type of shape 1 = " << visitorGetName.get() << "\n"; 111 | std::cout << "Type of shape 2 = " << visitorGetName(s2) << "\n"; 112 | std::cout << "Type of shape 3 = " << visitorGetName(s3) << "\n"; 113 | 114 | std::cout << "===> Experiment 2: FunctionAdapter " << "\n"; 115 | 116 | s1.accept(visitorGetArea); 117 | std::cout << "Perimeter of shape 1 = " << visitorGetArea.get() << "\n"; 118 | s2.accept(visitorGetArea); 119 | std::cout << "Perimeter of shape 2 = " << visitorGetArea.get() << "\n"; 120 | std::cout << "Perimeter of shape 2 = " << visitorGetArea(s2) << "\n"; 121 | s3.accept(visitorGetArea); 122 | std::cout << "Perimeter of shape 3 = " << visitorGetArea.get() << "\n"; 123 | #endif 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /src/design-patterns/strategy-pattern1.cpp: -------------------------------------------------------------------------------- 1 | // File: strategy-pattern1.cpp 2 | // Brief: Modern C++ example of GOF's strategy design pattern. 3 | // Author: Caio Rodrigues 4 | //-------------------------------------------------------------- 5 | #include 6 | #include 7 | #include 8 | 9 | // Strategy interface 10 | struct IStrategy{ 11 | virtual ~IStrategy(){} 12 | // Essential: Algorithm encapsulated by strategy object 13 | virtual auto compute(double x, double y) const -> double = 0; 14 | // Optional: Provides strategy metadata 15 | virtual auto name() const -> const std::string = 0; 16 | // Clone this object (Note: This is a virtual constructor) 17 | virtual auto clone() const -> IStrategy* = 0; 18 | }; 19 | 20 | class Context{ 21 | private: 22 | std::unique_ptr _strategy; 23 | public: 24 | Context() 25 | : _strategy{nullptr} { } 26 | Context(IStrategy* s) 27 | : _strategy{s} { } 28 | Context(const IStrategy& s) 29 | : _strategy{s.clone()} { } 30 | auto setStrategy(IStrategy* s){ 31 | _strategy.reset(s); 32 | } 33 | auto setStrategy(const IStrategy& s){ 34 | _strategy.reset(s.clone()); 35 | } 36 | auto compute(double x, double y) -> void { 37 | if(_strategy == nullptr) 38 | std::runtime_error("Error: strategy not set"); 39 | double result = _strategy->compute(x, y); 40 | std::cout << " strategy = " << _strategy->name() << " " 41 | << "( x = " << x << " ; " 42 | << "y = " << y << " )" 43 | << "\n" ; 44 | std::cout << "Result = " << result << "\n"; 45 | } 46 | }; 47 | 48 | 49 | class AddStrategy: public IStrategy { 50 | public: 51 | auto name() const -> const std::string{ 52 | return "add"; 53 | } 54 | auto compute(double x, double y) const -> double { 55 | return x + y; 56 | } 57 | 58 | auto clone() const -> IStrategy* { 59 | std::cerr << " [TRACE] AddStrategy => I was cloned" << "\n"; 60 | return new AddStrategy(*this); 61 | } 62 | }; 63 | 64 | #if 1 65 | struct MulStrategy: public IStrategy { 66 | public: 67 | auto name() const -> const std::string{ 68 | return "mul"; 69 | } 70 | double compute(double x, double y) const { 71 | return x + y; 72 | } 73 | auto clone() const -> IStrategy* { 74 | std::cerr << " [TRACE] MulStrategy => I was cloned" << "\n"; 75 | return new MulStrategy(*this); 76 | } 77 | }; 78 | 79 | struct LinearCombStrategy: public IStrategy { 80 | double a, b, c; 81 | LinearCombStrategy(double a, double b, double c) 82 | : a(a), b(b), c(c) 83 | { 84 | } 85 | auto name() const -> const std::string{ 86 | return "Linear combination a * x + b * y + c"; 87 | } 88 | auto compute(double x, double y) const -> double{ 89 | return a * x + b * y + c; 90 | } 91 | auto clone() const -> IStrategy* { 92 | std::cerr << " [TRACE] LinearCombStrategy => I was cloned" << "\n"; 93 | return new LinearCombStrategy(*this); 94 | } 95 | }; 96 | #endif 97 | 98 | 99 | int main(){ 100 | Context ctx; 101 | std::cout << "==== Strategy = add ====" << "\n"; 102 | ctx.setStrategy(new AddStrategy); 103 | ctx.compute(3.0, 4.0); 104 | 105 | std::cout << "==== Strategy = mul ====" << "\n"; 106 | ctx.setStrategy(new MulStrategy); 107 | ctx.compute(3.0, 4.0); 108 | 109 | std::cout << "==== Strategy = Linear combination ====" << "\n"; 110 | ctx.setStrategy(new LinearCombStrategy(5, 3, 4)); 111 | ctx.compute(3.0, 4.0); 112 | 113 | std::cout << "==== Strategy = Linear combination [2] ====" << "\n"; 114 | auto comb1 = LinearCombStrategy(6.0, 5.0, 10.0); 115 | // Copy stack-allocated object comb1 using the virtual constructor 116 | ctx.setStrategy(comb1); 117 | ctx.compute(5.0, 3.0); 118 | 119 | std::cout << "==== Strategy = Linear combination [2] ====" << "\n"; 120 | // Copy stack-allocated temporary object comb1 using the virtual constructor 121 | // clone 122 | ctx.setStrategy(LinearCombStrategy{6.0, 5.0, 10.0}); 123 | ctx.compute(2.0, 6.0); 124 | 125 | return 0; 126 | }; 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /src/boost/boost-pointer-container.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Demonstration and testing of boost pointer container. 3 | //--------------------------------------------------------------------- 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class Base{ 12 | public: 13 | static auto nextID() -> int { 14 | static int i = 0; 15 | return ++i; 16 | } 17 | 18 | Base() = default; 19 | // Destructor of base class must always be virtual 20 | virtual ~Base() = default; 21 | 22 | virtual auto getID() const -> int = 0; 23 | 24 | virtual auto getType() const -> std::string = 0; 25 | 26 | }; 27 | 28 | 29 | class DerivedA: public Base{ 30 | public: 31 | const int m_id; 32 | 33 | DerivedA(): m_id(Base::nextID()) { } 34 | auto getType() const -> std::string { 35 | return "DerivedA"; 36 | } 37 | auto getID() const -> int { 38 | return m_id; 39 | } 40 | ~DerivedA(){ 41 | std::cout << " [INFO] Class DerivedA deleted. => Object ID = " 42 | << m_id << "\n"; 43 | } 44 | }; 45 | 46 | 47 | class DerivedB: public Base{ 48 | const int m_id; 49 | public: 50 | DerivedB(): m_id(Base::nextID()) { } 51 | auto getType() const -> std::string { 52 | return "DerivedB"; 53 | } 54 | auto getID() const -> int { 55 | return m_id; 56 | } 57 | ~DerivedB(){ 58 | std::cout << " [INFO] Class DerivedB deleted. => ObjectID = " 59 | << m_id << "\n"; 60 | } 61 | }; 62 | 63 | 64 | void showType(Base const& obj) 65 | { 66 | std::cout << "Object ID = " << obj.getID() 67 | << " Class type = " << obj.getType() 68 | << "\n"; 69 | } 70 | 71 | int main(){ 72 | 73 | std::cout << "\n === EXPERIMENT 0 ==============================" << "\n"; 74 | std::vector xsa; 75 | xsa.push_back(DerivedA()); 76 | xsa.push_back(DerivedA()); 77 | xsa.emplace_back(); 78 | 79 | std::cout << "Run std::for_each" << "\n"; 80 | std::for_each(xsa.begin(), xsa.end(), showType); 81 | 82 | std::cout << "\n === EXPERIMENT 1 ==============================" << "\n"; 83 | 84 | std::vector> xs; 85 | xs.push_back(std::make_shared()); 86 | xs.push_back(std::make_shared()); 87 | xs.push_back(std::make_shared()); 88 | xs.push_back(std::make_shared()); 89 | 90 | std::cout << " <> xs[0] type " << xs[0]->getType() 91 | << " ; id = " << xs[0]->getID() << "\n"; 92 | 93 | std::cout << " <> xs[2] type " << xs[2]->getType() 94 | << " ; id = " << xs[2]->getID() << "\n"; 95 | 96 | std::for_each(xs.begin(), xs.end(), 97 | [](auto const& pBase){ 98 | showType(*pBase); 99 | }); 100 | 101 | std::vector identifiers1; 102 | std::transform(xs.begin(), xs.end(), 103 | std::back_inserter(identifiers1), 104 | [](auto pBase){ return pBase->getID(); }); 105 | 106 | 107 | std::cout << "\n === EXPERIMENT 2 ==============================" << "\n"; 108 | 109 | boost::ptr_vector ps; 110 | ps.push_back(new DerivedA); 111 | ps.push_back(new DerivedB()); 112 | ps.push_back(new DerivedA()); 113 | ps.push_back(new DerivedB); 114 | 115 | std::cout << " <> ps[0] type " << ps[0].getType() << " ; id = " << ps[0].getID() << "\n"; 116 | std::cout << " <> ps[1] type " << ps[1].getType() << " ; id = " << ps[1].getID() << "\n"; 117 | std::cout << " <> ps[2] type " << ps[2].getType() << " ; id = " << ps[2].getID() << "\n"; 118 | 119 | std::vector identifiers2; 120 | std::transform(xs.begin(), xs.end(), 121 | std::back_inserter(identifiers2), 122 | std::bind(&Base::getID, std::placeholders::_1)); 123 | 124 | std::cout << "\n ==> Show objects before deleting last item " << "\n"; 125 | std::for_each(ps.begin(), ps.end(), showType); 126 | 127 | std::cout << "\n ==> Show objects after deleting last item " << "\n"; 128 | ps.pop_back(); 129 | std::for_each(ps.begin(), ps.end(), showType); 130 | 131 | std::cout << " ============= END =================" << "\n"; 132 | 133 | return 0; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /src/dataTypeSizes.cpp: -------------------------------------------------------------------------------- 1 | /** File: dataTypeSizes.cpp 2 | Objective: Show C/C++ primitive data types sizes. 3 | 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | 12 | int main(){ 13 | // 8 bits / 1 byte numeric types 14 | //--------------------------------------------------- 15 | int charMin = numeric_limits::min() ; 16 | int charMax = numeric_limits::max() ; 17 | 18 | int scharMin = numeric_limits::min() ; 19 | int scharMax = numeric_limits::max() ; 20 | 21 | int ucharMin = numeric_limits::min() ; 22 | int ucharMax = numeric_limits::max() ; 23 | 24 | int int8Min = numeric_limits::min() ; 25 | int int8Max = numeric_limits::max() ; 26 | 27 | int uint8Min = numeric_limits::min() ; 28 | int uint8Max = numeric_limits::max() ; 29 | 30 | // 16 bits / 2 bytes Numeric types 31 | //--------------------------------------------------- 32 | 33 | int shortMin = numeric_limits::min() ; 34 | int shortMax = numeric_limits::max() ; 35 | 36 | int ushortMin = numeric_limits::min() ; 37 | int ushortMax = numeric_limits::max() ; 38 | 39 | int int16Min = numeric_limits::min() ; 40 | int int16Max = numeric_limits::max() ; 41 | 42 | int uint16Min = numeric_limits::min() ; 43 | int uint16Max = numeric_limits::max() ; 44 | 45 | // 32 bits / 4 bytes Numeric types 46 | //--------------------------------------------------- 47 | 48 | int intMin = numeric_limits::min() ; 49 | int intMax = numeric_limits::max() ; 50 | 51 | cout << "C/C++ Data type sizes in number of bytes (1 byte = 8 bits)" << endl; 52 | 53 | cout << "\n1 byte / 8 bits Data types" << endl; 54 | cout << "------------------------------------" << endl; 55 | cout << "sizeof(char) = " << sizeof(char) << " min = " << charMin << " max = " << charMax << endl; 56 | cout << "sizeof(signed char) = " << sizeof(signed char) << " min = " << scharMin << " max = " << scharMax << endl; 57 | cout << "sizeof(unsigned char) = " << sizeof(unsigned char) << " min = " << ucharMin << " max = " << ucharMax << endl; 58 | cout << "sizeof(int8_t) = " << sizeof(int8_t) << " min = " << int8Min << " max = " << int8Max << endl; 59 | cout << "sizeof(uint8_t) = " << sizeof(uint8_t) << " min = " << uint8Min << " max = " << uint8Max << endl; 60 | 61 | cout << "\n2 bytes / 16 bits Data types" << endl; 62 | cout << "------------------------------------" << endl; 63 | cout << "sizeof(short) = " << sizeof(short) << " min = " << shortMin << " max = " << shortMax << endl; 64 | cout << "sizeof(usigned short) = " << sizeof(unsigned short) << " min = " << ushortMin << " max = " << ushortMax << endl; 65 | cout << "sizeof(int16_t) = " << sizeof(int16_t) << " min = " << int16Min << " max = " << int16Max << endl; 66 | cout << "sizeof(uint16_t) = " << sizeof(uint16_t) << " min = " << uint16Min << " max = " << uint16Max << endl; 67 | 68 | cout << "\n4 bytes / 32 bits Data types" << endl; 69 | cout << "------------------------------------" << endl; 70 | cout << "sizeof(int) = " << sizeof(int) << " min = " << intMin << " max = " << intMax << endl; 71 | cout << "sizeof(int32_t) = " << sizeof(int32_t) << endl; 72 | cout << "sizeof(int64_t) = " << sizeof(int64_t) << endl; 73 | 74 | cout << "sizeof(float) = " << sizeof(float) << endl; 75 | cout << "\n8 bytes / 64 bits Data types" << endl; 76 | cout << "------------------------------------" << endl; 77 | cout << "sizeof(long) = " << sizeof(long) << endl; 78 | cout << "sizeof(long long) = " << sizeof(long long) << endl; 79 | cout << "sizeof(double) = " << sizeof(double) << endl; 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /src/numerics/decompose_binary32flt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: decompose_binary32flt.cpp 3 | * Author: Caio Rodrigues Soares Silva 4 | * Brief: Sample C++ program to decompose IEE754 32 bits floating point. 5 | * 6 | * Note: The results of this app can be checked with the online calculator: 7 | * https://calculla.com/floating_point_numbers 8 | **************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define SHOW_FLOAT(expr) show_float(#expr, (expr)) 19 | 20 | template 21 | std::string num2hexstr(T number, int padding = 8) 22 | { 23 | std::stringstream ss; 24 | if(padding != 0){ 25 | ss << "0x" << std::hex 26 | << std::setfill('0') << std::setw(padding) << number; 27 | } else { 28 | ss << "0x" << std::hex << number; 29 | } 30 | return ss.str(); 31 | } 32 | 33 | std::string to_hexfloat(float number) 34 | { 35 | std::stringstream ss; 36 | ss << std::hexfloat << number; 37 | return ss.str(); 38 | } 39 | 40 | // Decompose float point 41 | void show_float(const char* expr, float x) 42 | { 43 | constexpr int w1 = 34; 44 | constexpr int w2 = 4; 45 | 46 | // Float point classification constants 47 | static auto const fpmap = std::map{ 48 | {FP_INFINITE, "FP_INFINITE"} 49 | ,{FP_NAN, "FP_NAN"} 50 | ,{FP_NORMAL, "PF_NORMAL"} 51 | ,{FP_SUBNORMAL, "FP_SUBNORMAL"} 52 | ,{FP_ZERO, "FP_ZERO"} 53 | }; 54 | 55 | // Integer represetation extracted 56 | // through type punning aka memory reinterpretation 57 | std::uint32_t* pn = reinterpret_cast(&x); 58 | std::uint32_t value = *pn; 59 | std::uint32_t mantissa = value & ((1 << 23) - 1); 60 | std::uint32_t raw_exp = (value >> 23) & 0xFF; 61 | std::uint32_t sign = (value >> 31) & 0x01; 62 | 63 | auto print_row = [&w1, &w2](const char* label, auto const& value) 64 | { 65 | std::cout << std::setw(w1) << std::right << label 66 | << std::setw(w2) << std::left << value 67 | << "\n"; 68 | }; 69 | 70 | print_row("Input Expression: ", expr); 71 | print_row("Classification: ", fpmap.at(std::fpclassify(x))); 72 | print_row("Decimal Representation: ", x); 73 | print_row("Hexadecimal Representation: ", to_hexfloat(x)); 74 | print_row("Integer Representation (hex): ", num2hexstr(value)); 75 | print_row("Sign bit: ", sign); 76 | print_row("Exponent: ", static_cast(raw_exp) - 127); 77 | print_row("Raw Exponent: ", raw_exp); 78 | print_row("Raw Exponent (hex): ", num2hexstr(raw_exp, 0)); 79 | print_row("Mantissa (hex): ", num2hexstr(mantissa, 0)); 80 | std::cout << "\n\n"; 81 | } 82 | 83 | 84 | int main() 85 | { 86 | std::puts("\n==== Decomposition of Single Precision Float Points =====\n"); 87 | 88 | // Signed Zero 89 | SHOW_FLOAT(+0.0f); 90 | SHOW_FLOAT(-0.0f); 91 | 92 | // NaN - Not a number 93 | SHOW_FLOAT(+std::numeric_limits::quiet_NaN()); 94 | SHOW_FLOAT(-std::numeric_limits::quiet_NaN()); 95 | 96 | // Positive and negative Infinity 97 | SHOW_FLOAT(+std::numeric_limits::infinity()); 98 | SHOW_FLOAT(-std::numeric_limits::infinity()); 99 | 100 | // Subnormal 101 | SHOW_FLOAT(+std::numeric_limits::min()); 102 | SHOW_FLOAT(+std::numeric_limits::min() / 100.0f); 103 | SHOW_FLOAT(-std::numeric_limits::min() / 1000000.0f); 104 | 105 | // Epsilon 106 | SHOW_FLOAT(+std::numeric_limits::epsilon()); 107 | 108 | // Normal Numbers 109 | SHOW_FLOAT(1.0f); 110 | SHOW_FLOAT(0.5f); 111 | SHOW_FLOAT(1E-5f); 112 | SHOW_FLOAT(1.051646E4f); 113 | SHOW_FLOAT(-99000134.3401f); 114 | SHOW_FLOAT(std::numeric_limits::max()); 115 | SHOW_FLOAT(std::numeric_limits::lowest()); 116 | 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /src/design-patterns/interface-class.cpp: -------------------------------------------------------------------------------- 1 | // File: interface-class.cpp 2 | // Brief: Demonstration of interface class pattern/idiom. 3 | // Author: Caio Rodrigues 4 | //---------------------------------------------------------- 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include // Smart pointers 14 | 15 | // Interface Stack. (Should be placed in the header file.) 16 | class IStack{ 17 | public: 18 | virtual ~IStack() = default; 19 | virtual int size() const = 0; 20 | virtual void push(double x) = 0; 21 | virtual double pop() = 0; 22 | virtual double peek() const = 0; 23 | }; 24 | 25 | // Implementation of interface stack 26 | // Using vector as internal representation 27 | class StackVector: public IStack{ 28 | public: 29 | StackVector(){} 30 | StackVector(const std::initializer_list& xs){ 31 | _stack.insert(_stack.begin(), xs.begin(), xs.end()); 32 | } 33 | int size() const { 34 | return _stack.size(); 35 | } 36 | void push(double x){ 37 | _stack.push_back(x); 38 | } 39 | double pop(){ 40 | if(this->size() == 0) 41 | throw std::runtime_error("Error: stack is empty"); 42 | double top = _stack.back(); 43 | _stack.pop_back(); 44 | return top; 45 | } 46 | double peek() const { 47 | if(this->size() == 0) 48 | throw std::runtime_error("Error: stack is empty"); 49 | return _stack.back(); 50 | } 51 | private: 52 | std::vector _stack{}; 53 | }; 54 | 55 | class StackDeque: public IStack{ 56 | public: 57 | StackDeque(){} 58 | StackDeque(const std::initializer_list& xs){ 59 | _stack.insert(_stack.begin(), xs.begin(), xs.end()); 60 | } 61 | int size() const { 62 | return _stack.size(); 63 | } 64 | void push(double x){ 65 | _stack.push_back(x); 66 | } 67 | double pop(){ 68 | if(this->size() == 0) 69 | throw std::runtime_error("Error: stack is empty"); 70 | double top = _stack.back(); 71 | _stack.pop_back(); 72 | return top; 73 | } 74 | double peek() const { 75 | if(this->size() == 0) 76 | throw std::runtime_error("Error: stack is empty"); 77 | return _stack.back(); 78 | } 79 | private: 80 | std::deque _stack{}; 81 | }; 82 | 83 | auto stack_sum(IStack& s) -> double{ 84 | //std::cerr << " ==> stack_sum for references" << std::endl; 85 | double sum = 0.0; 86 | if(s.size() == 0) 87 | return sum; 88 | while(s.size() != 0) 89 | sum += s.pop(); 90 | return sum; 91 | } 92 | 93 | auto stack_sum(IStack* s) -> double{ 94 | // std::cerr << " ==> stack_sum for pointers" << std::endl; 95 | double sum = 0.0; 96 | if(s->size() == 0) 97 | return sum; 98 | while(s->size() != 0) 99 | sum += s->pop(); 100 | return sum; 101 | } 102 | 103 | int main(){ 104 | StackVector sv = {1.0, 2.0, 3.0, 5.0, 6.0}; 105 | StackDeque sd = {1.0, 2.0, 3.0, 5.0, 6.0}; 106 | // The same client code works with any implementation of the interface. 107 | std::cout << "stack_sum(sv) = " << stack_sum(sv) << std::endl; 108 | std::cout << "stack_sum(sd) = " << stack_sum(sd) << std::endl; 109 | 110 | IStack* spointer = nullptr; 111 | StackVector sv2 = {1.0, 2.0, 3.0, 5.0, 6.0}; 112 | StackDeque sd2 = {1.0, 2.0, 3.0, 5.0, 6.0}; 113 | spointer = &sv2; 114 | std::cout << "stack_sum(spointer) = " << stack_sum(spointer) << std::endl; 115 | spointer = &sd2; 116 | std::cout << "stack_sum(spointer) = " << stack_sum(spointer) << std::endl; 117 | 118 | auto sptr = std::unique_ptr>{ 119 | nullptr, 120 | // Custom deleter 121 | [](IStack* p){ 122 | std::cerr << " ==== Stack deleted OK" << std::endl ; 123 | delete p; 124 | } 125 | }; 126 | sptr.reset(new StackVector()); 127 | sptr->push(10); 128 | sptr->push(25.0); 129 | sptr->push(20.0); 130 | std::cout << "stack_sum(sptr) = " << stack_sum(*sptr) << std::endl; 131 | sptr.reset(new StackDeque()); 132 | sptr->push(10); 133 | sptr->push(25.0); 134 | sptr->push(20.0); 135 | std::cout << "stack_sum(sptr) = " << stack_sum(*sptr) << std::endl; 136 | return 0; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/numeric-limits.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * File: numeric-limits.cpp 3 | * Brief: Shows the numeric limits for all possible numerical types. 4 | * Author: Caio Rodrigues 5 | *************************************************************************/ 6 | 7 | #include 8 | #include // Numeric limits 9 | #include // setw, and other IO manipulators 10 | #include // std::string 11 | #include // uint8_t, int8_t, ... 12 | #include 13 | 14 | struct RowPrinter{ 15 | int m_left; // Left alignment 16 | int m_right; // Right alignment 17 | RowPrinter(int left, int right): m_left(left), m_right(right){ 18 | // Print bool as 'true' or 'false' instead of 0 or 1. 19 | std::cout << std::boolalpha; 20 | } 21 | 22 | template 23 | auto printRow(const std::string& label, const A& value) const -> void { 24 | std::cout << std::setw(m_left) << label 25 | << std::setw(m_right) << value << "\n"; 26 | } 27 | }; 28 | 29 | #define SHOW_INTEGER_LIMITS(numtype) showNumericLimits(#numtype) 30 | #define SHOW_FLOAT_LIMITS(numtype) showFloatPointLimits(#numtype) 31 | 32 | template 33 | void showNumericLimits(const std::string& name){ 34 | RowPrinter rp{30, 25}; 35 | std::cout << "Numeric limits for type: " << name << "\n"; 36 | std::cout << std::string(60, '-') << "\n"; 37 | rp.printRow("Type:", name); 38 | rp.printRow("Is integer:", std::numeric_limits::is_integer); 39 | rp.printRow("Is signed:", std::numeric_limits::is_signed); 40 | rp.printRow("Number of digits 10:", std::numeric_limits::digits10); 41 | rp.printRow("Max Number of digits 10:", std::numeric_limits::max_digits10); 42 | 43 | // RTTI - Run-Time Type Information 44 | if(typeid(T) == typeid(uint8_t) 45 | || typeid(T) == typeid(int8_t) 46 | || typeid(T) == typeid(bool) 47 | || typeid(T) == typeid(char) 48 | || typeid(T) == typeid(unsigned char) 49 | ){ 50 | // Min Abs - samllest positive value for float point numbers 51 | rp.printRow("Min Abs:", static_cast(std::numeric_limits::min())); 52 | // Smallest value (can be negative) 53 | rp.printRow("Min:", static_cast(std::numeric_limits::lowest())); 54 | // Largest value 55 | rp.printRow("Max:", static_cast(std::numeric_limits::max())); 56 | } else { 57 | rp.printRow("Min Abs:", std::numeric_limits::min()); 58 | rp.printRow("Min:", std::numeric_limits::lowest()); 59 | rp.printRow("Max:", std::numeric_limits::max()); 60 | } 61 | rp.printRow("Size in bytes:", sizeof(T)); 62 | rp.printRow("Size in bits:", 8 * sizeof(T)); 63 | std::cout << "\n"; 64 | } 65 | 66 | template 67 | void showFloatPointLimits(const std::string& name){ 68 | RowPrinter rp{30, 25}; 69 | showNumericLimits(name); 70 | rp.printRow("Epsilon:", std::numeric_limits::epsilon()); 71 | rp.printRow("Min exponent:", std::numeric_limits::min_exponent10); 72 | rp.printRow("Max exponent:", std::numeric_limits::max_exponent10); 73 | } 74 | 75 | int main(){ 76 | SHOW_INTEGER_LIMITS(bool); 77 | SHOW_INTEGER_LIMITS(char); 78 | SHOW_INTEGER_LIMITS(unsigned char); 79 | SHOW_INTEGER_LIMITS(wchar_t); 80 | 81 | // Standard integers in 82 | SHOW_INTEGER_LIMITS(int8_t); 83 | SHOW_INTEGER_LIMITS(uint8_t); 84 | SHOW_INTEGER_LIMITS(int16_t); 85 | SHOW_INTEGER_LIMITS(uint16_t); 86 | SHOW_INTEGER_LIMITS(int32_t); 87 | SHOW_INTEGER_LIMITS(uint32_t); 88 | SHOW_INTEGER_LIMITS(int64_t); 89 | SHOW_INTEGER_LIMITS(uint64_t); 90 | 91 | SHOW_INTEGER_LIMITS(short); 92 | SHOW_INTEGER_LIMITS(unsigned short); 93 | SHOW_INTEGER_LIMITS(int); 94 | SHOW_INTEGER_LIMITS(unsigned int); 95 | SHOW_INTEGER_LIMITS(long); 96 | SHOW_INTEGER_LIMITS(unsigned long); 97 | SHOW_INTEGER_LIMITS(long long); 98 | SHOW_INTEGER_LIMITS(unsigned long long); 99 | 100 | SHOW_FLOAT_LIMITS(float); 101 | SHOW_FLOAT_LIMITS(double); 102 | SHOW_FLOAT_LIMITS(long double); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /src/cpp17/optional1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // std::stof 3 | #include // operator (<<) and class ostream 4 | #include 5 | #include // setprecision 6 | 7 | #include 8 | 9 | // Class with optional field. 10 | struct Location{ 11 | double lat; 12 | double lon; 13 | std::optional name; 14 | }; 15 | 16 | // Make std::optional printable 17 | std::ostream& operator<<(std::ostream& os, const Location& x){ 18 | os << std::setprecision(2) << std::fixed; 19 | if(x.name) 20 | os << "Location(" 21 | << "x = " << x.lat 22 | << " ; y = " << x.lon 23 | << " ; name = " 24 | << x.name.value() << ")"; 25 | else 26 | os << "Location(" 27 | << "x = " << x.lat 28 | << " ; y = " << x.lon 29 | << " ; name = " 30 | << "" << ")"; 31 | return os; 32 | } 33 | 34 | // Make std::optional printable 35 | std::ostream& operator<<(std::ostream& os, const std::optional& x){ 36 | if(x) 37 | os << "Some[Double](" << x.value() << ")"; 38 | else 39 | os << "None[Double]"; 40 | return os; 41 | } 42 | 43 | std::optional 44 | parseDouble(const std::string& str) 45 | { 46 | try{ 47 | // Return some value 48 | return std::make_optional(stod(str)); 49 | } catch (const std::invalid_argument& ex) { 50 | // Return nothing 51 | return std::nullopt; 52 | } 53 | } 54 | 55 | auto getEnvVar(std::string const& varname) -> std::optional 56 | { 57 | if(const char* v = std::getenv(varname.c_str())) 58 | // Returns some value 59 | return v; 60 | else 61 | // Returns nothing (same as std::nullopt) 62 | return {}; 63 | } 64 | 65 | int main(){ 66 | char endl = '\n'; 67 | 68 | std::optional oa; 69 | std::optional ob = std::nullopt; 70 | std::optional oc = 10.233; 71 | std::optional od(1e3); 72 | std::optional oe {}; 73 | 74 | std::puts("==== EXPERIMENT 1 === Print optional value"); 75 | std::cout << "oa = " << oa << endl; 76 | std::cout << "ob = " << ob << endl; 77 | std::cout << "oc = " << oc << endl; 78 | std::cout << "od = " << od << endl; 79 | std::cout << "oe = " << oe << endl; 80 | 81 | std::puts("==== EXPERIMENT 2 === Reset optional value"); 82 | std::cout << "Reset variable oc " << endl; 83 | oc.reset(); 84 | std::cout << "oc = " << oc << endl; 85 | 86 | std::puts("==== EXPERIMENT 3 ==== check whether optional has value. (is not empty) ===="); 87 | if(oc) 88 | std::cout << ">> oc has a vaule" << endl; 89 | else 90 | std::cout << ">> oc is empty" << endl; 91 | 92 | std::puts("==== EXPERIMENT 4 ==== try parse double ===="); 93 | std::cout << "x0 = " << parseDouble("-1.0e3") << endl; 94 | std::cout << "x1 = " << parseDouble("1.351 ") << endl; 95 | std::cout << "x2 = " << parseDouble("1.asdasd351 xxgh") << endl; 96 | std::cout << "x4 = " << parseDouble("sad4543fgx") << endl; 97 | 98 | std::puts("=== EXPERIMENT 5 ======== Structs/Classes with optional fields ===="); 99 | std::vector xs { 100 | {10.31, 23.4, "Waypoint Delta"}, 101 | {-46.23, 145.13, "Waypoint gamma"}, 102 | {90.43, 100.345, std::nullopt}, 103 | {0, 0, {}}, 104 | }; 105 | int i = 0; 106 | for(auto x: xs){ 107 | std::cout << "x[" << i << "]" << " = " << x << endl; 108 | i++; 109 | } 110 | 111 | std::puts("=== EXPERIMENT 6 - Print environment variables. ===== "); 112 | auto var_home = getEnvVar("HOME"); 113 | if(var_home.has_value()) 114 | std::cout << "$HOME = " << var_home.value() << endl; 115 | else 116 | std::cout << "$HOME = " << "UNKNOWN" << endl; 117 | 118 | auto var_dummy = getEnvVar("DUMMY-VAR"); 119 | if(var_dummy.has_value()) 120 | std::cout << "$DUMMYVAR = " << var_dummy.value() << endl; 121 | else 122 | std::cout << "$DUMMYVAR = " << "UNKNOWN" << endl; 123 | 124 | 125 | std::puts("==== EXPERIMENT 7 - Test member function .value_or() ===="); 126 | std::cout << "$XDG_SESSION_PATH = " 127 | << getEnvVar("XDG_SESSION_PATH").value_or("<>") << '\n'; 128 | std::cout << "$HOMEX = " 129 | << getEnvVar("HOMEX").value_or("<>") << '\n'; 130 | 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /src/design-patterns/property-type-erasure2.cpp: -------------------------------------------------------------------------------- 1 | // Author: Caio Rodrigues 2 | // Brief: Properties with type-erasure and runtime discovery 3 | //----------------------------------------------- 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // Forward declarations 13 | //------------------------- 14 | 15 | template 16 | class TProperty; 17 | 18 | class IProperty 19 | { 20 | public: 21 | virtual std::string Name() const = 0; 22 | virtual std::type_info const& Type() const = 0 ; 23 | virtual void Print(std::ostream& os) const = 0; 24 | 25 | virtual ~IProperty() = default; 26 | 27 | // Note: Adding Non virtual methods does not causes break the base class ABI 28 | // or binary compatibility with derived classes (fragile-base class problem). 29 | template 30 | T Get() const { 31 | if(this->Type() != typeid(T)) throw std::bad_cast(); 32 | return static_cast const*>(this)->Get(); 33 | } 34 | 35 | template 36 | void Set(T const& value) { 37 | if(this->Type() != typeid(T)) throw std::bad_cast(); 38 | static_cast*>(this)->Set(value); 39 | } 40 | 41 | template 42 | TProperty& As() 43 | { 44 | if(this->Type() != typeid(T)) throw std::bad_cast(); 45 | return *static_cast*>(this); 46 | } 47 | 48 | template 49 | void Visit(Visitor& visitor) 50 | { 51 | if(this->Type() != typeid(T)) throw std::bad_cast(); 52 | static_cast*>(this)->Visit(visitor); 53 | } 54 | 55 | // Make class printable 56 | friend std::ostream& operator<<(std::ostream& os, IProperty const& rhs) 57 | { 58 | rhs.Print(os); 59 | return os; 60 | } 61 | }; 62 | 63 | /** Class that encapsulate get/set properties 64 | * @tparam - Type default constructible, copiable and equality-comparable 65 | */ 66 | template 67 | class TProperty: public IProperty 68 | { 69 | std::string m_name; 70 | T m_value; 71 | std::type_info const* m_tinfo; 72 | public: 73 | TProperty(std::string name, T const& init = T{}) 74 | : m_name(std::move(name)) 75 | , m_value(init) 76 | , m_tinfo(&typeid(T)) 77 | { } 78 | 79 | ~TProperty() = default; 80 | 81 | std::string Name() const 82 | { 83 | return m_name; 84 | } 85 | 86 | const std::type_info& Type() const 87 | { 88 | return *m_tinfo; 89 | } 90 | T Get() const 91 | { 92 | return m_value; 93 | } 94 | TProperty& Set(T const& value) 95 | { 96 | std::cerr << " [TRACE] Property [" << m_name << "] set to value = " 97 | << value << std::endl; 98 | m_value = value; 99 | return *this; 100 | } 101 | 102 | void Print(std::ostream& os) const 103 | { 104 | os << " Property{ Name = " << std::quoted(m_name) 105 | << " ; Value = " << m_value << " }"; 106 | } 107 | 108 | void PrintValue(std::ostream& os) const 109 | { 110 | os << m_value; 111 | } 112 | 113 | template 114 | void Visit(Visitor& visitor) 115 | { 116 | visitor.visit(m_value); 117 | } 118 | }; 119 | 120 | template 121 | std::shared_ptr 122 | make_property(std::string const& name, T const& init = T{}) 123 | { 124 | return std::make_shared>(name, init); 125 | } 126 | 127 | int main() 128 | { 129 | std::vector> plist; 130 | 131 | plist.push_back(make_property("basis-points", 100)); 132 | plist.push_back(make_property("price", 5.6)); 133 | plist.push_back(make_property("product", "")); 134 | 135 | std::cout <<"\n ======= Experiment 1 =======" << std::endl; 136 | int i = 0; 137 | for(const auto& p: plist) 138 | std::cout << " => p[" << i++ << "] = " << *p << "\n"; 139 | 140 | std::cout <<"\n ======= Experiment 2 =======" << std::endl; 141 | TProperty& p0 = plist[0]->As(); 142 | p0.Set(200); 143 | std::cout << " => p0.Name() = " << p0.Name() << " ; Value = " << p0.Get() << "\n"; 144 | 145 | plist[0]->Set(80); 146 | 147 | std::cout << " => plist[0]->Name() = " << plist[0]->Name() 148 | << " plist[0]->Get() = " << plist[0]->Get() 149 | << std::endl; 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /src/dlls/example-windows1/testlib.hpp: -------------------------------------------------------------------------------- 1 | // File: testlib.hpp 2 | // Brief: Sample Windows shared library / DLL header 3 | // Author: Caio Rodrigues 4 | //------------------------------------------------------ 5 | #ifndef _TESTLIB_H_ 6 | #define _TESTLIB_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef _WIN32 13 | // If not compiled for Windows, remove declspec directive. 14 | #define __declspec(param) 15 | #endif 16 | 17 | #define EXPORT_CPP __declspec(dllexport) 18 | 19 | #ifdef __cplusplus 20 | // Indicat that a given symbol/function has C-linkage and 21 | // does not have name mangling. 22 | #define EXPORT_C extern "C" __declspec(dllexport) 23 | #else 24 | // If a C-compiler uses this header, remove 'extern "C"' 25 | #define EXPORT_C __declspec(dllexport) 26 | #endif 27 | 28 | 29 | /** The macro __cplusplus is used for allowing this 30 | * header to be used from 'C'. If a C compiler is used 31 | * all definitions inside this #ifdef are discarded. 32 | */ 33 | #ifdef __cplusplus 34 | 35 | namespace Linalg { 36 | EXPORT_CPP double norm(const std::vector& xs); 37 | 38 | EXPORT_CPP std::vector linTransform( 39 | double a, 40 | double b, 41 | std::vector& xs 42 | ); 43 | 44 | EXPORT_CPP 45 | std::ostream& 46 | printVector(std::ostream& os, std::vector& xs); 47 | } 48 | 49 | #endif 50 | 51 | // ======= C-interface for Linalg namespace =========// 52 | 53 | /** Handle or opaque pointer for std::vector */ 54 | typedef void* hVectorD; 55 | 56 | /* ----- C-Wrappers for Linalg namespace ---- */ 57 | 58 | extern "C" __declspec(dllexport) 59 | double testlib_vectorD_Linalg_norm(hVectorD hv); 60 | 61 | extern "C" __declspec(dllexport) 62 | void testlib_vectorD_Linalg_printVector(const char* name, hVectorD hv); 63 | 64 | 65 | // ======= Non-polymorphic class exported by DLL =========// 66 | 67 | #ifdef __cplusplus 68 | // Non-polymorphic class 69 | class __declspec(dllexport) SampleClass{ 70 | public: 71 | SampleClass(); 72 | SampleClass(const std::string& name); 73 | ~SampleClass(); 74 | std::string getName() const; 75 | int get(); 76 | void set(int n); 77 | private: 78 | std::string m_name; 79 | int m_counter; 80 | }; 81 | #endif 82 | 83 | 84 | /* ----- C-Wrappers for SampleClass namespace ---- */ 85 | 86 | using hSampleClass = void*; 87 | 88 | /** Nullable constructor zero-arg constructor */ 89 | extern "C" __declspec(dllexport) 90 | hSampleClass 91 | testlib_SampleClass_make0(); 92 | 93 | /** Other constructor */ 94 | EXPORT_C hSampleClass testlib_SampleClass_make1(const char* name); 95 | 96 | /** Destructor */ 97 | EXPORT_C 98 | void 99 | testlib_SampleClass_delete(hSampleClass hnd); 100 | 101 | /** Wrapper for get method */ 102 | EXPORT_C 103 | int 104 | testlib_SampleClass_get(hSampleClass hnd); 105 | 106 | /** Wrapper for set method */ 107 | EXPORT_C 108 | void 109 | testlib_SampleClass_set(hSampleClass hnd, int n); 110 | 111 | EXPORT_C 112 | const char* 113 | testlib_SampleClass_getName(hSampleClass hnd); 114 | 115 | //========== Interface class ============// 116 | 117 | 118 | // Polymorphic Interface class 119 | // binary compatible across different compilers 120 | // as it does not use any STL container on the 121 | // interface. 122 | #ifdef __cplusplus 123 | struct InterfaceClass{ 124 | /* Returns class unique ID */ 125 | virtual const char* getID() const = 0; 126 | /** Set class internal state */ 127 | virtual void setName(const char* name) = 0; 128 | virtual const char* getName() = 0; 129 | 130 | /** Virtual constructor */ 131 | virtual ~InterfaceClass() = default; 132 | // virtual ~InterfaceClass(); 133 | }; 134 | #else 135 | #define InterfaceClass void 136 | #endif 137 | 138 | 139 | /** Factory function */ 140 | EXPORT_C InterfaceClass* teslib_InterfaceClass_factory(const char* class_id); 141 | /** C-wrapper for destructor */ 142 | EXPORT_C void testlib_InterfaceClass_delete(InterfaceClass* hinst); 143 | /** C-wrapper for getID method */ 144 | EXPORT_C const char* testlib_InterfaceClass_getID(InterfaceClass* hinst); 145 | EXPORT_C void testlib_InterfaceClass_setName(InterfaceClass* hinst, const char* name); 146 | EXPORT_C const char* testlib_InterfaceClass_getName(InterfaceClass* hinst); 147 | 148 | 149 | #endif /** --- End of file */ 150 | -------------------------------------------------------------------------------- /src/regex1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #define DBG_DISP(expr) std::cerr << __FILE__ << ":" << __LINE__ << ":" \ 7 | << " ; " << #expr << " = " << (expr) << std::endl 8 | 9 | int main() 10 | { 11 | std::cout << std::boolalpha; 12 | std::cerr << std::boolalpha; 13 | 14 | { 15 | std::puts("\n ======== EXPERIMENT 1 === Match entire string ====="); 16 | std::regex numRegex("\\d+"); 17 | DBG_DISP(std::regex_match("3423", numRegex)); 18 | DBG_DISP(std::regex_match("AAB786", numRegex)); 19 | DBG_DISP(std::regex_match(" 9745", numRegex)); 20 | DBG_DISP(std::regex_match(" 634 ", numRegex)); 21 | } 22 | { 23 | std::puts("\n ======== EXPERIMENT 2 === Check whether text has regex ====="); 24 | std::regex variable("\\s?[a-zA-Z][a-zA-Z|\\d]*\\b"); 25 | DBG_DISP(std::regex_search("3423", variable)); 26 | DBG_DISP(std::regex_search("dot.com\\ -buble hello variable4561 ", variable)); 27 | DBG_DISP(std::regex_search(" -dot.com.buble.burst ", variable)); 28 | } 29 | { 30 | std::puts("\n ======== EXPERIMENT 3 === Extract text ====="); 31 | std::regex phoneRe{"phone:\\s*(\\d{8})\\s*$"}; 32 | std::string line; 33 | std::smatch result; 34 | 35 | line = "phone:85619751"; 36 | if(std::regex_search(line, result, phoneRe) && result.size() > 1) 37 | std::cout << "Result1 = " << result.str(1) << "\n"; 38 | else 39 | std::cout << "Result1 = <>" << std::endl; 40 | 41 | line = "phone: 65658741 "; 42 | if(std::regex_search(line, result, phoneRe) && result.size() > 1) 43 | std::cout << "Result2 = " << result.str(1) << "\n"; 44 | else 45 | std::cout << "Result2 = <>" << std::endl; 46 | 47 | line = "phone: 756596213434"; 48 | if(std::regex_search(line, result, phoneRe) && result.size() > 1) 49 | std::cout << "Result3 = " << result.str(1) << "\n"; 50 | else 51 | std::cout << "Result3 = <>" << std::endl; 52 | 53 | line = "phone: ABBX621"; 54 | if(std::regex_search(line, result, phoneRe) && result.size() > 1) 55 | std::cout << "Result4 = " << result.str(1) << "\n"; 56 | else 57 | std::cout << "Result4 = <>" << std::endl; 58 | } 59 | 60 | { 61 | std::puts("\n ======== EXPERIMENT 4-A === Finding all regex matches ======"); 62 | std::regex nregex("[0-9]+\\b", std::regex::ECMAScript); 63 | std::string line = " 565 923 100 -934 AABB56 0835"; 64 | std::sregex_iterator it_beg(line.begin(), line.end(), nregex); 65 | std::sregex_iterator it_end; 66 | std::cout << " Number of matches = " << std::distance(it_beg, it_end) << "\n"; 67 | int i = 0; 68 | for(auto it = it_beg; it != it_end; it++){ 69 | std::cout << " => x[" << i++ << "] = " << it->str() << "\n"; 70 | } 71 | } 72 | { 73 | std::puts("\n ======== EXPERIMENT 4-B === Finding all regex matches ======"); 74 | // Matches 4 letters followed by 3 digits 75 | // first capture group 4 letters set, second capture group: 3 digits set 76 | std::regex re("([A-Z]{4})([0-9]{3})"); 77 | std::string line = " ABCD367 XYAZ561 baa 341 MNPQ456 "; 78 | std::sregex_iterator begin(line.begin(), line.end(), re); 79 | std::sregex_iterator end; 80 | for(auto it = begin; it != end; it++) 81 | std::cout << " capture[0] = " << it->str() 82 | << " ; capture[1] = " << it->str(1) 83 | << " ; capture[2] = " << it->str(2) 84 | << "\n"; 85 | } 86 | { 87 | std::puts("\n ======== EXPERIMENT 4-C === Finding all regex matches range-based loop ==="); 88 | // Matches 4 letters followed by 3 digits 89 | // first capture group 4 letters set, second capture group: 3 digits set 90 | std::regex re("([A-Z]{4})([0-9]{3})"); 91 | std::string line = " ABCD367 XYAZ561 baa 341 MNPQ456 "; 92 | std::smatch matches; 93 | std::regex_search(line, matches, re); 94 | for(const auto& m : matches ) 95 | std::cout << " =>>> " << m << "\n"; 96 | } 97 | { 98 | std::puts("\n ======== EXPERIMENT 5 === Replace matches ======"); 99 | // Matches 4 letters followed by 3 digits 100 | // first capture group 4 letters set, second capture group: 3 digits set 101 | std::regex re("([A-Z]{4})([0-9]{3})"); 102 | std::string line = " ABCD367 XYAZ561 baa 341 MNPQ456 "; 103 | std::string out = std::regex_replace(line, re, "{$1=$2} - "); 104 | std::cout << " out = " << out << std::endl; 105 | 106 | } 107 | return 0; 108 | } 109 | -------------------------------------------------------------------------------- /src/windows/dynamic-loading2.cpp: -------------------------------------------------------------------------------- 1 | // File: dynamic-loading2.cpp 2 | // Brief: Dynamically loads a DLL - shared library at runtime using a class. 3 | // Note: Demonstration of WINAPIs LoadLibrary, FreeLibrary, GetProcAddress 4 | // Author: Caio Rodrigues 5 | //--------------------------------------------------------------------------- 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | //========== File: DLLLoader.hpp =======// 12 | class DLLLoader 13 | { 14 | private: 15 | HMODULE m_hLib; 16 | std::string m_file; 17 | public: 18 | DLLLoader(const std::string& file); 19 | DLLLoader(const DLLLoader&) = delete; 20 | DLLLoader(DLLLoader&& rhs); 21 | ~DLLLoader(); 22 | auto operator=(const DLLLoader&) = delete; 23 | auto operator=(DLLLoader&& rhs); 24 | 25 | auto GetFile() const -> std::string; 26 | auto IsLoaded() const -> bool; 27 | operator bool() const; 28 | 29 | template 30 | auto GetFunction(const std::string& functionName ) const -> FunctionSignature* 31 | { 32 | if(m_hLib == nullptr) 33 | return nullptr; 34 | FARPROC hFunc = ::GetProcAddress(m_hLib, functionName.c_str()); 35 | if(hFunc == nullptr) 36 | return nullptr; 37 | return reinterpret_cast(hFunc); 38 | } 39 | }; 40 | 41 | //========== File: Main.cpp =======// 42 | 43 | int main(){ 44 | // Wide-unicode strings 45 | std::wstring fileURL = L"http://httpbin.org/image/jpeg"; 46 | std::wstring file1 = L"download-file1.jpeg"; 47 | std::wstring file2 = L"download-file2.jpeg"; 48 | 49 | auto dll = DLLLoader("urlmon.dll"); 50 | if(!dll){ 51 | std::cerr << "[Error] failed to load DLL." << std::endl; 52 | return EXIT_FAILURE; 53 | } 54 | std::cerr << "[INFO] DLL loaded OK." << std::endl; 55 | 56 | // -----------------------------------------------------------------// 57 | std::cout << "===== Experiment 1 =========== " << std::endl; 58 | 59 | auto URLDownloadToFileW = 60 | dll.GetFunction("URLDownloadToFileW"); 65 | 66 | if(URLDownloadToFileW == nullptr){ 67 | std::cerr << "[Error] failed to load function. " << std::endl; 68 | return EXIT_FAILURE; 69 | } 70 | std::cerr << "[INFO] Function URLDownloadToFileW loaded OK. " << std::endl; 71 | 72 | 73 | HRESULT result1 = URLDownloadToFileW(nullptr, fileURL.c_str(), file1.c_str(), 0, nullptr); 74 | if(SUCCEEDED(result1)) 75 | std::cerr << " [INFO] Download successful OK. " << std::endl; 76 | else 77 | std::cerr << " [ERROR] Download failure. " << std::endl; 78 | 79 | // -----------------------------------------------------------------// 80 | std::cout << "===== Experiment 2 =========== " << std::endl; 81 | // Note: Calling convention __cdecl can be omitted 82 | using URLDownloadToFileW_t = 83 | HRESULT (*) (LPUNKNOWN, LPCWSTR, LPCWSTR, DWORD, LPBINDSTATUSCALLBACK); 84 | 85 | auto URLDownloadToFileW2 = 86 | dll.GetFunction("URLDownloadToFileW"); 87 | 88 | HRESULT result2 = 89 | URLDownloadToFileW(nullptr, fileURL.c_str(), file2.c_str(), 0, nullptr); 90 | 91 | if(SUCCEEDED(result2)) 92 | std::cerr << " [INFO] Download successful OK. " << std::endl; 93 | else 94 | std::cerr << " [ERROR] Download failure. " << std::endl; 95 | return 0; 96 | } 97 | 98 | ///==== Implementations - file: DLLoader.hpp =======// 99 | DLLLoader::DLLLoader(const std::string& file): 100 | m_file(file), 101 | m_hLib(::LoadLibraryA(file.c_str())) 102 | { 103 | } 104 | 105 | // Move CTOR 106 | DLLLoader::DLLLoader(DLLLoader&& rhs): 107 | m_hLib(std::move(rhs.m_hLib)), 108 | m_file(std::move(rhs.m_file)) 109 | { 110 | } 111 | // Move assignment operator 112 | auto DLLLoader::operator=(DLLLoader&& rhs) 113 | { 114 | std::swap(this->m_hLib, rhs.m_hLib); 115 | std::swap(this->m_file, rhs.m_file); 116 | } 117 | 118 | DLLLoader::~DLLLoader() 119 | { 120 | std::cerr << " [INFO] DLL handler released OK." << std::endl; 121 | if(m_hLib != nullptr) 122 | ::FreeLibrary(m_hLib); 123 | } 124 | 125 | auto DLLLoader::GetFile() const -> std::string 126 | { 127 | return m_file; 128 | } 129 | 130 | auto DLLLoader::IsLoaded() const -> bool 131 | { 132 | return m_hLib == nullptr; 133 | } 134 | 135 | DLLLoader::operator bool() const 136 | { 137 | return m_hLib != nullptr; 138 | } 139 | -------------------------------------------------------------------------------- /src/cppStlVector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /// Pass the vectors by value. It copies the vectors, so passing by 9 | // reference does not copies the vectors and it is more efficient. 10 | // 11 | vector sumVectors1(vector xs, vector ys){ 12 | vector zs(xs.size()); 13 | 14 | for (int i = 0; i < xs.size(); i++){ 15 | zs.at(i) = xs.at(i) + ys.at(i); 16 | } 17 | 18 | return zs; 19 | } 20 | 21 | vector sumVectors2(vector &xs, vector &ys){ 22 | vector zs(xs.size()); 23 | 24 | for (int i = 0; i < xs.size(); i++){ 25 | zs.at(i) = xs.at(i) + ys.at(i); 26 | } 27 | 28 | return zs; 29 | } 30 | 31 | 32 | void printVector1(string name, vector xs){ 33 | cout << name << " = [ "; 34 | 35 | for (int i = 0; i < xs.size(); i++){ 36 | cout << xs.at(i) << " " ; 37 | } 38 | 39 | cout << "]" << endl; 40 | } 41 | 42 | void printVector2(string name, vector &xs){ 43 | cout << name << " = [ "; 44 | 45 | for (int i = 0; i < xs.size(); i++){ 46 | cout << xs.at(i) << " " ; 47 | } 48 | 49 | cout << "]" << endl; 50 | } 51 | 52 | void printVectorWithIterator(string name, vector &xs){ 53 | cout << name << " = [ "; 54 | 55 | for (vector::iterator i = xs.begin(); i != xs.end(); ++i){ 56 | cout << *i << " " ; 57 | } 58 | 59 | cout << "]" << endl; 60 | 61 | } 62 | 63 | 64 | // Returns the sum of all vector elements. 65 | double vectorSum(vector &xs){ 66 | double sum = 0; 67 | 68 | for (int i = 0; i < xs.size(); i++){ 69 | sum = sum + xs.at(i); 70 | } 71 | 72 | return sum; 73 | } 74 | 75 | // Returns the product of all vectors elements. 76 | double vectorProd(vector &xs){ 77 | double prod = 1.0; 78 | 79 | for (int i = 0; i < xs.size(); i++){ 80 | prod = prod + xs.at(i); 81 | } 82 | 83 | return prod; 84 | } 85 | 86 | double vectorNorm(vector &xs){ 87 | double sum = 1.0; 88 | double x = 0.0; 89 | 90 | for (int i = 0; i < xs.size(); i++){ 91 | x = xs.at(i); 92 | sum = sum + x * x; 93 | } 94 | 95 | return sqrt(sum); 96 | } 97 | 98 | 99 | double vectorAverage(vector &xs){ 100 | double sum = 1.0; 101 | 102 | for (int i = 0; i < xs.size(); i++){ 103 | sum = sum + xs.at(i); 104 | } 105 | 106 | return sum / xs.size(); 107 | } 108 | 109 | 110 | void vectorAnalytics(string name, vector &xs){ 111 | cout << "\n\nAnalytic for vector " << name << endl; 112 | cout << "----------------------------------- " << endl; 113 | printVector2(name, xs); 114 | cout << "size = " << xs.size() << endl; 115 | cout << "average = " << vectorAverage(xs) << endl; 116 | cout << "sum = " << vectorSum(xs) << endl; 117 | cout << "product = " << vectorProd(xs) << endl; 118 | cout << "norm = " << vectorNorm(xs) << endl; 119 | 120 | } 121 | 122 | 123 | int main(){ 124 | int size = 6; 125 | 126 | // Vector initialized from a double array. 127 | vector xs({1, 2, 3, 5.5, 10.8, 4.5}); 128 | 129 | // Vector initialized with all elements set to 0.0 130 | vector ys(6); 131 | 132 | // Vector intialized with all elements set to 4.0 133 | vector zs(6, 4.0); 134 | 135 | // Vector with 0 elements. 136 | vector ks; 137 | 138 | printVector1("xs", xs); 139 | 140 | printVector1("ys", ys); 141 | 142 | printVector2("zs", zs); 143 | 144 | printVectorWithIterator("Print Vector with iteractor - xs", xs); 145 | 146 | cout << "xs.size() = " << xs.size() << endl ; 147 | cout << "xs.at(3) = " << xs.at(3) << endl ; 148 | cout << "xs.at(0) = " << xs.at(0) << endl ; 149 | cout << "xs.at(5) = " << xs.at(5) << endl ; 150 | cout << "vectorSum(xs) = " << vectorSum(xs) << endl; 151 | cout << "vectorNorm(xs) = " << vectorNorm(xs) << endl; 152 | 153 | printVector1("sumVectors1(xs, zs) = xs + zs", sumVectors1(xs, zs)); 154 | printVector1("sumVectors2(xs, zs) = xs + zs", sumVectors2(xs, zs)); 155 | 156 | cout << "Clear vector xs -> " ; 157 | xs.clear(); 158 | printVector2("xs", xs); 159 | 160 | ks.push_back(4.0); 161 | ks.push_back(5.0); 162 | ks.push_back(3.0); 163 | ks.push_back(6.0); 164 | ks.push_back(7.0); 165 | ks.push_back(9.3); 166 | printVector2("ks", ks); 167 | 168 | vectorAnalytics("ks", ks); 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /dotnet-cpp-ffi1/hpc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // #include "hpc.hpp" 7 | 8 | using namespace std; 9 | 10 | /// it can be put in a separated header file. 11 | // 12 | extern "C" { double vector2DNorm(double x, double y); } 13 | 14 | extern "C" { double vectorNorm(double [], int) ; } 15 | 16 | extern "C" { double arrayNorm(double [], int); } 17 | 18 | extern "C" { void* createVector(double [], int); } 19 | 20 | extern "C" { double* genArray(int size); } 21 | 22 | extern "C" { void genArray2(double* arr, int size); } 23 | 24 | extern "C" {double vectorSum(double xs [], size_t n); } 25 | 26 | /// C-wrapper for the circle class 27 | extern "C" { 28 | void *Circle_new (double radius); 29 | void Circle_delete (void *circle); 30 | double Circle_getArea(void *circle); 31 | } 32 | 33 | 34 | 35 | // Create a C++ STL vector from an C-array. 36 | // 37 | vector arrayToVector(double arr[], int n){ 38 | vector xs; 39 | for (int i = 0; i < n; i++){ 40 | xs.push_back(arr[i]); 41 | } 42 | return xs; 43 | } 44 | 45 | vector arrayToVector2(double arr[], int n){ 46 | // arr -> Is a pointer to the first array cell 47 | // arr + n -> Is a pointer ot the last array cell. 48 | vector v(arr, arr + n); 49 | return v; 50 | } 51 | 52 | 53 | // extern "C" { void* createVector(double [], int); } 54 | 55 | void* createVector(double xs [], int n){ 56 | vector v(xs, xs + n); 57 | return static_cast (& v[0]); 58 | } 59 | 60 | 61 | 62 | 63 | 64 | double arrayNorm(double xs [], int n){ 65 | double acc = 0; 66 | 67 | for (int i = 0; i < n; i++){ 68 | acc = acc + xs[i] * xs[i]; 69 | } 70 | 71 | return sqrt(acc); 72 | } 73 | 74 | 75 | double vector2DNorm(double x, double y){ 76 | return sqrt(x * x + y * y); 77 | } 78 | 79 | 80 | double vectorNorm(vector &xs){ 81 | double sum = 0.0; 82 | 83 | for (size_t i = 0; i < xs.size(); i++){ 84 | sum = sum + xs.at(i) * xs.at(i); 85 | } 86 | 87 | return sqrt(sum); 88 | } 89 | 90 | 91 | // C-wrapper to vectorNorm 92 | // 93 | // extern "C" { double vectorNorm(double [], int) ; } 94 | // 95 | double vectorNorm(double xs [], int n){ 96 | //vector v = arrayToVector(xs, n); 97 | vector v = arrayToVector2(xs, n); 98 | return vectorNorm(v); 99 | } 100 | 101 | double vectorSum(vector &xs){ 102 | double sum = 0.0 ; 103 | for (size_t i = 0; i < xs.size(); i++){ 104 | sum = sum + xs.at(i); 105 | } 106 | } 107 | 108 | // C-wrapper for vectorSum 109 | // 110 | double vectorSum(double xs [], size_t n){ 111 | vectorv(n); 112 | double* p = v.data(); 113 | p = xs; 114 | return vectorSum(v); 115 | } 116 | 117 | 118 | 119 | vector vectorScale(vector &xs, double scale){ 120 | vector ys; 121 | 122 | for (int i = 0; i < xs.size(); i++){ 123 | ys.push_back(scale * xs.at(i)); 124 | } 125 | return ys; 126 | } 127 | 128 | 129 | // void vectorScale(double xs [], int n, double* out){ 130 | // vector v = vectorScale(arrayToVector2(xs, n)); 131 | // return v 132 | // } 133 | 134 | // Generates an array of size n 135 | // 136 | double* genArray(int size){ 137 | double *arr = new double[size]; 138 | 139 | for(int i = 0; i < size; i++){ 140 | arr[i] = i * i; 141 | } 142 | 143 | return arr; 144 | } 145 | 146 | // Generates an array of size n 147 | // 148 | // Unlike genArray, in this function, the caller 149 | // must allocate the array that will be returned. 150 | // 151 | void genArray2(double *xs, int size){ 152 | for(int i = 0; i < size; i++){ 153 | xs[i] = i * i; 154 | } 155 | } 156 | 157 | 158 | 159 | class Circle{ 160 | private: 161 | double radius; 162 | double PI = 3.1415; 163 | 164 | public: 165 | Circle(){ 166 | radius = 1.0; 167 | } 168 | 169 | Circle(double rad){ 170 | radius = rad; 171 | } 172 | 173 | double getArea(){ 174 | return radius * radius * PI; 175 | } 176 | 177 | }; 178 | 179 | 180 | // Return a void pointer to the circle object. 181 | // 182 | void* Circle_new(double radius){ 183 | return new Circle(radius); 184 | } 185 | 186 | void Circle_delete(void* circle){ 187 | // Cast void pointer to circle 188 | Circle *c = (Circle *) circle; 189 | // Deallocate the memory. 190 | delete c; 191 | } 192 | 193 | double Circle_getArea(void* circle){ 194 | Circle *c = (Circle *) circle; 195 | return c->getArea(); 196 | } 197 | 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /src/operator-overload1.cpp: -------------------------------------------------------------------------------- 1 | // File: operator-overload1.cpp 2 | // Brief: Arithmetic operator overloading 3 | // Author: Caio Rodrigues 4 | //-------------------------------------------- 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /**----------------------------------------- 12 | * Complex.hpp - Class declaration 13 | *-----------------------------------------*/ 14 | 15 | /** Complex number */ 16 | class Complex{ 17 | private: 18 | double m_real, m_imag; 19 | public: 20 | /** Make class printable */ 21 | friend std::ostream& operator<<(std::ostream&, const Complex&); 22 | 23 | /** Constructors */ 24 | Complex(); 25 | Complex(double real, double imag); 26 | /** Named constructor */ 27 | static Complex fromReal(double real); 28 | static Complex fromImag(double imag); 29 | 30 | double Real() const; 31 | double Imag() const; 32 | 33 | Complex operator-(); 34 | Complex operator+(const Complex& rhs); 35 | Complex operator-(const Complex& rhs); 36 | Complex operator*(const Complex& rhs); 37 | Complex operator/(const Complex& rhs); 38 | 39 | Complex operator+(double d); 40 | Complex operator-(double d); 41 | Complex operator*(double scale); 42 | Complex operator/(double factor); 43 | }; 44 | 45 | //------ Overloaded Functions ---------------// 46 | 47 | double abs(Complex& cpl){ 48 | double x = cpl.Real(); 49 | double y = cpl.Imag(); 50 | return std::sqrt(x * x + y * y); 51 | } 52 | 53 | /**----------------------------------------- 54 | * Main() 55 | *-----------------------------------------*/ 56 | 57 | int main(){ 58 | std::cout << " ==== [EXPERIMENT 1] ==============" << std::endl; 59 | Complex c1; 60 | Complex c2{2, 5}; 61 | Complex c3{3, 4}; 62 | std::cout << "c1 = " << c1 << " ; c2 = " << c2 << " ; c3 = " << c3 << std::endl; 63 | 64 | std::cout << " ==== [EXPERIMENT 2] ==============" << std::endl; 65 | auto r1 = c2 + c3; 66 | std::cout << "-(c2 + c3) = " << -(c2 + c3) << std::endl; 67 | std::cout << "c2 + c2 = " << r1 << std::endl; 68 | std::cout << "r1.Real() = " << r1.Real() << " ; r1.Imag() = " << r1.Imag() << std::endl; 69 | std::cout << " 4 * (c1 + c2 + c3) = " << (c1 + c2 + c3) * 4 << std::endl; 70 | std::cout << "(c2 * c3 - c1) = " << (c2 * c3 - c1) << std::endl; 71 | 72 | std::cout << "(c2 / c3) * 25 = " << c2 / c3 * 25 << std::endl; 73 | 74 | std::cout << " ==== [EXPERIMENT 3] ==============" << std::endl; 75 | 76 | std::cout << "abs(c2) = " << abs(c2) << std::endl; 77 | 78 | 79 | return 0; 80 | } 81 | 82 | /**------------------------------------------------------ 83 | * File: Complex.cpp - Class implementation (definition) 84 | *------------------------------------------------------*/ 85 | 86 | std::ostream& operator<<(std::ostream& os, const Complex& rhs){ 87 | return os << "Complex{ " << rhs.m_real << " + " << rhs.m_imag << "j" << " }"; 88 | } 89 | 90 | Complex::Complex(double real, double imag) 91 | : m_real(real), m_imag(imag) 92 | { 93 | } 94 | 95 | Complex::Complex(): Complex(0.0, 0.0) 96 | { 97 | } 98 | 99 | 100 | Complex Complex::fromReal(double real) 101 | { 102 | return Complex(real, 0); 103 | } 104 | 105 | Complex Complex::fromImag(double imag) 106 | { 107 | return Complex(0, imag); 108 | } 109 | 110 | double Complex::Real() const { 111 | return m_real; 112 | } 113 | 114 | double Complex::Imag() const { 115 | return m_imag; 116 | } 117 | 118 | Complex Complex::operator-(){ 119 | return {-m_real, -m_imag}; 120 | } 121 | 122 | Complex Complex::operator+(const Complex& rhs) 123 | { 124 | const auto& self = *this; 125 | return {self.m_real + rhs.m_real, self.m_imag + rhs.m_imag }; 126 | } 127 | 128 | Complex Complex::operator-(const Complex& rhs) 129 | { 130 | const auto& self = *this; 131 | // (x1 + j . y1)(x2 + j . y2) = x1.x2 + j( -y1.y2 ) 132 | return Complex{self.m_real - rhs.m_real, self.m_imag - rhs.m_imag }; 133 | } 134 | 135 | Complex Complex::operator*(const Complex& rhs) 136 | { 137 | return Complex{ 138 | m_real * rhs.m_real - m_imag * rhs.m_imag, 139 | m_real * rhs.m_imag + m_imag * rhs.m_real 140 | }; 141 | } 142 | 143 | Complex Complex::operator/(const Complex& rhs) 144 | { 145 | double q = rhs.m_real * rhs.m_real + rhs.m_imag * rhs.m_imag; 146 | double real = this->m_real * rhs.m_real + this->m_imag * rhs.m_imag; 147 | double imag = this->m_imag * rhs.m_real - this->m_real * rhs.m_imag; 148 | return { real / q, imag / q }; 149 | } 150 | 151 | Complex Complex::operator+(double d){ 152 | return Complex{m_real + d, m_imag + d}; 153 | } 154 | Complex Complex::operator-(double d){ 155 | return Complex{m_real - d, m_imag - d}; 156 | } 157 | Complex Complex::operator*(double scale){ 158 | return {this->m_real * scale, this->m_imag * scale}; 159 | } 160 | Complex Complex::operator/(double factor){ 161 | return Complex(this->m_real / factor, this->m_imag / factor); 162 | } 163 | 164 | -------------------------------------------------------------------------------- /src/gsl-vector-wrapper.cpp: -------------------------------------------------------------------------------- 1 | // Brief: C++ Wrapper example to GNU Scientific Library Vector. 2 | // Author: Caio Rodrigues 3 | // Compile with: $ clang++ gsl-vector-wrapper.cpp -std=c++11 -Wall -Wextra -g -lgsl -lgslcblas -o out.bin 4 | // Run with: $ ./out.bin 5 | // 6 | // GNU Scientific Library - C++ Linear Algebra Wrapper 7 | //---------------------------------------------------------------------- 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // Install GNU Scientific Library on Fedora with: 18 | // $ sudo dnf install gsl-devel.x86_64 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include /* Random numbers*/ 26 | #include 27 | 28 | 29 | // Load Shared libraries needed by CLING REPL. 30 | #ifdef __CLING__ 31 | R__LOAD_LIBRARY(/lib64/libgslcblas.so.0); 32 | R__LOAD_LIBRARY(/lib64/libgsl.so); 33 | #endif 34 | 35 | class GSLVector{ 36 | private: 37 | gsl_vector* m_hnd; 38 | int m_size; 39 | public: 40 | GSLVector(int m_size) { 41 | this->m_size = m_size; 42 | this->m_hnd = gsl_vector_alloc(m_size); 43 | } 44 | // Overloaded constructor 45 | GSLVector(int m_size, double x) { 46 | this->m_size = m_size; 47 | this->m_hnd = gsl_vector_alloc(m_size); 48 | gsl_vector_set_all(m_hnd, x); 49 | } 50 | // Copy constructor 51 | GSLVector(const GSLVector& src){ 52 | m_size = src.m_size; 53 | m_hnd = gsl_vector_alloc(src.m_size); 54 | gsl_vector_memcpy(m_hnd, src.m_hnd); 55 | } 56 | // Copy assignment operator 57 | GSLVector& operator= (const GSLVector& src){ 58 | std::cerr << " [TRACE] Copy assignment operator." << "\n"; 59 | if(m_size != src.m_size){ 60 | gsl_vector_free(m_hnd); 61 | m_hnd = gsl_vector_alloc(src.m_size); 62 | } 63 | gsl_vector_memcpy(m_hnd, src.m_hnd); 64 | return *this; 65 | } 66 | // Destructor 67 | ~GSLVector(){ 68 | if(m_hnd != nullptr) 69 | gsl_vector_free(m_hnd); 70 | } 71 | size_t size() const { return m_size; } 72 | 73 | gsl_vector* data(){ 74 | return this->m_hnd; 75 | } 76 | struct ElementProxy{ 77 | GSLVector* ptr; 78 | size_t index; 79 | ElementProxy(GSLVector* ptr, size_t index): ptr(ptr), index(index){} 80 | ElementProxy& operator=(double x){ 81 | gsl_vector_set(ptr->data(), index, x); 82 | return *this; 83 | } 84 | double get() const { 85 | return gsl_vector_get(ptr->data(), index); 86 | } 87 | }; 88 | 89 | ElementProxy operator[](size_t index){ 90 | return ElementProxy(this, index); 91 | // return gsl_vector_get(m_hnd, index); 92 | } 93 | // double operator[](int index){ 94 | // return gsl_vector_get(m_hnd, index); 95 | // } 96 | 97 | void set(int index, double x){ 98 | gsl_vector_set(m_hnd, index, x); 99 | } 100 | double max() const { 101 | return gsl_vector_max(m_hnd); 102 | } 103 | double min() const { 104 | return gsl_vector_min(m_hnd); 105 | } 106 | GSLVector operator + (const GSLVector& va){ 107 | // Invoke copy constructor 108 | GSLVector vec2 = *this; 109 | gsl_vector_add(vec2.m_hnd, va.m_hnd); 110 | return vec2; 111 | } 112 | GSLVector operator * (double scale){ 113 | // Invoke copy constructor 114 | GSLVector vec2 = *this; 115 | gsl_vector_scale(vec2.m_hnd, scale); 116 | return vec2; 117 | } 118 | friend std::ostream& operator<<(std::ostream& os, const GSLVector& vec){ 119 | os << "[" << vec.m_size << "]("; 120 | for(int i = 0; i < vec.m_size; i++){ 121 | os << std::setprecision(4) << std::fixed << " " << gsl_vector_get(vec.m_hnd, i); 122 | } 123 | os << ") "; 124 | return os; 125 | } 126 | }; 127 | 128 | int main(){ 129 | GSLVector vec1(5, 2.45); 130 | vec1.set(0, -3.45); 131 | 132 | std::cout << std::boolalpha; 133 | std::cout << "vec1 = " << vec1 << "\n"; 134 | // test copy constructor 135 | std::puts("Create vec2 - before invoke copy constructor"); 136 | GSLVector vec2 = vec1; 137 | std::cout << "vec1 = " << vec2 << "\n"; 138 | std::cout << "&vec2 == &vec1: " << (&vec1 == &vec2) << "\n"; 139 | assert(&vec2 != &vec1); 140 | vec2.set(0, 10.0); 141 | vec2.set(1, 25.0); 142 | vec2[3] = 2.30; 143 | std::cout << "vec2 = " << vec2 << "\n"; 144 | 145 | GSLVector vec3 = vec1 + vec2; 146 | std::cout << "vec3 = " << vec3 << "\n"; 147 | std::cout << "vec1 * 3 + vec2 * 2.5 = " << vec1 * 1.5 + vec2 * 2.5 << "\n"; 148 | 149 | return 0; 150 | } 151 | 152 | --------------------------------------------------------------------------------