#pragma once
#include <xs/Sv.h>
// remove OpenBSD pollution macro
#undef fileno
namespace xs {
using xs::my_perl;
struct Io : Sv {
static Io noinc (SV* val) { return Io(val, NONE); }
static Io noinc (IO* val) { return Io(val, NONE); }
Io (std::nullptr_t = nullptr) {}
Io (SV* sv, bool policy = INCREMENT) : Sv(sv, policy) { _validate(); }
Io (GV* sv, bool policy = INCREMENT) : Sv(sv, policy) { _validate(); }
Io (IO* sv, bool policy = INCREMENT) : Sv(sv, policy) {}
Io (const Io& oth) : Sv(oth) {}
Io (Io&& oth) : Sv(std::move(oth)) {}
Io (const Sv& oth) : Sv(oth) { _validate(); }
Io (Sv&& oth) : Sv(std::move(oth)) { _validate(); }
Io (const Simple&) = delete;
Io (const Array&) = delete;
Io (const Hash&) = delete;
Io (const Sub&) = delete;
Io& operator= (SV* val) { Sv::operator=(val); _validate(); return *this; }
Io& operator= (GV* val) { Sv::operator=(val); _validate(); return *this; }
Io& operator= (IO* val) { Sv::operator=(val); return *this; }
Io& operator= (const Io& oth) { Sv::operator=(oth); return *this; }
Io& operator= (Io&& oth) { Sv::operator=(std::move(oth)); return *this; }
Io& operator= (const Sv& oth) { return operator=(oth.get()); }
Io& operator= (Sv&& oth) { Sv::operator=(std::move(oth)); _validate(); return *this; }
Io& operator= (const Simple&) = delete;
Io& operator= (const Array&) = delete;
Io& operator= (const Hash&) = delete;
Io& operator= (const Sub&) = delete;
void set (SV* val) { Sv::operator=(val); }
operator AV* () const = delete;
operator HV* () const = delete;
operator CV* () const = delete;
operator GV* () const = delete;
operator IO* () const { return (IO*)sv; }
IO* operator-> () const { return (IO*)sv; }
template <typename T = SV> panda::enable_if_one_of_t<T,SV,IO>* get () const { return (T*)sv; }
int fileno () const { return PerlIO_fileno(ifp()); }
PerlIO* ifp () const { return IoIFP(sv); }
PerlIO* ofp () const { return IoOFP(sv); }
char iotype () const { return IoTYPE(sv); }
private:
void _validate ();
};
}