Google APIs Client Library for C++
codec.h
Go to the documentation of this file.
00001 /*
00002  * \copyright Copyright 2013 Google Inc. All Rights Reserved.
00003  * \license @{
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  *
00017  * @}
00018  */
00019 
00020 // Author: ewiseblatt@google.com (Eric Wiseblatt)
00021 /*
00022  * @defgroup DataLayerCodec Data Layer - Data Encoder/Decoders
00023  *
00024  * The raw data encoders/decoders are components in the data layer that are
00025  * responsible for transforming data. Typical examples are encoding,
00026  * encryption and compression. Transformations can be performed on entire
00027  * byte sequences or on individual chunks.
00028  */
00029 
00030 #ifndef APISERVING_CLIENTS_CPP_DATA_CODEC_H_
00031 #define APISERVING_CLIENTS_CPP_DATA_CODEC_H_
00032 
00033 #include <string>
00034 using std::string;
00035 
00036 #include "googleapis/client/data/data_reader.h"
00037 #include "googleapis/base/callback.h"
00038 #include "googleapis/base/macros.h"
00039 #include "googleapis/strings/stringpiece.h"
00040 #include "googleapis/util/status.h"
00041 namespace googleapis {
00042 
00043 namespace client {
00044 
00045 /*
00046  * Provides an interface for encoding and decoding data.
00047  * @ingroup DataLayerCodec
00048  *
00049  * This is a pure abstract class. It needs to be subclassed to provide
00050  * specific encodings and decodings, including encryption or compression.
00051  */
00052 class Codec {
00053  public:
00054   /*
00055    * Standard constructor.
00056    */
00057   Codec();
00058 
00059   /*
00060    * Standard destructor.
00061    */
00062   virtual ~Codec();
00063 
00064   /*
00065    * Encodes a string.
00066    *
00067    * @param[in] decoded The unencoded string to encode is treated as binary
00068    *            data, not a null-terminated c-string.
00069    * @param[out] encoded The encoded string should be treated as binary data,
00070    *             not a null-terminated c-string. Use data(), not c_state()
00071    *             to get at the bytes if needed.
00072    * @return ok if the string could be encoded.
00073    *
00074    * @see Decode
00075    */
00076   virtual util::Status Encode(
00077       const StringPiece& decoded, string* encoded);
00078 
00079   /*
00080    * Decodes a string.
00081    *
00082    * @param[in] encoded The encoded string to encode is treated as binary
00083    *            data, not a null-terminated c-string.
00084    * @param[out] unencoded The decoded string should be treated as binary data,
00085    *             not a null-terminated c-string. Use data(), not c_state()
00086    *             to get at the bytes if needed.
00087    * @return ok if the string could be decoded.
00088    *
00089    * @see Encode
00090    */
00091   virtual util::Status Decode(
00092       const StringPiece& encoded, string* unencoded);
00093 
00094   /*
00095    * Creates a reader that encodes all the output of another reader.
00096    *
00097    * The default method returns an InMemory reader using the Decode method
00098    * on the input read into one monolithic string.
00099    *
00100    * Specialized encoder/decoders should override this to encode as the reader
00101    * streams if possible.
00102    *
00103    * @param[in] reader  The caller maintains ownership of reader to encode.
00104    *                    However, they may pass ownership to the deleter.
00105    * @param[in] deleter If not NULL then it will be Run() when the reader is
00106    *            destroyed.
00107    * @param[out] status ok on success, otherwise the reason for error.
00108    * @return ownership of a new reader that will return the decoded data.
00109    *         This will never be null, though may be an InvalidDataReader
00110    *         returning the same status on failure.
00111    *
00112    * @see NewManagedDecodingReader
00113    */
00114   virtual DataReader* NewManagedEncodingReader(
00115       DataReader* reader, Closure* deleter, util::Status* status) = 0;
00116 
00117   /*
00118    * Creates a reader that decodes all the output of another reader.
00119    *
00120    * The default method returns an InMemory reader using the Decode method
00121    * on the input read into one monolithic string.
00122    *
00123    * Specialized decoder/encoders should override this to decode as the reader
00124    * streams if possible.
00125    *
00126    * @param[in] reader  The caller maintains ownership of reader to decode.
00127    *                    However, they may pass ownership to the deleter.
00128    * @param[in] deleter If not NULL then it will be Run() when the reader is
00129    *            destroyed.
00130    * @param[out] status ok on success, otherwise the reason for error.
00131    * @return ownership of a new reader that will return the encoded data.
00132    *         This will never be null, though may be an InvalidDataReader
00133    *         returning the same status on failure.
00134    *
00135    * @see NewManagedEnccodingReader
00136    */
00137   virtual DataReader* NewManagedDecodingReader(
00138       DataReader* reader, Closure* deleter, util::Status* status) = 0;
00139 
00140   /*
00141    * Creates a reader that encodes the output of another reader.
00142    *
00143    * @param[in] reader The caller maintains ownership of the raeder to encode.
00144    * @param[out] status ok on success, otherwise the reason for error.
00145    *
00146    * @see NewManagedEncodingReader
00147    */
00148   DataReader* NewUnmanagedEncodingReader(
00149       DataReader* reader, util::Status* status) {
00150     return NewManagedEncodingReader(reader, NULL, status);
00151   }
00152 
00153   /*
00154    * Creates a reader that decodes the output of another reader.
00155    *
00156    * @param[in] reader The caller maintains ownership of the raeder to decode.
00157    * @param[out] status ok on success, otherwise the reason for error.
00158    *
00159    * @see NewManagedDecodingReader
00160    */
00161   DataReader* NewUnmanagedDecodingReader(
00162       DataReader* reader, util::Status* status) {
00163     return NewManagedDecodingReader(reader, NULL, status);
00164   }
00165 
00166  private:
00167   DISALLOW_COPY_AND_ASSIGN(Codec);
00168 };
00169 
00170 /*
00171  * A factory for creating Codec instances.
00172  * @ingroup DataLayerCodec
00173  *
00174  * This factory must be subclassed for a particualr concrete
00175  * <code>Codec</code>. The subclasses may provide additional configuration
00176  * parameters particular to the encoding/decoding scheme they implement.
00177  *
00178  * @see Codec
00179  */
00180 class CodecFactory {
00181  public:
00182   /*
00183    * Standard constructor.
00184    */
00185   CodecFactory();
00186 
00187   /*
00188    * Standard destructor.
00189    */
00190   virtual ~CodecFactory();
00191 
00192   /*
00193    * The factory method that creates a new instance.
00194    *
00195    * @param[out] status ok on success, otherwise the reason for failure.
00196    * @return Ownership of the new instance is passed back to the caller.
00197    */
00198   virtual Codec* New(util::Status* status) = 0;
00199 
00200  private:
00201   DISALLOW_COPY_AND_ASSIGN(CodecFactory);
00202 };
00203 
00204 /*
00205  * A helper class for implementing CodecReaders.
00206  *
00207  * This class assumes bounded transformation sizes for a given input size.
00208  */
00209 class CodecReader : public DataReader {
00210  public:
00211   /*
00212    * Standard constructor.
00213    *
00214    * @param[in] source The untarnsformed stream the codec is processing.
00215    * @param[in] deleter The deleter if this is to be a managed stream.
00216    * @param[in] chunk_size The size of source data to accumulate for each
00217    *            transform (until the very last one)
00218    * @param[in] buffer_size The size to allocate for transformed data.
00219    * @param[in] encoding Whether this reader is encoding or decoding
00220    *            determines whether we'll EncodeChunk or DecodeChunk.
00221    */
00222   CodecReader(
00223       DataReader* source, Closure* deleter,
00224       int64 chunk_size, int64 buffer_size,
00225       bool encoding);
00226 
00227   /*
00228    * Standard destructor.
00229    */
00230   virtual ~CodecReader();
00231 
00232   /*
00233    * Called when resetting readers (seeking to start)
00234    */
00235   virtual util::Status Init();
00236 
00237  protected:
00238   /*
00239    * Returns whether the reader was constructed for encoding or decoding.
00240    */
00241   bool encoding() const { return encoding_; }
00242 
00243   /*
00244    * Reads from internal transformed buffer, replentishing it as necessary.
00245    *
00246    * This method is compliant with the base DataReader::DoReadToBuffer
00247    * semantics. In particular, results are never non-negative and 0 does
00248    * not have any special meaning with regard to errors or being done.
00249    *
00250    * @param[in] max_bytes Max bytes to copy from buffer.
00251    * @param[in] storage The storage to read into.
00252    * @return Number of bytes read will never be more than the
00253    *         constructed buffer_size, at least for the base class.
00254    */
00255   virtual int64 DoReadToBuffer(int64 max_bytes, char* storage);
00256 
00257   /*
00258    * Implements seeking through the transformed stream.
00259    *
00260    * This method is compliant with the base DataReader::DoSetOffset semantics.
00261    */
00262   virtual int64 DoSetOffset(int64 to_offset);
00263 
00264   /*
00265    * Hook for codecs to encode a chunk.
00266    *
00267    * @param[in] from The raw chunk from the source stream.
00268    * @param[in] final True if this is the final chunk.
00269    * @param[in] to The target buffer must be allocated big enough.
00270    * @param[in,out] to_len The size of the 'to' buffer on input.
00271    *                       The amount of data written into 'to' on output.
00272    */
00273   virtual util::Status EncodeChunk(
00274       const StringPiece& from, bool final, char* to, int64* to_len) = 0;
00275 
00276   /*
00277    * Hook for codecs to decode a chunk.
00278    *
00279    * @param[in] from The raw chunk from the source stream.
00280    * @param[in] final True if this is the final chunk.
00281    * @param[in] to The target buffer must be allocated big enough.
00282    * @param[in,out] to_len The size of the 'to' buffer on input.
00283    *                       The amount of data written into 'to' on output.
00284    */
00285   virtual util::Status DecodeChunk(
00286       const StringPiece& from, bool final, char* to, int64* to_len) = 0;
00287 
00288  private:
00289   struct Buffer;
00290   DataReader* source_;
00291   int64 chunk_size_;
00292   scoped_ptr<char[]> chunk_;
00293   scoped_ptr<Buffer> buffer_;  // Waiting to read
00294   bool encoding_;
00295   bool read_final_;
00296 
00297   /*
00298    * Returns how much buffered data is available.
00299    */
00300   int MaybeFetchNextChunk();
00301   DISALLOW_COPY_AND_ASSIGN(CodecReader);
00302 };
00303 
00304 }  // namespace client
00305 
00306 } // namespace googleapis
00307 #endif  // APISERVING_CLIENTS_CPP_DATA_CODEC_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines