diff options
| author | crupest <crupest@outlook.com> | 2020-12-30 15:37:39 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2020-12-30 15:37:39 +0800 | 
| commit | e0964bbc4f66e7d193abd249213c9cf762fd0294 (patch) | |
| tree | ee4f5307fc555ef66a3752e20388dca8f386c2f1 /works | |
| parent | 7e9e803b33a9380d2ff3111c8d11f25f5d2b98ec (diff) | |
| download | crupest-e0964bbc4f66e7d193abd249213c9cf762fd0294.tar.gz crupest-e0964bbc4f66e7d193abd249213c9cf762fd0294.tar.bz2 crupest-e0964bbc4f66e7d193abd249213c9cf762fd0294.zip  | |
import(life): ...
Diffstat (limited to 'works')
| -rw-r--r-- | works/life/cpp-practicum/Base.hpp | 37 | ||||
| -rw-r--r-- | works/life/cpp-practicum/Book.cpp | 36 | ||||
| -rw-r--r-- | works/life/cpp-practicum/Book.hpp | 51 | ||||
| -rw-r--r-- | works/life/cpp-practicum/CMakeLists.txt | 21 | ||||
| -rw-r--r-- | works/life/cpp-practicum/Record.cpp | 38 | ||||
| -rw-r--r-- | works/life/cpp-practicum/Record.hpp | 36 | ||||
| -rw-r--r-- | works/life/cpp-practicum/StringUtil.cpp | 305 | ||||
| -rw-r--r-- | works/life/cpp-practicum/StringUtil.hpp | 148 | ||||
| -rw-r--r-- | works/life/cpp-practicum/Vendor.cpp | 33 | ||||
| -rw-r--r-- | works/life/cpp-practicum/Vendor.hpp | 45 | ||||
| -rw-r--r-- | works/life/cpp-practicum/main.cpp | 297 | 
11 files changed, 286 insertions, 761 deletions
diff --git a/works/life/cpp-practicum/Base.hpp b/works/life/cpp-practicum/Base.hpp index f26b81f..bdf87dd 100644 --- a/works/life/cpp-practicum/Base.hpp +++ b/works/life/cpp-practicum/Base.hpp @@ -1,15 +1,8 @@  #pragma once
 -#include <cstddef>
  #include <exception>
 -// #include <gsl/gsl>
  #include <stdexcept>
 -// Now we have no gsl but we need gsl::index
 -namespace gsl {
 -using index = std::ptrdiff_t;
 -}
 -
  #define CRU_UNUSED(entity) static_cast<void>(entity);
  #define CRU__CONCAT(a, b) a##b
 @@ -31,33 +24,7 @@ using index = std::ptrdiff_t;    classname(classname &&) = delete;                                            \
    classname &operator=(classname &&) = delete;
 -namespace cru {
 -class Object {
 +class SerializationException : public std::runtime_error {
  public:
 -  Object() = default;
 -  CRU_DEFAULT_COPY(Object)
 -  CRU_DEFAULT_MOVE(Object)
 -  virtual ~Object() = default;
 -};
 -
 -struct Interface {
 -  Interface() = default;
 -  CRU_DELETE_COPY(Interface)
 -  CRU_DELETE_MOVE(Interface)
 -  virtual ~Interface() = default;
 +  using runtime_error::runtime_error;
  };
 -
 -[[noreturn]] inline void UnreachableCode() { std::terminate(); }
 -
 -using Index = gsl::index;
 -
 -// https://www.boost.org/doc/libs/1_54_0/doc/html/hash/reference.html#boost.hash_combine
 -template <class T> inline void hash_combine(std::size_t &s, const T &v) {
 -  std::hash<T> h;
 -  s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
 -}
 -
 -#define CRU_DEFINE_CLASS_LOG_TAG(tag)                                          \
 -private:                                                                       \
 -  constexpr static std::u16string_view log_tag = tag;
 -} // namespace cru
 diff --git a/works/life/cpp-practicum/Book.cpp b/works/life/cpp-practicum/Book.cpp new file mode 100644 index 0000000..bf67d7c --- /dev/null +++ b/works/life/cpp-practicum/Book.cpp @@ -0,0 +1,36 @@ +#include "Book.hpp"
 +
 +#include <QString>
 +
 +QTextStream &operator>>(QTextStream &left, Book &right) {
 +  auto line = left.readLine();
 +
 +  auto fields = line.split(QChar('|'));
 +
 +  if (fields.size() != 6) {
 +    throw SerializationException("The line has not 6 parts.");
 +  }
 +
 +  right.SetIsbn(fields[0].toStdU16String());
 +  right.SetTitle(fields[1].toStdU16String());
 +  right.SetType(fields[2].toStdU16String());
 +  right.SetAuthor(fields[3].toStdU16String());
 +  right.SetPress(fields[4].toStdU16String());
 +
 +  bool ok;
 +  auto stock_count = fields[5].toInt(&ok);
 +  if (!ok) {
 +    throw SerializationException("Part 6 is not a number.");
 +  }
 +
 +  right.SetStockCount(stock_count);
 +
 +  return left;
 +}
 +
 +QTextStream &operator<<(QTextStream &left, const Book &right) {
 +  left << right.GetIsbn() << '|' << right.GetTitle() << '|' << right.GetType()
 +       << '|' << right.GetAuthor() << '|' << right.GetPress() << '|'
 +       << right.GetStockCount();
 +  return left;
 +}
 diff --git a/works/life/cpp-practicum/Book.hpp b/works/life/cpp-practicum/Book.hpp new file mode 100644 index 0000000..2fb1123 --- /dev/null +++ b/works/life/cpp-practicum/Book.hpp @@ -0,0 +1,51 @@ +#pragma once
 +#include "Base.hpp"
 +
 +#include <QTextStream>
 +#include <string>
 +
 +class Book final {
 +public:
 +  Book() = default;
 +
 +  Book(std::u16string isbn, std::u16string title, std::u16string type,
 +       std::u16string author, std::u16string press, int stock_count)
 +      : isbn_(std::move(isbn)), title_(std::move(title)),
 +        type_(std::move(type)), author_(std::move(author)),
 +        press_(std::move(press)), stock_count_(stock_count) {}
 +
 +  CRU_DEFAULT_COPY(Book)
 +  CRU_DEFAULT_MOVE(Book)
 +
 +  ~Book() = default;
 +
 +public:
 +  std::u16string GetIsbn() const { return isbn_; }
 +  void SetIsbn(std::u16string isbn) { isbn_ = std::move(isbn); }
 +
 +  std::u16string GetTitle() const { return title_; }
 +  void SetTitle(std::u16string title) { title_ = std::move(title); }
 +
 +  std::u16string GetType() const { return type_; }
 +  void SetType(std::u16string type) { type_ = std::move(type); }
 +
 +  std::u16string GetAuthor() const { return author_; }
 +  void SetAuthor(std::u16string author) { author_ = std::move(author); }
 +
 +  std::u16string GetPress() const { return press_; }
 +  void SetPress(std::u16string press) { press_ = std::move(press); }
 +
 +  int GetStockCount() const { return stock_count_; }
 +  void SetStockCount(int stock_count) { stock_count_ = stock_count; }
 +
 +private:
 +  std::u16string isbn_;
 +  std::u16string title_;
 +  std::u16string type_;
 +  std::u16string author_;
 +  std::u16string press_;
 +  int stock_count_;
 +};
 +
 +QTextStream &operator>>(QTextStream &left, Book &right);
 +QTextStream &operator<<(QTextStream &left, const Book &right);
 diff --git a/works/life/cpp-practicum/CMakeLists.txt b/works/life/cpp-practicum/CMakeLists.txt index fbf1c13..7958850 100644 --- a/works/life/cpp-practicum/CMakeLists.txt +++ b/works/life/cpp-practicum/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../vcpkg/scripts/buildsystems/vcpkg.cmake
 +  CACHE STRING "Vcpkg toolchain file")
 +
  cmake_minimum_required(VERSION 3.14)
  project(CppPraticum)
 @@ -11,4 +14,20 @@ if (MSVC)  	add_compile_options(/utf-8 /W4 /WX)
  endif()
 -add_executable(main main.cpp Base.hpp StringUtil.hpp StringUtil.cpp)
 +find_package(Qt5Core CONFIG REQUIRED)
 +find_package(Qt5Gui CONFIG REQUIRED)
 +find_package(Qt5Widgets CONFIG REQUIRED)
 +
 +add_executable(main
 +	Base.hpp
 +
 +	Book.hpp
 +	Book.cpp
 +	Vendor.hpp
 +	Vendor.cpp
 +	Record.hpp
 +	Record.cpp
 +
 +	main.cpp
 +)
 +target_link_libraries(main PRIVATE Qt5::Core Qt5::Widgets Qt5::Gui)
 diff --git a/works/life/cpp-practicum/Record.cpp b/works/life/cpp-practicum/Record.cpp new file mode 100644 index 0000000..1041b23 --- /dev/null +++ b/works/life/cpp-practicum/Record.cpp @@ -0,0 +1,38 @@ +#include "Record.hpp"
 +
 +void Record::WriteTo(QFile file) {
 +  file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate);
 +  QTextStream stream(&file);
 +  stream.setCodec("UTF-8");
 +
 +  stream << books_.size() << ' ' << vendors_.size() << '\n';
 +  for (const auto &book : books_) {
 +    stream << book << '\n';
 +  }
 +  for (const auto &vendor : vendors_) {
 +    stream << vendor << '\n';
 +  }
 +}
 +
 +void Record::ReadFrom(QFile file) {
 +  file.open(QFile::ReadOnly | QFile::Text);
 +  QTextStream stream(&file);
 +  stream.setCodec("UTF-8");
 +
 +  books_.clear();
 +  vendors_.clear();
 +
 +  int book_count, vendor_count;
 +  stream >> book_count >> vendor_count;
 +  stream.skipWhiteSpace();
 +  for (int i = 0; i < book_count; i++) {
 +    Book book;
 +    stream >> book;
 +    books_.push_back(std::move(book));
 +  }
 +  for (int i = 0; i < vendor_count; i++) {
 +    Vendor vendor;
 +    stream >> vendor;
 +    vendors_.push_back(std::move(vendor));
 +  }
 +}
 diff --git a/works/life/cpp-practicum/Record.hpp b/works/life/cpp-practicum/Record.hpp new file mode 100644 index 0000000..e39e626 --- /dev/null +++ b/works/life/cpp-practicum/Record.hpp @@ -0,0 +1,36 @@ +#pragma once
 +#include "Base.hpp"
 +
 +#include "Book.hpp"
 +#include "Vendor.hpp"
 +
 +#include <QFile>
 +#include <optional>
 +#include <vector>
 +
 +class Record final {
 +public:
 +  Record();
 +
 +  CRU_DEFAULT_COPY(Record);
 +  CRU_DEFAULT_MOVE(Record);
 +
 +  ~Record() = default;
 +
 +public:
 +  void WriteTo(QFile file);
 +  void ReadFrom(QFile file);
 +
 +  const std::vector<Book> &GetBooks() const { return books_; }
 +  const std::vector<Vendor> &GetVendors() const { return vendors_; }
 +
 +  // TODO: Implementation
 +  std::optional<Book> FindBookByIsbn(std::u16string_view isbn);
 +
 +  // TODO: Implementation
 +  void RemoveBookByIsbn(std::u16string_view isbn);
 +
 +private:
 +  std::vector<Book> books_;
 +  std::vector<Vendor> vendors_;
 +};
 diff --git a/works/life/cpp-practicum/StringUtil.cpp b/works/life/cpp-practicum/StringUtil.cpp deleted file mode 100644 index e6cd377..0000000 --- a/works/life/cpp-practicum/StringUtil.cpp +++ /dev/null @@ -1,305 +0,0 @@ -#include "StringUtil.hpp"
 -#include "Base.hpp"
 -
 -namespace cru {
 -namespace {
 -template <typename UInt, int number_of_bit, typename ReturnType>
 -inline std::enable_if_t<std::is_unsigned_v<UInt>, ReturnType>
 -ExtractBits(UInt n) {
 -  return static_cast<ReturnType>(n & ((1u << number_of_bit) - 1));
 -}
 -} // namespace
 -
 -CodePoint Utf8NextCodePoint(std::string_view str, Index current,
 -                            Index *next_position) {
 -  CodePoint result;
 -
 -  if (current >= static_cast<Index>(str.length())) {
 -    result = k_invalid_code_point;
 -  } else {
 -    const auto cu0 = static_cast<std::uint8_t>(str[current++]);
 -
 -    auto read_next_folowing_code = [&str, ¤t]() -> CodePoint {
 -      if (current == static_cast<Index>(str.length()))
 -        throw TextEncodeException(
 -            "Unexpected end when read continuing byte of multi-byte code "
 -            "point.");
 -
 -      const auto u = static_cast<std::uint8_t>(str[current]);
 -      if (!(u & (1u << 7)) || (u & (1u << 6))) {
 -        throw TextEncodeException(
 -            "Unexpected bad-format (not 0b10xxxxxx) continuing byte of "
 -            "multi-byte code point.");
 -      }
 -
 -      return ExtractBits<std::uint8_t, 6, CodePoint>(str[current++]);
 -    };
 -
 -    if ((1u << 7) & cu0) {
 -      if ((1u << 6) & cu0) {     // 2~4-length code point
 -        if ((1u << 5) & cu0) {   // 3~4-length code point
 -          if ((1u << 4) & cu0) { // 4-length code point
 -            if (cu0 & (1u << 3)) {
 -              throw TextEncodeException(
 -                  "Unexpected bad-format begin byte (not 0b11110xxx) of 4-byte"
 -                  "code point.");
 -            }
 -
 -            const CodePoint s0 = ExtractBits<std::uint8_t, 3, CodePoint>(cu0)
 -                                 << (6 * 3);
 -            const CodePoint s1 = read_next_folowing_code() << (6 * 2);
 -            const CodePoint s2 = read_next_folowing_code() << 6;
 -            const CodePoint s3 = read_next_folowing_code();
 -            result = s0 + s1 + s2 + s3;
 -          } else { // 3-length code point
 -            const CodePoint s0 = ExtractBits<std::uint8_t, 4, CodePoint>(cu0)
 -                                 << (6 * 2);
 -            const CodePoint s1 = read_next_folowing_code() << 6;
 -            const CodePoint s2 = read_next_folowing_code();
 -            result = s0 + s1 + s2;
 -          }
 -        } else { // 2-length code point
 -          const CodePoint s0 = ExtractBits<std::uint8_t, 5, CodePoint>(cu0)
 -                               << 6;
 -          const CodePoint s1 = read_next_folowing_code();
 -          result = s0 + s1;
 -        }
 -      } else {
 -        throw TextEncodeException(
 -            "Unexpected bad-format (0b10xxxxxx) begin byte of a code point.");
 -      }
 -    } else {
 -      result = static_cast<CodePoint>(cu0);
 -    }
 -  }
 -
 -  if (next_position != nullptr)
 -    *next_position = current;
 -  return result;
 -}
 -
 -CodePoint Utf16NextCodePoint(std::u16string_view str, Index current,
 -                             Index *next_position) {
 -  CodePoint result;
 -
 -  if (current >= static_cast<Index>(str.length())) {
 -    result = k_invalid_code_point;
 -  } else {
 -    const auto cu0 = str[current++];
 -
 -    if (!IsUtf16SurrogatePairCodeUnit(cu0)) { // 1-length code point
 -      result = static_cast<CodePoint>(cu0);
 -    } else if (IsUtf16SurrogatePairLeading(cu0)) { // 2-length code point
 -      if (current >= static_cast<Index>(str.length())) {
 -        throw TextEncodeException(
 -            "Unexpected end when reading second code unit of surrogate pair.");
 -      }
 -      const auto cu1 = str[current++];
 -
 -      if (!IsUtf16SurrogatePairTrailing(cu1)) {
 -        throw TextEncodeException(
 -            "Unexpected bad-range second code unit of surrogate pair.");
 -      }
 -
 -      const auto s0 = ExtractBits<std::uint16_t, 10, CodePoint>(cu0) << 10;
 -      const auto s1 = ExtractBits<std::uint16_t, 10, CodePoint>(cu1);
 -
 -      result = s0 + s1 + 0x10000;
 -
 -    } else {
 -      throw TextEncodeException(
 -          "Unexpected bad-range first code unit of surrogate pair.");
 -    }
 -  }
 -
 -  if (next_position != nullptr)
 -    *next_position = current;
 -  return result;
 -}
 -
 -CodePoint Utf16PreviousCodePoint(std::u16string_view str, Index current,
 -                                 Index *previous_position) {
 -  CodePoint result;
 -  if (current <= 0) {
 -    result = k_invalid_code_point;
 -  } else {
 -    const auto cu0 = str[--current];
 -
 -    if (!IsUtf16SurrogatePairCodeUnit(cu0)) { // 1-length code point
 -      result = static_cast<CodePoint>(cu0);
 -    } else if (IsUtf16SurrogatePairTrailing(cu0)) { // 2-length code point
 -      if (current <= 0) {
 -        throw TextEncodeException(
 -            "Unexpected end when reading first code unit of surrogate pair.");
 -      }
 -      const auto cu1 = str[--current];
 -
 -      if (!IsUtf16SurrogatePairLeading(cu1)) {
 -        throw TextEncodeException(
 -            "Unexpected bad-range first code unit of surrogate pair.");
 -      }
 -
 -      const auto s0 = ExtractBits<std::uint16_t, 10, CodePoint>(cu1) << 10;
 -      const auto s1 = ExtractBits<std::uint16_t, 10, CodePoint>(cu0);
 -
 -      result = s0 + s1 + 0x10000;
 -
 -    } else {
 -      throw TextEncodeException(
 -          "Unexpected bad-range second code unit of surrogate pair.");
 -    }
 -  }
 -
 -  if (previous_position != nullptr)
 -    *previous_position = current;
 -  return result;
 -}
 -
 -void Utf8EncodeCodePointAppend(CodePoint code_point, std::string &str) {
 -  auto write_continue_byte = [&str](std::uint8_t byte6) {
 -    str.push_back((1u << 7) + (((1u << 6) - 1) & byte6));
 -  };
 -
 -  if (code_point >= 0 && code_point <= 0x007F) {
 -    str.push_back(static_cast<char>(code_point));
 -  } else if (code_point >= 0x0080 && code_point <= 0x07FF) {
 -    std::uint32_t unsigned_code_point = code_point;
 -    str.push_back(static_cast<char>(ExtractBits<std::uint32_t, 5, std::uint8_t>(
 -                                        (unsigned_code_point >> 6)) +
 -                                    0b11000000));
 -    write_continue_byte(
 -        ExtractBits<std::uint32_t, 6, std::uint8_t>(unsigned_code_point));
 -  } else if (code_point >= 0x0800 && code_point <= 0xFFFF) {
 -    std::uint32_t unsigned_code_point = code_point;
 -    str.push_back(static_cast<char>(ExtractBits<std::uint32_t, 4, std::uint8_t>(
 -                                        (unsigned_code_point >> (6 * 2))) +
 -                                    0b11100000));
 -    write_continue_byte(
 -        ExtractBits<std::uint32_t, 6, std::uint8_t>(unsigned_code_point >> 6));
 -    write_continue_byte(
 -        ExtractBits<std::uint32_t, 6, std::uint8_t>(unsigned_code_point));
 -  } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) {
 -    std::uint32_t unsigned_code_point = code_point;
 -    str.push_back(static_cast<char>(ExtractBits<std::uint32_t, 3, std::uint8_t>(
 -                                        (unsigned_code_point >> (6 * 3))) +
 -                                    0b11110000));
 -    write_continue_byte(ExtractBits<std::uint32_t, 6, std::uint8_t>(
 -        unsigned_code_point >> (6 * 2)));
 -    write_continue_byte(
 -        ExtractBits<std::uint32_t, 6, std::uint8_t>(unsigned_code_point >> 6));
 -    write_continue_byte(
 -        ExtractBits<std::uint32_t, 6, std::uint8_t>(unsigned_code_point));
 -  } else {
 -    throw TextEncodeException("Code point out of range.");
 -  }
 -}
 -
 -void Utf16EncodeCodePointAppend(CodePoint code_point, std::u16string &str) {
 -  if ((code_point >= 0 && code_point <= 0xD7FF) ||
 -      (code_point >= 0xE000 && code_point <= 0xFFFF)) {
 -    str.push_back(static_cast<char16_t>(code_point));
 -  } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) {
 -    std::uint32_t u = code_point - 0x10000;
 -    str.push_back(static_cast<char16_t>(
 -        ExtractBits<std::uint32_t, 10, std::uint32_t>(u >> 10) + 0xD800u));
 -    str.push_back(static_cast<char16_t>(
 -        ExtractBits<std::uint32_t, 10, std::uint32_t>(u) + 0xDC00u));
 -  } else {
 -    throw TextEncodeException("Code point out of range.");
 -  }
 -}
 -
 -std::string ToUtf8(std::u16string_view s) {
 -  std::string result;
 -  for (CodePoint cp : Utf16CodePointIterator{s}) {
 -    Utf8EncodeCodePointAppend(cp, result);
 -  }
 -  return result;
 -}
 -
 -std::u16string ToUtf16(std::string_view s) {
 -  std::u16string result;
 -  for (CodePoint cp : Utf8CodePointIterator{s}) {
 -    Utf16EncodeCodePointAppend(cp, result);
 -  }
 -  return result;
 -}
 -
 -bool Utf16IsValidInsertPosition(std::u16string_view s, gsl::index position) {
 -  if (position < 0)
 -    return false;
 -  if (position > static_cast<gsl::index>(s.size()))
 -    return false;
 -  if (position == 0)
 -    return true;
 -  if (position == static_cast<gsl::index>(s.size()))
 -    return true;
 -  return !IsUtf16SurrogatePairTrailing(s[position]);
 -}
 -
 -gsl::index Utf16BackwardUntil(std::u16string_view str, gsl::index position,
 -                              const std::function<bool(CodePoint)> &predicate) {
 -  if (position <= 0)
 -    return position;
 -  while (true) {
 -    gsl::index p = position;
 -    auto c = Utf16PreviousCodePoint(str, p, &position);
 -    if (predicate(c))
 -      return p;
 -    if (c == k_invalid_code_point)
 -      return p;
 -  }
 -  UnreachableCode();
 -}
 -
 -gsl::index Utf16ForwardUntil(std::u16string_view str, gsl::index position,
 -                             const std::function<bool(CodePoint)> &predicate) {
 -  if (position >= static_cast<gsl::index>(str.size()))
 -    return position;
 -  while (true) {
 -    gsl::index p = position;
 -    auto c = Utf16NextCodePoint(str, p, &position);
 -    if (predicate(c))
 -      return p;
 -    if (c == k_invalid_code_point)
 -      return p;
 -  }
 -  UnreachableCode();
 -}
 -
 -inline bool IsSpace(CodePoint c) { return c == 0x20 || c == 0xA; }
 -
 -gsl::index Utf16PreviousWord(std::u16string_view str, gsl::index position,
 -                             bool *is_space) {
 -  if (position <= 0)
 -    return position;
 -  auto c = Utf16PreviousCodePoint(str, position, nullptr);
 -  if (IsSpace(c)) { // TODO: Currently only test against 0x20(space).
 -    if (is_space)
 -      *is_space = true;
 -    return Utf16BackwardUntil(str, position,
 -                              [](CodePoint c) { return !IsSpace(c); });
 -  } else {
 -    if (is_space)
 -      *is_space = false;
 -    return Utf16BackwardUntil(str, position, IsSpace);
 -  }
 -}
 -
 -gsl::index Utf16NextWord(std::u16string_view str, gsl::index position,
 -                         bool *is_space) {
 -  if (position >= static_cast<gsl::index>(str.size()))
 -    return position;
 -  auto c = Utf16NextCodePoint(str, position, nullptr);
 -  if (IsSpace(c)) { // TODO: Currently only test against 0x20(space).
 -    if (is_space)
 -      *is_space = true;
 -    return Utf16ForwardUntil(str, position,
 -                             [](CodePoint c) { return !IsSpace(c); });
 -  } else {
 -    if (is_space)
 -      *is_space = false;
 -    return Utf16ForwardUntil(str, position, IsSpace);
 -  }
 -}
 -} // namespace cru
 diff --git a/works/life/cpp-practicum/StringUtil.hpp b/works/life/cpp-practicum/StringUtil.hpp deleted file mode 100644 index d7b6cc9..0000000 --- a/works/life/cpp-practicum/StringUtil.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#pragma once
 -#include "Base.hpp"
 -
 -#include <functional>
 -#include <string>
 -#include <string_view>
 -
 -namespace cru {
 -using CodePoint = std::int32_t;
 -constexpr CodePoint k_invalid_code_point = -1;
 -
 -class TextEncodeException : public std::runtime_error {
 -public:
 -  using runtime_error::runtime_error;
 -};
 -
 -inline bool IsUtf16SurrogatePairCodeUnit(char16_t c) {
 -  return c >= 0xD800 && c <= 0xDFFF;
 -}
 -
 -inline bool IsUtf16SurrogatePairLeading(char16_t c) {
 -  return c >= 0xD800 && c <= 0xDBFF;
 -}
 -
 -inline bool IsUtf16SurrogatePairTrailing(char16_t c) {
 -  return c >= 0xDC00 && c <= 0xDFFF;
 -}
 -
 -CodePoint Utf8NextCodePoint(std::string_view str, Index current,
 -                            Index *next_position);
 -
 -CodePoint Utf16NextCodePoint(std::u16string_view str, Index current,
 -                             Index *next_position);
 -CodePoint Utf16PreviousCodePoint(std::u16string_view str, Index current,
 -                                 Index *previous_position);
 -
 -template <typename StringType>
 -using NextCodePointFunctionType = CodePoint (*)(StringType, Index, Index *);
 -
 -template <typename StringType,
 -          NextCodePointFunctionType<StringType> NextCodePointFunction>
 -class CodePointIterator {
 -public:
 -  using difference_type = Index;
 -  using value_type = CodePoint;
 -  using pointer = void;
 -  using reference = value_type;
 -  using iterator_category = std::forward_iterator_tag;
 -
 -public:
 -  struct past_end_tag_t {};
 -
 -  explicit CodePointIterator(StringType string)
 -      : string_(std::move(string)), position_(0) {}
 -  explicit CodePointIterator(StringType string, past_end_tag_t)
 -      : string_(std::move(string)), position_(string_.size()) {}
 -
 -  CRU_DEFAULT_COPY(CodePointIterator)
 -  CRU_DEFAULT_MOVE(CodePointIterator)
 -
 -  ~CodePointIterator() = default;
 -
 -public:
 -  StringType GetString() const { return string_; }
 -  Index GetPosition() const { return position_; }
 -
 -  bool IsPastEnd() const {
 -    return position_ == static_cast<Index>(string_.size());
 -  }
 -
 -public:
 -  CodePointIterator begin() const { return *this; }
 -  CodePointIterator end() const {
 -    return CodePointIterator{string_, past_end_tag_t{}};
 -  }
 -
 -public:
 -  bool operator==(const CodePointIterator &other) const {
 -    // You should compare iterator that iterate on the same string.
 -    Expects(this->string_.data() == other.string_.data() &&
 -            this->string_.size() == other.string_.size());
 -    return this->position_ == other.position_;
 -  }
 -  bool operator!=(const CodePointIterator &other) const {
 -    return !this->operator==(other);
 -  }
 -
 -  CodePointIterator &operator++() {
 -    Expects(!IsPastEnd());
 -    Forward();
 -    return *this;
 -  }
 -
 -  CodePointIterator operator++(int) {
 -    Expects(!IsPastEnd());
 -    CodePointIterator old = *this;
 -    Forward();
 -    return old;
 -  }
 -
 -  CodePoint operator*() const {
 -    return NextCodePointFunction(string_, position_, &next_position_cache_);
 -  }
 -
 -private:
 -  void Forward() {
 -    if (next_position_cache_ > position_) {
 -      position_ = next_position_cache_;
 -    } else {
 -      NextCodePointFunction(string_, position_, &position_);
 -    }
 -  }
 -
 -private:
 -  StringType string_;
 -  Index position_;
 -  mutable Index next_position_cache_;
 -};
 -
 -using Utf8CodePointIterator =
 -    CodePointIterator<std::string_view, &Utf8NextCodePoint>;
 -
 -using Utf16CodePointIterator =
 -    CodePointIterator<std::u16string_view, &Utf16NextCodePoint>;
 -
 -void Utf8EncodeCodePointAppend(CodePoint code_point, std::string &str);
 -void Utf16EncodeCodePointAppend(CodePoint code_point, std::u16string &str);
 -
 -std::string ToUtf8(std::u16string_view s);
 -std::u16string ToUtf16(std::string_view s);
 -
 -// If given s is not a valid utf16 string, return value is UD.
 -bool Utf16IsValidInsertPosition(std::u16string_view s, gsl::index position);
 -
 -// Return position after the character making predicate returns true or 0 if no
 -// character doing so.
 -gsl::index Utf16BackwardUntil(std::u16string_view str, gsl::index position,
 -                              const std::function<bool(CodePoint)> &predicate);
 -// Return position before the character making predicate returns true or
 -// str.size() if no character doing so.
 -gsl::index Utf16ForwardUntil(std::u16string_view str, gsl::index position,
 -                             const std::function<bool(CodePoint)> &predicate);
 -
 -gsl::index Utf16PreviousWord(std::u16string_view str, gsl::index position,
 -                             bool *is_space = nullptr);
 -gsl::index Utf16NextWord(std::u16string_view str, gsl::index position,
 -                         bool *is_space = nullptr);
 -} // namespace cru
 diff --git a/works/life/cpp-practicum/Vendor.cpp b/works/life/cpp-practicum/Vendor.cpp new file mode 100644 index 0000000..7544451 --- /dev/null +++ b/works/life/cpp-practicum/Vendor.cpp @@ -0,0 +1,33 @@ +#include "Vendor.hpp"
 +
 +#include <QString>
 +
 +QTextStream &operator>>(QTextStream &left, Vendor &right) {
 +  auto line = left.readLine();
 +
 +  auto fields = line.split(QChar('|'));
 +
 +  if (fields.size() != 5) {
 +    throw SerializationException("Line has not 5 parts.");
 +  }
 +
 +  bool ok;
 +  auto id = fields[0].toInt(&ok);
 +  if (!ok) {
 +    throw SerializationException("Part 1 is not a number.");
 +  }
 +
 +  right.SetId(id);
 +  right.SetName(fields[1].toStdU16String());
 +  right.SetType(fields[2].toStdU16String());
 +  right.SetAddress(fields[3].toStdU16String());
 +  right.SetPhone(fields[4].toStdU16String());
 +
 +  return left;
 +}
 +
 +QTextStream &operator<<(QTextStream &left, const Vendor &right) {
 +  left << right.GetId() << '|' << right.GetName() << '|' << right.GetType()
 +       << '|' << right.GetAddress() << '|' << right.GetPhone();
 +  return left;
 +}
 diff --git a/works/life/cpp-practicum/Vendor.hpp b/works/life/cpp-practicum/Vendor.hpp new file mode 100644 index 0000000..24c22ee --- /dev/null +++ b/works/life/cpp-practicum/Vendor.hpp @@ -0,0 +1,45 @@ +#pragma once
 +#include "Base.hpp"
 +
 +#include <QTextStream>
 +#include <string>
 +
 +class Vendor final {
 +public:
 +  Vendor() = default;
 +  Vendor(int id, std::u16string name, std::u16string type,
 +         std::u16string address, std::u16string phone)
 +      : id_(id), name_(std::move(name)), type_(std::move(type)),
 +        address_(std::move(address)), phone_(std::move(phone)) {}
 +
 +  CRU_DEFAULT_COPY(Vendor)
 +  CRU_DEFAULT_MOVE(Vendor)
 +
 +  ~Vendor() = default;
 +
 +public:
 +  int GetId() const { return id_; }
 +  void SetId(int id) { id_ = id; }
 +
 +  std::u16string GetName() const { return name_; }
 +  void SetName(std::u16string name) { name_ = std::move(name); }
 +
 +  std::u16string GetType() const { return type_; }
 +  void SetType(std::u16string type) { type_ = std::move(type); }
 +
 +  std::u16string GetAddress() const { return address_; }
 +  void SetAddress(std::u16string address) { address_ = std::move(address); }
 +
 +  std::u16string GetPhone() const { return phone_; }
 +  void SetPhone(std::u16string phone) { phone_ = std::move(phone); }
 +
 +private:
 +  int id_;
 +  std::u16string name_;
 +  std::u16string type_;
 +  std::u16string address_;
 +  std::u16string phone_;
 +};
 +
 +QTextStream &operator>>(QTextStream &left, Vendor &right);
 +QTextStream &operator<<(QTextStream &left, const Vendor &right);
 diff --git a/works/life/cpp-practicum/main.cpp b/works/life/cpp-practicum/main.cpp index 0f90b74..a6c92e5 100644 --- a/works/life/cpp-practicum/main.cpp +++ b/works/life/cpp-practicum/main.cpp @@ -1,281 +1,34 @@ -#include "Base.hpp"
 -#include "StringUtil.hpp"
 +#include "qboxlayout.h"
 +#include "qnamespace.h"
 +#include <QApplication>
 +#include <QHBoxLayout>
 +#include <QMainWindow>
 +#include <QPushButton>
 +#include <QVBoxLayout>
 +#include <QWidget>
 -#include <fstream>
 -#include <iostream>
 -#include <optional>
 -#include <ostream>
 -#include <stdexcept>
 -#include <string>
 -#include <string_view>
 -#include <type_traits>
 +int main(int argc, char *argv[]) {
 +  QApplication application(argc, argv);
 -inline std::u16string_view ToUtf16View(const std::wstring &str) {
 -  return std::u16string_view(reinterpret_cast<const char16_t *>(str.c_str()),
 -                             str.size());
 -}
 -
 -inline std::wstring_view ToWStringView(std::u16string_view str) {
 -  return std::wstring_view(reinterpret_cast<const wchar_t *>(str.data()),
 -                           str.size());
 -}
 -
 -class SerializationException : public std::runtime_error {
 -public:
 -  using runtime_error::runtime_error;
 -};
 -
 -std::vector<std::string_view> SplitByVerticalLine(std::string_view str,
 -                                                  int field_count) {
 -  std::vector<std::string_view> fields;
 -  gsl::index current_position = 0;
 -
 -  for (int i = 0; i < field_count - 1; i++) {
 -    auto pos = str.find('|', current_position);
 -    if (pos == std::string::npos) {
 -      throw SerializationException("Failed to find next splitter('|').");
 -    }
 -    fields.push_back(str.substr(current_position, pos - current_position));
 -    current_position = pos + 1;
 -  }
 -  fields.push_back(str.substr(current_position));
 -
 -  return fields;
 -}
 -
 -class Book final {
 -public:
 -  Book() = default;
 -
 -  Book(std::u16string isbn, std::u16string title, std::u16string type,
 -       std::u16string author, std::u16string press, int stock_count)
 -      : isbn_(std::move(isbn)), title_(std::move(title)),
 -        type_(std::move(type)), author_(std::move(author)),
 -        press_(std::move(press)), stock_count_(stock_count) {}
 -
 -  CRU_DEFAULT_COPY(Book)
 -  CRU_DEFAULT_MOVE(Book)
 -
 -  ~Book() = default;
 -
 -public:
 -  std::u16string GetIsbn() const { return isbn_; }
 -  void SetIsbn(std::u16string isbn) { isbn_ = std::move(isbn); }
 -
 -  std::u16string GetTitle() const { return title_; }
 -  void SetTitle(std::u16string title) { title_ = std::move(title); }
 -
 -  std::u16string GetType() const { return type_; }
 -  void SetType(std::u16string type) { type_ = std::move(type); }
 -
 -  std::u16string GetAuthor() const { return author_; }
 -  void SetAuthor(std::u16string author) { author_ = std::move(author); }
 -
 -  std::u16string GetPress() const { return press_; }
 -  void SetPress(std::u16string press) { press_ = std::move(press); }
 -
 -  int GetStockCount() const { return stock_count_; }
 -  void SetStockCount(int stock_count) { stock_count_ = stock_count; }
 -
 -private:
 -  std::u16string isbn_;
 -  std::u16string title_;
 -  std::u16string type_;
 -  std::u16string author_;
 -  std::u16string press_;
 -  int stock_count_;
 -};
 -
 -std::istream &operator>>(std::istream &left, Book &right) {
 -  std::string line;
 -  std::getline(left, line);
 -
 -  std::vector<std::string_view> fields = SplitByVerticalLine(line, 6);
 -
 -  right.SetIsbn(cru::ToUtf16(fields[0]));
 -  right.SetTitle(cru::ToUtf16(fields[1]));
 -  right.SetType(cru::ToUtf16(fields[2]));
 -  right.SetAuthor(cru::ToUtf16(fields[3]));
 -  right.SetPress(cru::ToUtf16(fields[4]));
 -  right.SetStockCount(std::stoi(std::string(fields[5])));
 -
 -  return left;
 -}
 -
 -std::ostream &operator<<(std::ostream &left, const Book &right) {
 -  left << cru::ToUtf8(right.GetIsbn()) << '|' << cru::ToUtf8(right.GetTitle())
 -       << '|' << cru::ToUtf8(right.GetType()) << '|'
 -       << cru::ToUtf8(right.GetAuthor()) << '|' << cru::ToUtf8(right.GetPress())
 -       << '|' << right.GetStockCount();
 -  return left;
 -}
 -
 -void PrettyPrint(std::wostream &stream, const Book &book) {
 -  stream << L"ISBN: " << ToWStringView(book.GetIsbn()) << L"\n";
 -  stream << L"标题: " << ToWStringView(book.GetTitle()) << L"\n";
 -  stream << L"类型: " << ToWStringView(book.GetType()) << L"\n";
 -  stream << L"作者: " << ToWStringView(book.GetAuthor()) << L"\n";
 -  stream << L"出版社: " << ToWStringView(book.GetPress()) << L"\n";
 -  stream << L"库存: " << book.GetStockCount() << L"\n";
 -}
 -
 -class Vendor final {
 -public:
 -  Vendor() = default;
 -  Vendor(int id, std::u16string name, std::u16string type,
 -         std::u16string address, std::u16string phone)
 -      : id_(id), name_(std::move(name)), type_(std::move(type)),
 -        address_(std::move(address)), phone_(std::move(phone)) {}
 -
 -  CRU_DEFAULT_COPY(Vendor)
 -  CRU_DEFAULT_MOVE(Vendor)
 -
 -  ~Vendor() = default;
 -
 -public:
 -  int GetId() const { return id_; }
 -  void SetId(int id) { id_ = id; }
 -
 -  std::u16string GetName() const { return name_; }
 -  void SetName(std::u16string name) { name_ = std::move(name); }
 -
 -  std::u16string GetType() const { return type_; }
 -  void SetType(std::u16string type) { type_ = std::move(type); }
 -
 -  std::u16string GetAddress() const { return address_; }
 -  void SetAddress(std::u16string address) { address_ = std::move(address); }
 -
 -  std::u16string GetPhone() const { return phone_; }
 -  void SetPhone(std::u16string phone) { phone_ = std::move(phone); }
 -
 -private:
 -  int id_;
 -  std::u16string name_;
 -  std::u16string type_;
 -  std::u16string address_;
 -  std::u16string phone_;
 -};
 -
 -std::istream &operator>>(std::istream &left, Vendor &right) {
 -  std::string line;
 -  std::getline(left, line);
 -
 -  std::vector<std::string_view> fields = SplitByVerticalLine(line, 5);
 -
 -  right.SetId(std::stoi(std::string(fields[0])));
 -  right.SetName(cru::ToUtf16(fields[1]));
 -  right.SetType(cru::ToUtf16(fields[2]));
 -  right.SetAddress(cru::ToUtf16(fields[3]));
 -  right.SetPhone(cru::ToUtf16(fields[4]));
 -
 -  return left;
 -}
 -
 -std::ostream &operator<<(std::ostream &left, const Vendor &right) {
 -  left << right.GetId() << '|' << cru::ToUtf8(right.GetName()) << '|'
 -       << cru::ToUtf8(right.GetType()) << '|' << cru::ToUtf8(right.GetAddress())
 -       << '|' << cru::ToUtf8(right.GetPhone());
 -  return left;
 -}
 -
 -class Record final {
 -public:
 -  Record();
 -
 -  CRU_DEFAULT_COPY(Record);
 -  CRU_DEFAULT_MOVE(Record);
 -
 -  ~Record() = default;
 -
 -public:
 -  void WriteTo(std::ostream &stream);
 -  void ReadFrom(std::istream &stream);
 -
 -  const std::vector<Book> &GetBooks() const { return books_; }
 -  const std::vector<Vendor> &GetVendors() const { return vendors_; }
 -
 -  // TODO: Implementation
 -  std::optional<Book> FindBookByIsbn(std::u16string_view isbn);
 -
 -  // TODO: Implementation
 -  void RemoveBookByIsbn(std::u16string_view isbn);
 -
 -private:
 -  std::vector<Book> books_;
 -  std::vector<Vendor> vendors_;
 -};
 -
 -void Record::WriteTo(std::ostream &stream) {
 -  stream << books_.size() << ' ' << vendors_.size() << '\n';
 -  for (const auto &book : books_) {
 -    stream << book << '\n';
 -  }
 -  for (const auto &vendor : vendors_) {
 -    stream << vendor << '\n';
 -  }
 -}
 -
 -void Record::ReadFrom(std::istream &stream) {
 -  books_.clear();
 -  vendors_.clear();
 -  int book_count, vendor_count;
 -  stream >> book_count >> vendor_count;
 -  stream >> std::ws;
 -  for (int i = 0; i < book_count; i++) {
 -    Book book;
 -    stream >> book;
 -    books_.push_back(std::move(book));
 -  }
 -  for (int i = 0; i < vendor_count; i++) {
 -    Vendor vendor;
 -    stream >> vendor;
 -    vendors_.push_back(std::move(vendor));
 -  }
 -}
 +  QMainWindow main_window;
 -int main() {
 -  Record record;
 +  QWidget centeral_area;
 +  QVBoxLayout central_area_layout;
 +  centeral_area.setLayout(¢ral_area_layout);
 -  while (true) {
 -    std::wcout << L"1. 查询 2. 添加 0. 退出\n";
 -    int choice = 0;
 -    std::wcin >> choice;
 -    if (choice == 1) {
 -      std::wcout
 -          << L"1. 图书 2. 供应商\n输入数字选择操作,其他任意字符将退出程序。\n";
 -      choice = 0;
 -      std::wcin >> choice;
 -      if (choice == 1) {
 -        std::wcout << L"请输入图书编号:\n";
 -        std::wstring isbn;
 -        std::wcin >> isbn;
 -        auto find_result = record.FindBookByIsbn(ToUtf16View(isbn));
 -        if (find_result) {
 -          PrettyPrint(std::wcout, *find_result);
 -          std::wcout << L"0. 返回主菜单 1. 修改 2. 删除\n";
 -          choice = 0;
 -          std::wcin >> choice;
 -          if (choice == 1) {
 -            // TODO: 
 -          } else if (choice == 2) {
 -            record.RemoveBookByIsbn(ToUtf16View(isbn));
 -            std::wcout << L"删除成功。\n";
 -          }
 -        } else {
 -          std::wcout << L"该书不存在。\n";
 -        }
 -      } else if (choice == 2) {
 +  main_window.setCentralWidget(¢eral_area);
 -      } else {
 -        return 0;
 -      }
 +  QWidget top_bar;
 +  QHBoxLayout top_bar_layout;
 +  top_bar.setLayout(&top_bar_layout);
 +  central_area_layout.addWidget(&top_bar);
 -    } else if (choice == 2) {
 +  QPushButton import_button(QStringLiteral("导入"));
 +  QPushButton export_button(QStringLiteral("导出"));
 +  top_bar_layout.addWidget(&import_button);
 +  top_bar_layout.addWidget(&export_button);
 -    } else {
 -      return 0;
 -    }
 -  }
 +  main_window.show();
 -  return 0;
 +  return application.exec();
  }
  | 
