2009-10-19 8 views
9

मेरे पास एक अनुरोध क्लाइंट के साथ एक नेटवर्क क्लाइंट है जो std::streambuf* लेता है। इस विधि को boost::iostreams::copy द्वारा कार्यान्वित किया गया है- इसे कस्टम std::streambuf-समर्पित कक्षा में जो नेटवर्क एपीआई को डेटा लिखना है, जो महान काम करता है, को जानता है। इसका मतलब यह है कि मैं इसे किसी फ़ाइल को स्मृति में पढ़ने की आवश्यकता के बिना अनुरोध में स्ट्रीम कर सकता हूं।एक प्रतिलिपि बनाकर std :: स्ट्रिंग से स्ट्रीम?

कुछ मामलों में, जहां डेटा के बड़े ब्लॉक भेजे जाने चाहिए, जो फ़ाइल में नहीं हैं, इसलिए मैंने एक अधिभार शामिल किया जो एक स्ट्रिंग लेता है। स्ट्रीम में सभी नेटवर्क कोड को डुप्लिकेट करने से बचने के लिए, यह स्पष्ट प्रतीत होता है कि मुझे streambuf स्ट्रिंग का प्रतिनिधित्व करना चाहिए और अन्य विधि को कॉल करना चाहिए।

std::istringstream ss(data); 
send(ss.rdbuf()); 

दुर्भाग्य से, istringstream डेटा, जो कुछ मामलों में कई मेगाबाइट है की एक प्रतिलिपि बनाता: एक ही रास्ता मैं यह पता लगाने की यह काम करने के लिए कर सकता है की तरह कुछ था। यह सामान्य मामले में सही मायने रखता है, ज़ाहिर है, अगर आप किसी ऑब्जेक्ट का कॉन्स्ट रेफरेंस देते हैं तो आप यह नहीं मानते कि वह ऑब्जेक्ट उस संदर्भ का उपयोग जारी रख सकता है।

मैं निम्नलिखित के साथ इस के आसपास काम किया:

struct zerocopy_istringbuf 
    : public std::stringbuf 
{ 
    zerocopy_istringbuf(std::string const* s) 
     : std::stringbuf(std::ios::in) 
    { 
     char* p = const_cast<char*>(s->c_str()); 
     setg(p, p, p + s->length()); 
    } 
}; 

... 

send(&zerocopy_istringbuf(data)); 

यह सिर्फ अच्छा काम करने लगता है, लेकिन मुझे आश्चर्य है अगर यह वास्तव में आवश्यक है। std::istringstream पर std::string const * क्यों नहीं ले रहा है? क्या ऐसा करने के लिए इससे अच्छा तरीका है?

उत्तर

4

आपको ये समस्या होने का कारण यह है कि std :: string वास्तव में आप जो कर रहे हैं उसके लिए उपयुक्त नहीं है। कच्चे डेटा के चारों ओर गुजरते समय वेक्टर के चार का उपयोग करना बेहतर विचार है। यदि यह संभव हो, तो मैं वेक्टर :: स्वैप और वैक्टरों के संदर्भों का उपयोग करके वेक्टर का उपयोग करने के लिए सब कुछ बदल दूंगा, ताकि आपकी सभी प्रतिलिपि को खत्म करने के लिए उपयुक्त हो। यदि आपको iostreams/streambuf api पसंद है, या यदि आपको किसी ऐसे स्ट्रीम से निपटना है जो स्ट्रीमबफ लेता है, तो यह आपके स्वयं के स्ट्रीमबफ को बनाने के लिए छोटा होगा जो आपके जैसे वेक्टर का उपयोग करता है। यह प्रभावी रूप से वही काम करेगा जो आप अन्य उत्तरों में सूचीबद्ध मुद्दों के साथ करते हैं, लेकिन आप कक्षा के अनुबंध का उल्लंघन नहीं करेंगे।

अन्यथा, मुझे लगता है कि आपको जो मिला है वह संभवतया हर जगह एक आइटरिंगस्ट्रीम के चारों ओर गुजरने का सबसे अच्छा तरीका है।

+0

एक दिलचस्प विचार है। मौजूदा सेटअप के बारे में मुझे पसंद की जाने वाली चीज़ों में से एक यह है कि मैं 'std :: stringbuf' से प्राप्त करके एक कस्टम इनपुट या आउटपुट स्ट्रीम सेट कर सकता हूं और मुझे केवल एक या दो सरल कार्यों, अंडरफ्लो या' ओवरफ़्लो' 'को ओवरराइड करना होगा और ' सिंक ', बेस क्लास मेरे लिए सभी बफर प्रबंधन को संभालती है। मुझे संदेह है कि 'std :: vector' से चीजों को आधार देने का मतलब होगा कि मुझे काफी अधिक कोड की आवश्यकता होगी। मैं वैसे भी 'स्वैप' का उपयोग करने में सक्षम हो सकता हूं, हालांकि मुझे लगातार संदर्भ में गुजरने के बजाय कॉलर को "छोड़ देना" होगा। –

2

imho, सबसे अच्छा विकल्प में बहिष्कृत वर्ग std :: strstream

+0

धन्यवाद, मुझे इसके बारे में पता नहीं था। एकमात्र समस्या यह है कि यह 'const *' के बजाय 'char *' चाहता है, लेकिन यह काम करने में काफी आसान है। –