1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 #ifndef _nsMsgLineBuffer_H 6 #define _nsMsgLineBuffer_H 7 8 #include "msgCore.h" // precompiled header... 9 10 // I can't believe I have to have this stupid class, but I can't find 11 // anything suitable (nsStrImpl might be, when it's done). nsIByteBuffer 12 // would do, if I had a stream for input, which I don't. 13 14 class nsByteArray { 15 public: 16 nsByteArray(); 17 virtual ~nsByteArray(); GetSize()18 uint32_t GetSize() { return m_bufferSize; } GetBufferPos()19 uint32_t GetBufferPos() { return m_bufferPos; } 20 nsresult GrowBuffer(uint32_t desired_size, uint32_t quantum = 1024); 21 nsresult AppendString(const char* string); 22 nsresult AppendBuffer(const char* buffer, uint32_t length); ResetWritePos()23 void ResetWritePos() { m_bufferPos = 0; } GetBuffer()24 char* GetBuffer() { return m_buffer; } 25 26 protected: 27 char* m_buffer; 28 uint32_t m_bufferSize; 29 uint32_t 30 m_bufferPos; // write Pos in m_buffer - where the next byte should go. 31 }; 32 33 /** 34 * nsMsgLineBuffer breaks up incoming data into lines. 35 * It accepts CRLF, CR or LF line endings. 36 * 37 * Data is fed in via BufferInput(). The virtual HandleLine() will be 38 * invoked for each line. The data passed to HandleLine() is verbatim, 39 * and will include whatever line endings were in the source data. 40 * 41 * Flush() should be called when the data is exhausted, to handle any 42 * leftover bytes in the buffer (e.g. if the data doesn't end with an EOL). 43 */ 44 class nsMsgLineBuffer : private nsByteArray { 45 public: 46 nsMsgLineBuffer(); 47 virtual ~nsMsgLineBuffer(); 48 nsresult BufferInput(const char* net_buffer, int32_t net_buffer_size); 49 50 /** 51 * HandleLine should be implemented by derived classes, to handle a line. 52 * The line will have whatever end-of-line characters were present in the 53 * source data (potentially none, if the data ends mid-line). 54 */ 55 virtual nsresult HandleLine(const char* line, uint32_t line_length) = 0; 56 57 /** 58 * Flush processes any unprocessed data currently in the buffer. Should 59 * be called when the source data is exhausted. 60 */ 61 nsresult Flush(); 62 }; 63 64 // I'm adding this utility class here for lack of a better place. This utility 65 // class is similar to nsMsgLineBuffer except it works from an input stream. It 66 // is geared towards efficiently parsing new lines out of a stream by storing 67 // read but unprocessed bytes in a buffer. I envision the primary use of this to 68 // be our mail protocols such as imap, news and pop which need to process line 69 // by line data being returned in the form of a proxied stream from the server. 70 71 class nsIInputStream; 72 73 class nsMsgLineStreamBuffer { 74 public: 75 NS_INLINE_DECL_REFCOUNTING(nsMsgLineStreamBuffer) 76 77 // aBufferSize -- size of the buffer you want us to use for buffering stream 78 // data 79 // aEndOfLinetoken -- The delimiter string to be used for determining the end 80 // of line. This allows us to parse platform specific end of 81 // line endings by making it a parameter. 82 // aAllocateNewLines -- true if you want calls to ReadNextLine to allocate new 83 // memory for the line. 84 // if false, the char * returned is just a ptr into the buffer. 85 // Subsequent calls to ReadNextLine will alter the data so your 86 // ptr only has a life time of a per call. 87 // aEatCRLFs -- true if you don't want to see the CRLFs on the lines 88 // returned by ReadNextLine. 89 // false if you do want to see them. 90 // aLineToken -- Specify the line token to look for, by default is LF ('\n') 91 // which cover as well CRLF. If lines are terminated with a CR 92 // only, you need to set aLineToken to CR ('\r') 93 nsMsgLineStreamBuffer( 94 uint32_t aBufferSize, bool aAllocateNewLines, bool aEatCRLFs = true, 95 char aLineToken = '\n'); // specify the size of the buffer you want the 96 // class to use.... 97 98 // Caller must free the line returned using PR_Free 99 // aEndOfLinetoken -- delimiter used to denote the end of a line. 100 // aNumBytesInLine -- The number of bytes in the line returned 101 // aPauseForMoreData -- There is not enough data in the stream to make a line 102 // at this time... 103 char* ReadNextLine(nsIInputStream* aInputStream, uint32_t& aNumBytesInLine, 104 bool& aPauseForMoreData, nsresult* rv = nullptr, 105 bool addLineTerminator = false); 106 nsresult GrowBuffer(uint32_t desiredSize); 107 void ClearBuffer(); 108 bool NextLineAvailable(); 109 110 private: 111 virtual ~nsMsgLineStreamBuffer(); 112 113 protected: 114 bool m_eatCRLFs; 115 bool m_allocateNewLines; 116 char* m_dataBuffer; 117 uint32_t m_dataBufferSize; 118 uint32_t m_startPos; 119 uint32_t m_numBytesInBuffer; 120 char m_lineToken; 121 }; 122 123 #endif 124