• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • CPACK
    • Home
    • List packs
    • Submit pack
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
    • SWISH Prolog shell
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

1.6.8 Blobs
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog
          • Overview
            • Blobs
              • A review of C++ features used by the API
              • How to define a blob using C++
              • The life of a PlBlob
              • C++ exceptions and blobs
              • Sample PlBlob code (connection to database)
              • Discussion of the sample PlBlob code
              • Sample PlBlob code (wrapping a pointer)
              • Discussion of the sample PlBlob code (wrapping a pointer)
              • Identifying blobs by atoms

1.6.8.7 Sample PlBlob code (wrapping a pointer)

struct MyFileBlob;

static PL_blob_t my_file_blob = PL_BLOB_DEFINITION(MyFileBlob, "my_file_blob");

static const PlOptionsFlag<int>
MyFileBlob_options("MyFileBlob-options",
                   { {"absolute", PL_FILE_ABSOLUTE},
                     {"ospath",   PL_FILE_OSPATH},
                     {"search",   PL_FILE_SEARCH},
                     {"exist",    PL_FILE_EXIST},
                     {"read",     PL_FILE_READ},
                     {"write",    PL_FILE_WRITE},
                     {"execute",  PL_FILE_EXECUTE},
                     {"noerrors", PL_FILE_NOERRORS} });

struct MyFileBlob : public PlBlob
{ std::FILE* file_;

  std::string mode_;
  int flags_;
  std::string filename_;
  std::vector<char> buffer_; // used by read(), to avoid re-allocation

  explicit MyFileBlob()
    : PlBlob(&my_file_blob) { }

  explicit MyFileBlob(PlTerm filename, PlTerm mode, PlTerm flags)
    : PlBlob(&my_file_blob),
      mode_(mode.as_string())
  { flags_ = MyFileBlob_options.lookup_list(flags);
    filename_ = filename.get_file_name(flags_);
    file_ = fopen(filename_.c_str(), mode_.c_str());
    if ( !file_ ) // TODO: get error code (might not be existence error)
      throw PlExistenceError("my_file_blob_open", PlTerm_string(filename_));
    // for debugging:
    //   PlTerm_string(filename.as_string() + "\" => \"" +
    //                 filename_ + "\", \"" + mode_ +
    //                 ", flags=" + MyFileBlob_options.as_string(flags_) + "\")")
  }

  PL_BLOB_SIZE

  std::string read(size_t count)
  { assert(sizeof buffer_[0] == sizeof (char));
    assert(sizeof (char) == 1);

    buffer_.reserve(count);
    return std::string(buffer_.data(),
                       std::fread(buffer_.data(), sizeof buffer_[0], count, file_));
  }

  bool eof() const
  { return std::feof(file_);
  }

  bool error() const
  { return std::ferror(file_);
  }

  virtual ~MyFileBlob() noexcept
  { if ( !close() )
      // Can't use PL_warning()
      Sdprintf("***ERROR: Close MyFileBlob failed: (%s)\n", filename_.c_str());
  }

  bool close() noexcept
  { if ( !file_ )
      return true;
    int rc = std::fclose(file_);
    file_ = nullptr;
    return rc == 0;
  }

  PlException MyFileBlobError(const std::string error) const
  { return PlGeneralError(PlCompound(error, PlTermv(symbol_term())));
  }

  int compare_fields(const PlBlob* _b_data) const override
  { // dynamic_cast is safer than static_cast, but slower (see documentation)
    // It's used here for testing (the documentation has static_cast)
    auto b_data = dynamic_cast<const MyFileBlob*>(_b_data);
    return filename_.compare(b_data->filename_);
  }

  bool write_fields(IOSTREAM *s, int flags) const override
  { PlStream strm(s);
    strm.printf(",");
    return write_fields_only(strm);
  }

  bool write_fields_only(PlStream& strm) const
  { // For debugging:
    // strm.printf("%s mode=%s flags=%s", filename_.c_str(), mode_.c_str(),
    //             MyFileBlob_options.as_string(flags_).c_str());
    strm.printf("%s", filename_.c_str());
    if ( !file_ )
      strm.printf("-CLOSED");
    return true;
  }

  bool portray(PlStream& strm) const
  { strm.printf("MyFileBlob(");
    write_fields_only(strm);
    strm.printf(")");
    return true;
  }
};

PREDICATE(my_file_open, 4)
{ auto ref = std::unique_ptr<PlBlob>(new MyFileBlob(A2, A3, A4));
  return A1.unify_blob(&ref);
}

PREDICATE(my_file_close, 1)
{ auto ref = PlBlobV<MyFileBlob>::cast_ex(A1, my_file_blob);
  if ( !ref->close() ) // TODO: get the error code
    throw ref->MyFileBlobError("my_file_blob_close_error");
  return true;
}

ClioPatria (version V3.1.1-51-ga0b30a5)