Listing 2: PerlStream.cc
bool PerlValue::isInt() const // line 1 { return SvIOK(value); } int PerlValue::Int() const // line 4 { if (SvIOK(value) || SvNOK(value) || SvPOK(value)) { return SvIV(value); } else if (exception_flags & PerlStream::eBadCast) { string errstr = string("Casting from a Perl ") + typeStr() + " to an int"; throw PerlBadCast(errstr); } return 0; // Not a valid value, so make it 0 } // ... Lots of other PerlValue functions PerlStreamBuf::PerlStreamBuf(unsigned int flags) : streambuf(), mContext(eScalar), mExceptionFlags(flags) {} PerlStreamBuf::~PerlStreamBuf() { freePerlValues(); } int PerlStreamBuf::overflow(int c) // line 23 { mBuffer += static_cast<char>(c); return c; } streamsize PerlStreamBuf::xsputn(const char* s, streamsize n) // line 26 { mBuffer.append(s, n); return n; } bool PerlStreamBuf::execute() // line 29 { string err; dSP; I32 ax; freePerlValues(); // Free values from the previous eval if (mBuffer.length() == 0) return true; ENTER; SAVETMPS; PUSHMARK(sp); // Create the string we want to send to Perl, and send it sv_setsv(ERRSV, &PL_sv_undef); PUTBACK; SV *code = sv_2mortal(newSVpv(mBuffer.data(),mBuffer.size())); I32 nstackvals = perl_eval_sv(code, mContext|G_KEEPERR); // Now get the response SPAGAIN; if (SvTRUE(ERRSV)) { err = "Eval failed: " + mBuffer + ": " + SvPV(ERRSV, PL_na); for (I32 i = 0; i < nstackvals; ++i) POPs; } else { // Get the return values from the Perl stack. mRtnVals.resize(nstackvals); for (I32 i = nstackvals-1; i >= 0; --i) { SV* val = POPs; SvREFCNT_inc(val); mRtnVals[i] = val; } } PUTBACK; FREETMPS; LEAVE; // Initialize things for the next go around mBuffer.erase(); mContext = eScalar; if (!errstr.empty()) { if (mExceptionFlags & PerlStream::eEvalFail) throw PerlEvalError(err); return false; } else { return true; } } void PerlStreamBuf::freePerlValues() { vector<SV*>::iterator p; for (p = mRtnVals.begin(); p != mRtnVals.end(); ++p) if (*p) { SvREFCNT_dec(*p); *p = 0; } mRtnVals.clear(); } End of Listing