// Generated by gtkmmproc -- DO NOT MODIFY! #include #include // -*- c++ -*- /* $Id$ */ /* Copyright (C) 2002 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include namespace { // Glib::IOChannel reference counting issues: // // Normally, you'd expect that the C++ object stays around as long as the // C instance does. Also Glib::wrap() usually returns always the same C++ // wrapper object for a single C instance. // // Unfortunately it isn't possible to implement these features if we didn't // create the underlying GIOChannel. That is, when wrapping existing // GIOChannel instances such as returned by e.g. g_io_channel_unix_new() or // g_io_channel_new_file(). Neither is there a way to hook up a wrapper // object in an existing GIOChannel, nor exists any destroy notification. // // So that means: If the IOChannel is implemented in C++ -- that is, our // GlibmmIOChannel backend is used -- we use the GIOChannel reference // counting mechanism. If the IOChannel backend is unknown, then the // wrapper instance holds always exactly one reference to the GIOChannel. // The wrapper object itself is then managed via our own refcounting // mechanism. To do that a utility class ForeignIOChannel is introduced to // override reference() and unreference(). class ForeignIOChannel : public Glib::IOChannel { public: ForeignIOChannel(GIOChannel* gobject, bool take_copy) : Glib::IOChannel(gobject, take_copy), ref_count_(0) {} virtual void reference() const; virtual void unreference() const; private: mutable int ref_count_; }; void ForeignIOChannel::reference() const { ++ref_count_; } void ForeignIOChannel::unreference() const { if (!(--ref_count_)) delete this; } } // anonymous namespace namespace Glib { class GlibmmIOChannel { public: GIOChannel base; Glib::IOChannel* wrapper; static const GIOFuncs vfunc_table; static GIOStatus io_read(GIOChannel* channel, char* buf, gsize count, gsize* bytes_read, GError** err); static GIOStatus io_write(GIOChannel* channel, const char* buf, gsize count, gsize* bytes_written, GError** err); static GIOStatus io_seek (GIOChannel* channel, gint64 offset, GSeekType type, GError** err); static GIOStatus io_close(GIOChannel* channel, GError** err); static GSource* io_create_watch(GIOChannel* channel, GIOCondition condition); static void io_free(GIOChannel* channel); static GIOStatus io_set_flags(GIOChannel* channel, GIOFlags flags, GError** err); static GIOFlags io_get_flags(GIOChannel* channel); }; // static const GIOFuncs GlibmmIOChannel::vfunc_table = { &GlibmmIOChannel::io_read, &GlibmmIOChannel::io_write, &GlibmmIOChannel::io_seek, &GlibmmIOChannel::io_close, &GlibmmIOChannel::io_create_watch, &GlibmmIOChannel::io_free, &GlibmmIOChannel::io_set_flags, &GlibmmIOChannel::io_get_flags, }; /**** GLib::IOChannel ******************************************************/ /* Construct a custom C++-implemented IOChannel. GlibmmIOChannel is an * extended GIOChannel struct which allows us to hook up a pointer to this * persistent wrapper instance. */ IOChannel::IOChannel() : gobject_ (static_cast(g_malloc(sizeof(GlibmmIOChannel)))) { g_io_channel_init(gobject_); gobject_->funcs = const_cast(&GlibmmIOChannel::vfunc_table); reinterpret_cast(gobject_)->wrapper = this; } /* Construct an IOChannel wrapper for an already created GIOChannel. * See the comment at the top of this file for an explanation of the * problems with this approach. */ IOChannel::IOChannel(GIOChannel* gobject, bool take_copy) : gobject_ (gobject) { // This ctor should never be called for GlibmmIOChannel instances. g_assert(gobject != 0); g_assert(gobject->funcs != &GlibmmIOChannel::vfunc_table); if(take_copy) g_io_channel_ref(gobject_); } IOChannel::~IOChannel() { if(gobject_) { // Check whether this IOChannel is implemented in C++, i.e. whether it // uses our GlibmmIOChannel forwarding backend. Normally, this will never // be true because the wrapper should only be deleted in the io_free() // callback, which clears gobject_ before deleting. But in case the ctor // of a derived class threw an exception the GIOChannel must be destroyed // prematurely. // if(gobject_->funcs == &GlibmmIOChannel::vfunc_table) { // Disconnect the wrapper object so that it won't be deleted twice. reinterpret_cast(gobject_)->wrapper = 0; } GIOChannel *const tmp_gobject = gobject_; gobject_ = 0; g_io_channel_unref(tmp_gobject); } } Glib::RefPtr IOChannel::create_from_file(const std::string& filename, const std::string& mode) { GError* error = 0; GIOChannel *const channel = g_io_channel_new_file(filename.c_str(), mode.c_str(), &error); if(error) Glib::Error::throw_exception(error); return Glib::wrap(channel, false); } Glib::RefPtr IOChannel::create_from_fd(int fd) { return Glib::wrap(g_io_channel_unix_new(fd), false); } #ifdef G_OS_WIN32 Glib::RefPtr IOChannel::create_from_win32_fd(int fd) { return Glib::wrap(g_io_channel_win32_new_fd(fd), false); } Glib::RefPtr IOChannel::create_from_win32_socket(int socket) { return Glib::wrap(g_io_channel_win32_new_socket(socket), false); } #endif /* G_OS_WIN32 */ IOStatus IOChannel::write(const Glib::ustring& str) { gsize bytes_written = 0; return write(str.data(), str.bytes(), bytes_written); } IOStatus IOChannel::read_line(Glib::ustring& line) { Glib::ScopedPtr buf; GError* error = 0; gsize bytes = 0; const GIOStatus status = g_io_channel_read_line(gobj(), buf.addr(), &bytes, 0, &error); if(error) Glib::Error::throw_exception(error); if(buf.get()) line.assign(buf.get(), buf.get() + bytes); else line.erase(); return (IOStatus) status; } IOStatus IOChannel::read_to_end(Glib::ustring& str) { Glib::ScopedPtr buf; GError* error = 0; gsize bytes = 0; const GIOStatus status = g_io_channel_read_to_end(gobj(), buf.addr(), &bytes, &error); if(error) Glib::Error::throw_exception(error); if(buf.get()) str.assign(buf.get(), buf.get() + bytes); else str.erase(); return (IOStatus) status; } IOStatus IOChannel::read(Glib::ustring& str, gsize count) { Glib::ScopedPtr buf (g_new(char, count)); GError* error = 0; gsize bytes = 0; const GIOStatus status = g_io_channel_read_chars(gobj(), buf.get(), count, &bytes, &error); if(error) Glib::Error::throw_exception(error); if(buf.get()) str.assign(buf.get(), buf.get() + bytes); else str.erase(); return (IOStatus) status; } IOStatus IOChannel::set_encoding(const std::string& encoding) { GError* error = 0; const GIOStatus status = g_io_channel_set_encoding( gobj(), (encoding.empty()) ? 0 : encoding.c_str(), &error); if(error) Glib::Error::throw_exception(error); return (IOStatus) status; } std::string IOChannel::get_encoding() const { const char *const encoding = g_io_channel_get_encoding(gobject_); return (encoding) ? std::string(encoding) : std::string(); } void IOChannel::set_line_term(const std::string& term) { if(term.empty()) g_io_channel_set_line_term(gobj(), 0, 0); else g_io_channel_set_line_term(gobj(), term.data(), term.size()); } std::string IOChannel::get_line_term() const { int len = 0; const char *const term = g_io_channel_get_line_term(gobject_, &len); return (term) ? std::string(term, len) : std::string(); } Glib::RefPtr IOChannel::create_watch(IOCondition condition) { // The corresponding unreference() takes place in the dtor // of the Glib::RefPtr object below. reference(); return IOSource::create(Glib::RefPtr(this), condition); } IOStatus IOChannel::read_vfunc(char*, gsize, gsize&) { g_assert_not_reached(); return IO_STATUS_ERROR; } IOStatus IOChannel::write_vfunc(const char*, gsize, gsize&) { g_assert_not_reached(); return IO_STATUS_ERROR; } IOStatus IOChannel::seek_vfunc(gint64, SeekType) { g_assert_not_reached(); return IO_STATUS_ERROR; } IOStatus IOChannel::close_vfunc() { g_assert_not_reached(); return IO_STATUS_ERROR; } Glib::RefPtr IOChannel::create_watch_vfunc(IOCondition) { g_assert_not_reached(); return Glib::RefPtr(); } IOStatus IOChannel::set_flags_vfunc(IOFlags) { g_assert_not_reached(); return IO_STATUS_ERROR; } IOFlags IOChannel::get_flags_vfunc() { g_assert_not_reached(); return IOFlags(0); } void IOChannel::reference() const { g_io_channel_ref(gobject_); } void IOChannel::unreference() const { g_io_channel_unref(gobject_); } Glib::RefPtr wrap(GIOChannel* gobject, bool take_copy) { IOChannel* cpp_object = 0; if(gobject) { if(gobject->funcs == &GlibmmIOChannel::vfunc_table) { cpp_object = reinterpret_cast(gobject)->wrapper; if(take_copy && cpp_object) cpp_object->reference(); } else { cpp_object = new ForeignIOChannel(gobject, take_copy); cpp_object->reference(); // the refcount is initially 0 } } return Glib::RefPtr(cpp_object); } /**** Glib::GlibmmIOChannel ************************************************/ // static GIOStatus GlibmmIOChannel::io_read(GIOChannel* channel, char* buf, gsize count, gsize* bytes_read, GError** err) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { return (GIOStatus) wrapper->read_vfunc(buf, count, *bytes_read); } catch(Glib::Error& error) { error.propagate(err); } catch(...) { Glib::exception_handlers_invoke(); } return G_IO_STATUS_ERROR; } // static GIOStatus GlibmmIOChannel::io_write(GIOChannel* channel, const char* buf, gsize count, gsize* bytes_written, GError** err) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { return (GIOStatus) wrapper->write_vfunc(buf, count, *bytes_written); } catch(Glib::Error& error) { error.propagate(err); } catch(...) { Glib::exception_handlers_invoke(); } return G_IO_STATUS_ERROR; } // static GIOStatus GlibmmIOChannel::io_seek(GIOChannel* channel, gint64 offset, GSeekType type, GError** err) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { return (GIOStatus) wrapper->seek_vfunc(offset, (SeekType) type); } catch(Glib::Error& error) { error.propagate(err); } catch(...) { Glib::exception_handlers_invoke(); } return G_IO_STATUS_ERROR; } // static GIOStatus GlibmmIOChannel::io_close(GIOChannel* channel, GError** err) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { return (GIOStatus) wrapper->close_vfunc(); } catch(Glib::Error& error) { error.propagate(err); } catch(...) { Glib::exception_handlers_invoke(); } return G_IO_STATUS_ERROR; } // static GSource* GlibmmIOChannel::io_create_watch(GIOChannel* channel, GIOCondition condition) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { const Glib::RefPtr source = wrapper->create_watch_vfunc((IOCondition) condition); return (source) ? source->gobj_copy() : 0; } catch(...) { Glib::exception_handlers_invoke(); } return 0; } // static void GlibmmIOChannel::io_free(GIOChannel* channel) { if(IOChannel *const wrapper = reinterpret_cast(channel)->wrapper) { wrapper->gobject_ = 0; delete wrapper; } g_free(channel); } // static GIOStatus GlibmmIOChannel::io_set_flags(GIOChannel* channel, GIOFlags flags, GError** err) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { return (GIOStatus) wrapper->set_flags_vfunc((IOFlags) flags); } catch(Glib::Error& error) { error.propagate(err); } catch(...) { Glib::exception_handlers_invoke(); } return G_IO_STATUS_ERROR; } // static GIOFlags GlibmmIOChannel::io_get_flags(GIOChannel* channel) { IOChannel *const wrapper = reinterpret_cast(channel)->wrapper; try { return (GIOFlags) wrapper->get_flags_vfunc(); } catch(...) { Glib::exception_handlers_invoke(); } return GIOFlags(0); } } // namespace Glib namespace { } // anonymous namespace Glib::IOChannelError::IOChannelError(Glib::IOChannelError::Code error_code, const Glib::ustring& error_message) : Glib::Error (G_IO_CHANNEL_ERROR, error_code, error_message) {} Glib::IOChannelError::IOChannelError(GError* gobject) : Glib::Error (gobject) {} Glib::IOChannelError::Code Glib::IOChannelError::code() const { return static_cast(Glib::Error::code()); } void Glib::IOChannelError::throw_func(GError* gobject) { throw Glib::IOChannelError(gobject); } namespace Glib { IOStatus IOChannel::read(gunichar& unichar) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_read_unichar(gobj(), &(unichar), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } IOStatus IOChannel::read(char* buf, gsize count, gsize& bytes_read) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_read_chars(gobj(), buf, count, &(bytes_read), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } IOStatus IOChannel::write(const char* buf, gssize count, gsize& bytes_written) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_write_chars(gobj(), buf, count, &(bytes_written), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } IOStatus IOChannel::write(gunichar unichar) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_write_unichar(gobj(), unichar, &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } IOStatus IOChannel::seek(gint64 offset, SeekType type) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_seek_position(gobj(), offset, ((GSeekType)(type)), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } IOStatus IOChannel::flush() { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_flush(gobj(), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } IOStatus IOChannel::close(bool flush) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_shutdown(gobj(), static_cast(flush), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } gsize IOChannel::get_buffer_size() const { return g_io_channel_get_buffer_size(const_cast(gobj())); } void IOChannel::set_buffer_size(gsize size) { g_io_channel_set_buffer_size(gobj(), size); } IOFlags IOChannel::get_flags() const { return ((IOFlags)(g_io_channel_get_flags(const_cast(gobj())))); } IOStatus IOChannel::set_flags(IOFlags flags) { GError *error = 0; IOStatus retvalue = ((IOStatus)(g_io_channel_set_flags(gobj(), ((GIOFlags)(flags)), &(error)))); if(error) ::Glib::Error::throw_exception(error); return retvalue; } void IOChannel::set_buffered(bool buffered) { g_io_channel_set_buffered(gobj(), static_cast(buffered)); } bool IOChannel::get_buffered() const { return g_io_channel_get_buffered(const_cast(gobj())); } IOCondition IOChannel::get_buffer_condition() const { return ((IOCondition)(g_io_channel_get_buffer_condition(const_cast(gobj())))); } bool IOChannel::get_close_on_unref() const { return g_io_channel_get_close_on_unref(const_cast(gobj())); } void IOChannel::set_close_on_unref(bool do_close) { g_io_channel_set_close_on_unref(gobj(), static_cast(do_close)); } } // namespace Glib