diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5b79a5415be450374d4fd7937805c31124ee120f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.cache/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000000000000000000000000000000..27dc726797ef1c2e36260c4eec44a4f91df80cae --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "program": "${workspaceFolder}/", //TODO: Add executable file here + "args": [ + "" // TODO: Add arguments here + ], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6c696d2e65e1dc613b3a0a51647def3854d4799e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.8.0) +project(stl_debug VERSION 0.1.0 LANGUAGES C CXX) + +set(CMAKE_CXX_STANDARD 17) + + +SET(CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fsanitize=address") + +if(CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE "Debug") +endif() + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +message(STATUS "BUILD TYPE : ${CMAKE_BUILD_TYPE}") + +INCLUDE_DIRECTORIES( + include +) + +add_subdirectory(src) + diff --git a/include/Human.hpp b/include/Human.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2a307bd63112b6ef48417d28182e339867937cb4 --- /dev/null +++ b/include/Human.hpp @@ -0,0 +1,14 @@ +#pragma once +#include +class Human +{ +private: + /* data */ + std::string name_; + int age_; +public: + explicit Human(int age, const std::string name = "") : name_(name), age_(age) {}; + virtual ~Human(); + virtual std::string print() const; + +}; diff --git a/include/Student.hpp b/include/Student.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c461ff1d5c23cb45a4c9c8654b651d02a955410c --- /dev/null +++ b/include/Student.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "Human.hpp" +#include + +class Student : public Human +{ +private: + /* data */ + std::string school_; +public: + Student() = delete; + explicit Student(int age, const std::string name = "", const std::string school = "") : Human(age, name), school_(school) {}; + virtual ~Student() override; + virtual std::string print() const override; +}; \ No newline at end of file diff --git a/include/logging.hpp b/include/logging.hpp new file mode 100644 index 0000000000000000000000000000000000000000..032e8d465291742ed90af66975989d2baf4811e5 --- /dev/null +++ b/include/logging.hpp @@ -0,0 +1,82 @@ +#ifndef LOGGING_HPP +#define LOGGING_HPP + +#include +#include +#include + +enum LogLevel +{ + DEBUG = 0, + INFO, + WARNING, + ERROR +}; +struct LocationInfo +{ + LocationInfo(std::string file, int line, const char *func) : file_(file), line_(line), func_(func) {} + ~LocationInfo() = default; + + std::string file_; + int line_; + const char *func_; +}; +class LogStream; +class LogWriter; + +class LogWriter +{ +public: + LogWriter(LocationInfo location, LogLevel loglevel) + : location_(location), log_level_(loglevel) + { + char *logv = std::getenv("LOGV"); + if (logv) + { + std::string string_logv = logv; + env_log_level = std::stoi(logv); + } + else + { + env_log_level = 4; + } + }; + + void operator<(const LogStream &stream); + +private: + void output_log(const std::ostringstream &g); + LocationInfo location_; + LogLevel log_level_; + int env_log_level; +}; + +class LogStream +{ +public: + template + LogStream &operator<<(const T &val) noexcept + { + sstream_ << val; + return *this; + } + + friend class LogWriter; + +private: + std::stringstream sstream_{}; +}; + +std::string level2string(LogLevel level); +std::string get_short_name(const char *file_path); + +#define __FILESHORTNAME__ get_short_name(__FILE__) +#define LOG_IF(level) \ + LogWriter(LocationInfo(__FILESHORTNAME__, __LINE__, __FUNCTION__), level) < LogStream() +#define LOG(level) LOG_##level +#define LOG_DEBUG LOG_IF(DEBUG) +#define LOG_INFO LOG_IF(INFO) +#define LOG_WARNING LOG_IF(WARNING) +#define LOG_ERROR LOG_IF(ERROR) + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..0276e9b0bbb4939f70edde4597bdf33809ff4b8d --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable( + lab0_debug main.cpp Human.cpp Student.cpp logging.cpp +) + +add_executable( + test_logging test_logging.cpp logging.cpp +) \ No newline at end of file diff --git a/src/Human.cpp b/src/Human.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc1b993bb47bf02b172af7ebcd1663d5522ea913 --- /dev/null +++ b/src/Human.cpp @@ -0,0 +1,15 @@ +#include "Human.hpp" +#include +#include + +Human::~Human() { + printf("Human destructor called\n"); +} + +std::string Human::print() const { + std::string res; + std::stringstream ss; + ss << "My name is " << name_ << " and I am " << age_ << " years old\n"; + ss >> res; + return res; +} \ No newline at end of file diff --git a/src/Student.cpp b/src/Student.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7576ea54718fa6260dee6d44d2558d2059e1cc9 --- /dev/null +++ b/src/Student.cpp @@ -0,0 +1,18 @@ +#include "Student.hpp" +#include "Human.hpp" +#include "cstring" +#include +#include + +Student::~Student() { + printf("Student destructor called\n"); +} + +std::string Student::print() const { + std::string res; + std::stringstream ss; + ss << Human::print(); + ss << "I'm from " << school_ << "\n"; + ss >> res; + return res; +} \ No newline at end of file diff --git a/src/logging.cpp b/src/logging.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d508956a1b2b051adfa19da833bb6ad9a3dec13 --- /dev/null +++ b/src/logging.cpp @@ -0,0 +1,42 @@ +#include "logging.hpp" + +void LogWriter::operator<(const LogStream &stream) { + std::ostringstream msg; + msg << stream.sstream_.rdbuf(); + output_log(msg); +} + +void LogWriter::output_log(const std::ostringstream &msg) { + if (log_level_ >= env_log_level) + std::cout << "[" << level2string(log_level_) << "] " + << "(" << location_.file_ + << ":" << location_.line_ + << "L "<< location_.func_<<")" + << msg.str() << std::endl; + +} +std::string level2string(LogLevel level) { + switch (level) + { + case DEBUG: + return "DEBUG"; + + case INFO: + return "INFO"; + + case WARNING: + return "WARNING"; + + case ERROR: + return "ERROR"; + + default: + return ""; + } +} +std::string get_short_name(const char * file_path) { + std::string short_file_path = file_path; + int index = short_file_path.find_last_of('/'); + + return short_file_path.substr(index+1); +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0669233e80ca9bae88dd726d28609190e288702a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include "Human.hpp" +#include "Student.hpp" +#include + +class check{ + public: + explicit check(Student* student){ + printf("Student object created\n"); + } +}; + +int main(int argc, char** argv){ + if(argc == 1 || std::string(argv[1]) != "-t"){ + std::cerr << "error: invalid argument\n"; + exit(-1); + } + printf("Hello, from stl_debug!\n"); + std::vector vec; + Human human(25, "John Doe"); + Student student(20, "Jane Doe", "MIT"); + vec.push_back(&human); + vec.push_back(&student); + for (const auto& h : vec) { + std::cout << h->print(); + } + // auto student1 = new Student(); //TODO: Error 1 : why? + auto student1 = static_cast(vec.back()); + // check check1 = check(vec.back()); //TODO: Error 2 : why? + check check1 = check(student1); + + // std::list list; + // list.push_back(1); + // for(auto i: list){ + // list.remove(i); //TODO: Error 3 : why? + // } + return 0; +} diff --git a/src/test_logging.cpp b/src/test_logging.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f58f8687b1dda8c5176e667b793031c580c35b30 --- /dev/null +++ b/src/test_logging.cpp @@ -0,0 +1,11 @@ +#include "logging.hpp" +// 引入头文件 +int main(){ + LOG(DEBUG) << "This is DEBUG log item."; + // 使用关键字 LOG,括号中填入要输出的日志等级 + // 紧接着就是<<以及日志的具体信息,就跟使用 std::cout 一样 + LOG(INFO) << "This is INFO log item"; + LOG(WARNING) << "This is WARNING log item"; + LOG(ERROR) << "This is ERROR log item"; + return 0; +} \ No newline at end of file