iostream ableiten -> werden \n gelöscht?



  • Hallo,
    ich bin dabei ne Klasse zu schreiben, die ein externes programm startet (in nem geforkten prozess) und pipes dahin legt. Die Pipes will ich benutzbar machen indem ich die klasse von streambuf ableite und ein iostream derivat daran anbinde... (wenn die klasse fertig ist, will ich sie unter GPL3 veröffentlichen)
    an sich bin ich schon ziemlich weit, aber irgendwie scheinen die daten nicht mehr durch die pipes zu gehen, seit die klasse von streambuf abgeleitet ist...
    also ich schicke einen string in den stream rein, kriege dann aber nicht die erwartete antwort raus...
    ich bin nicht sicher, aber ich glaube, das problem liegt zwischen dem aufruf des << operators und xsputn. wenn ich bla\n\n in den stream schicke, kommt bla\0 bei xsputn an und n ist 3 (ich denke das soll heissen, dass bis s[n] gelesen werden soll - etwas unüblich, aber ok)
    jedenfalls erwartet das externe programm ein \n, bis es antwortet (ich benutze testweise cat, das einfach die eingabe wieder zurückgeben müsste - aber auch mit nem anderen prog funktioniert es nicht...)

    testweise habe ich in der overflow methode mal explizit *_M_out_cur auf \n gesetzt und *(_M_out_cur+1) auf \0 (um sicherzugehen), aber es kam immernoch nicht die erwartete antwort...

    sieht vielleicht jemand einen fehler in den folgenden methoden?

    streamsize exec_streambuf::xsputn(const char* s, streamsize n) {
    	if(_M_out_cur+n <= _M_out_end) { // request can be satisfied
    		memcpy(_M_out_cur, s, sizeof(char_type)*n);
    		_M_out_cur += n+1;
    		return 1;
    	}
    
    	// not enough space - fill rest
    	int availspace = _M_out_end - _M_out_cur;
    	if(availspace > 0) {
    		memcpy(_M_out_cur, s, sizeof(char_type)*availspace);
    		_M_out_cur = _M_out_end;
    	}
    
    	// flush and redo
    	if(overflow(s[availspace]) != traits_type::eof()) {
    		return xsputn(s+availspace, n-availspace);
    	} else
    		return traits_type::eof();
    }
    
    exec_streambuf::int_type exec_streambuf::overflow(int_type c) {
    	*_M_out_cur = '\0'; // flush buffer
    	if(fwrite(_M_out_beg, sizeof(char_type), 1+_M_out_cur-_M_out_beg, PipeWriter) > 0) {
    		fflush(PipeWriter);
    
    		_M_out_cur = _M_out_beg+1; // reset buffer
    		*_M_out_beg = c;
    		return 1;
    	} else {
    		return traits_type::eof();
    	}
    }
    

    ach, es könnte vielleich helfen, den aufruf aus der main zu haben

    execstream P(argv[1]);
    char input[256];
    string output;
    while(true) {
    	cin.getline(&input[0],256);
    	P << input << "\n\n";
    	P.flush();
    	P >> output;
    	cout << output << endl;
    }
    

    wer's mal testen will:
    http://www.algorithman.de/storage/ExecStream.h
    http://www.algorithman.de/storage/test.cpp

    (funktioniert afaik nicht unter windows - weil das afaik den fork nicht unterstützt)
    danke!

    AlgoMan



  • Ansonsten könnte es auch am abholen der Antwort liegen...

    streamsize exec_streambuf::showmanyc() {
    	return _M_in_end - _M_in_cur;
    }
    
    streamsize exec_streambuf::xsgetn(char* s, streamsize n) {
    	// request can be satisfied
    	if(_M_in_cur + n <= _M_in_end) {
    		memcpy(s, _M_in_cur, sizeof(char_type)*n);
    		_M_in_cur += n;
    		return n;
    	}
    
    	// fetch rest from buffer
    	int avail = showmanyc();
    	if(avail > 0) {
    		memcpy(s, _M_in_cur, sizeof(char_type)*avail);
    		_M_in_cur = _M_in_end;
    	}
    
    	// refill buffer and redo
    	if(underflow() != traits_type::eof())
    		return avail+xsgetn(s+avail, n-avail);
    	else
    		return avail;
    }
    
    exec_streambuf::int_type exec_streambuf::underflow() {
    	int read = fread(_M_in_beg, sizeof(char_type), EXECSTREAM_BUFFERSIZE, PipeReader); // is this blocking??
    	if(read <= 0) { // error or eof
    		_M_in_end = _M_in_beg;
    		_M_in_cur = _M_in_beg;
    		return traits_type::eof();
    	}
    
    	// success
    	_M_in_end = _M_in_beg + read;
    	_M_in_cur = _M_in_beg;
    	return *_M_in_beg;
    }
    

Anmelden zum Antworten