GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

GATMemoryStream.c

Go to the documentation of this file.
00001 /** @file GATMemoryStream.c
00002  *  Source file for the GATMemoryStream class.
00003  *
00004  *  @date Wed Oct 29 2003
00005  *
00006  *  @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATMemoryStream.c,v 1.8 2004/04/02 12:31:58 hartmutkaiser Exp $
00007  *
00008  *  Copyright (C) Hartmut Kaiser
00009  *  This file is part of the GAT Engine.
00010  *  Contributed by Hartmut Kaiser <hartmutkaiser [at] t-online [dot] de>.
00011  *
00012  *  Use, modification and distribution is subject to the Gridlab Software
00013  *  License. (See accompanying file GLlicense.txt or copy at
00014  *  http://www.gridlab.org/GLlicense.txt)
00015  */
00016  
00017  static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATMemoryStream.c,v 1.8 2004/04/02 12:31:58 hartmutkaiser Exp $";
00018  
00019 /* System Header objects */
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 /* GAT Header objects */
00024 #include "GATInternal.h"
00025 #include "GATErrors.h"
00026 #include "GATType.h"
00027 #include "GATMemoryStream.h"
00028 
00029 /* define the vtable types */
00030 GATOBJECT_DEFINE_VTABLE(GATMemoryStream);
00031 GATSTREAMABLE_DEFINE_VTABLE(GATMemoryStream);
00032 
00033 /* define the converters to/from GATObject */
00034 GATOBJECT_DEFINE_CONVERTERS(GATMemoryStream)
00035 
00036 /* Macros */
00037 #define GATMEMORYSTREAM_BUFFERSIZE_INCREMENT 512
00038 
00039 /* Structures, unions and enums */
00040 struct GATMemoryStream_S {
00041   GATMemoryStream_vtable *GATObject__vtable;
00042   GATMemoryStream_IStreamable_vtable *GATStreamable__vtable;
00043   
00044   int8_t *buffer;
00045   GATuint32 max_size;
00046   GATuint32 used_size;
00047 };
00048 
00049 /* Static function prototypes */
00050 
00051 /* object scope variables */
00052 GATMemoryStream_vtable GATMemoryStream__vtable = {
00053   GATMemoryStream_GetType,
00054   GATMemoryStream_Destroy,
00055   GATMemoryStream_Equals,
00056   GATMemoryStream_Clone,
00057   GATMemoryStream_GetInterface,
00058   NULL
00059 };
00060 
00061 GATMemoryStream_IStreamable_vtable GATMemoryStream_IStreamable__vtable =
00062 {
00063   GATMemoryStream_Read,
00064   GATMemoryStream_Write,
00065   GATMemoryStream_Seek,
00066   GATMemoryStream_Close
00067 };
00068 
00069 /* External functions */
00070 
00071 /** GATMemoryStream_Create
00072  *  @brief Create a new GATMemoryStream object
00073  *
00074  *  The function @c GATMemoryStream_Create creates a new 
00075  *  GATMemoryStream object
00076  *
00077  *  @return Returns a handle to the newly created GATMemoryStream object.
00078  *        Returns 0 (zero) if an error occurs.
00079  */
00080 GATMemoryStream 
00081 GATMemoryStream_Create(void *initial_buffer, GATuint32 initial_size,
00082   GATBool takeover_ownership)
00083 {
00084   GATResult err_code = GAT_MEMORYFAILURE;
00085   GATMemoryStream retval = (GATMemoryStream) malloc(
00086     sizeof(struct GATMemoryStream_S));
00087       
00088   if (NULL != retval)
00089   {
00090     memset(retval, 0, sizeof(struct GATMemoryStream_S));
00091     retval->GATObject__vtable = &GATMemoryStream__vtable;
00092     retval->GATStreamable__vtable = &GATMemoryStream_IStreamable__vtable;
00093     if (takeover_ownership)
00094     {
00095       /* take over the ownership of the supplied buffer */
00096       retval->buffer = (int8_t *)initial_buffer;
00097       retval->max_size = initial_size;
00098       err_code = GAT_SUCCESS;
00099     }
00100     else
00101     {
00102       GATuint32 size = (NULL != initial_buffer) ? initial_size : 0;
00103       
00104       size += GATMEMORYSTREAM_BUFFERSIZE_INCREMENT;
00105       retval->buffer = (int8_t *)malloc(size);
00106       if (NULL == retval->buffer)
00107       {
00108         err_code = GAT_MEMORYFAILURE;
00109       }
00110       else
00111       {
00112         retval->max_size = size;
00113         if (NULL != initial_buffer)
00114         {
00115           memcpy(retval->buffer, initial_buffer, initial_size);
00116         }
00117         err_code = GAT_SUCCESS;
00118       }
00119     }
00120   }
00121   
00122   /* error handling */
00123   if (GAT_SUCCESS != err_code)
00124   {
00125     /* FIXME: GATStatus(err_code) */
00126     if (NULL != retval)
00127     {
00128       GATMemoryStream_Destroy(&retval);
00129     }
00130   }
00131   return retval;
00132 }
00133 
00134 /** void GATMemoryStream_Destroy(GATMemoryStream *resource)
00135  *
00136  *  The function GATMemoryStream_Destroy is the destructor used to
00137  *  free all the memory allocated by an GATMemoryStream instance.
00138  *
00139  *  @param description The pointer to the GATMemoryStream to destroy
00140  */
00141 void
00142 GATMemoryStream_Destroy(GATMemoryStream *object)
00143 {
00144   if (NULL != object && NULL != *object)
00145   {
00146     free((*object)->buffer);
00147     free(*object);
00148     *object = NULL;
00149   }
00150 }
00151 
00152 /** GATMemoryStream_Equals
00153  *  @brief Compare two GATMemoryStream objects
00154  *
00155  *  The function @c GATMemoryStream_Equals compares two objects of the
00156  *  @c GATMemoryStream type.
00157  *
00158  *  @param lhs The first list to compare
00159  *  @param rhs The second list to compare
00160  *  @param isequal The pointer to the location, where the outcome of the 
00161  *        function has to be stored.
00162  *
00163  *  @return An error code.
00164  */
00165 GATResult
00166 GATMemoryStream_Equals(GATMemoryStream_const lhs,
00167   GATMemoryStream_const rhs, GATBool *isequal)
00168 {
00169   GATResult retval = GAT_INVALID_HANDLE;
00170 
00171   if (NULL != lhs && NULL != rhs)
00172   {
00173     retval = GAT_INVALID_PARAMETER;
00174     if (NULL != isequal)
00175     {
00176       if (lhs->max_size != rhs->max_size || 
00177           lhs->used_size != rhs->used_size)
00178       {
00179         *isequal = GATFalse;
00180       }
00181       else
00182       {
00183         *isequal = !memcmp(lhs->buffer, rhs->buffer, lhs->used_size) ? 
00184           GATTrue : GATFalse;
00185       }
00186       retval = GAT_SUCCESS;
00187     }
00188   }
00189   return retval;
00190 }
00191 
00192 /** GATMemoryStream_Clone
00193  *  @brief Clone the given GATMemoryStream
00194  *
00195  *  The function @c GATMemoryStream_Clone generates a (deep) copy of 
00196  *  the given GATMemoryStream. 
00197  *
00198  *  @param description The object to clone
00199  *  @param new_object The pointer, through which the result is to be 
00200  *        returned.
00201  *
00202  *  @return An error type.
00203  */
00204 GATResult
00205 GATMemoryStream_Clone(GATMemoryStream_const handle, 
00206   GATMemoryStream *new_handle)
00207 {
00208   GATResult retval = GAT_INVALID_HANDLE;
00209   if (NULL != handle)
00210   {
00211     if (NULL == new_handle)
00212     {
00213       retval = GAT_INVALID_PARAMETER;
00214     }
00215     else
00216     {
00217       struct GATMemoryStream_S const *object = handle;
00218       GATMemoryStream new_object = (GATMemoryStream) 
00219         malloc(sizeof(struct GATMemoryStream_S));
00220       
00221       *new_handle = NULL;
00222       if (NULL == new_object)
00223       {
00224         retval = GAT_MEMORYFAILURE;
00225       }
00226       else
00227       {
00228         memset(new_object, 0, sizeof(struct GATMemoryStream_S));
00229         new_object->GATObject__vtable = &GATMemoryStream__vtable;
00230         new_object->GATStreamable__vtable = &GATMemoryStream_IStreamable__vtable;
00231         new_object->buffer = (int8_t *)malloc(object->max_size);
00232         if (NULL == new_object->buffer)
00233         {
00234           retval = GAT_MEMORYFAILURE;
00235         }
00236         else
00237         {
00238           memcpy(new_object->buffer, object->buffer, object->used_size);
00239           new_object->max_size = object->max_size;
00240           new_object->used_size = object->used_size;
00241           retval = GAT_SUCCESS;
00242         }
00243       }
00244     }
00245   }
00246   return retval;
00247 }
00248 
00249 /** GATType GATMemoryStream_GetType(GATMemoryStream_const resource)
00250  *  @brief Return the type of the GATMemoryStream
00251  *
00252  *  The function @c GATMemoryStream_GetType always returns 
00253  *  @c #GATType_GATMemoryStream. 
00254  *
00255  *  @param object The object to inspect
00256  *
00257  *  @return Returns always @c #GATType_GATMemoryStream. 
00258  */
00259 GATType
00260 GATMemoryStream_GetType(GATMemoryStream_const description)
00261 {
00262   GAT_UNUSED_PARAMETER(description);
00263   return GATType_GATMemoryStream;
00264 }
00265 
00266 /** int GATMemoryStream_GetInterface(GATMemoryStream_const file, GATInterface iftype, void const **ifp)
00267  *  @brief Get an interface supported by a GATObject
00268  *
00269  *  The function GATMemoryStream_GetInterface allows to get a pointer to an 
00270  *  additional interface supported by this GATMemoryStream.
00271  *
00272  *  @param object The object to be asked for the new interface.
00273  *  @param iftype The interface the object is to be asked for.
00274  *  @param ifp The pointer, through which the result is to be returned.
00275  *
00276  *  @return An error type.
00277  */
00278 GATResult GATMemoryStream_GetInterface(GATMemoryStream_const object, 
00279   GATInterface iftype, void const **ifp)
00280 {
00281   GATResult retval = GAT_INVALID_PARAMETER;
00282   if (NULL != ifp)
00283   {
00284     *ifp = NULL;
00285     if (GATInterface_IStreamable == iftype)
00286     {
00287       *ifp = (void const *) &object->GATStreamable__vtable;
00288       retval = GAT_SUCCESS;
00289     }
00290     else
00291     {
00292       retval = GAT_NO_INTERFACE;
00293     }
00294   }
00295   return retval;
00296 }
00297 
00298 /** GATMemoryStream_GetBuffer
00299  *
00300  */
00301 void *GATMemoryStream_GetBuffer(GATMemoryStream object, 
00302   GATuint32 *buffer_size, GATBool lend_ownership)
00303 {
00304   void *retval = NULL;
00305   if (NULL != object)
00306   {
00307     retval = object->buffer;
00308     if (NULL != buffer_size)
00309     {
00310       *buffer_size = object->used_size;
00311     }
00312     if (GATTrue == lend_ownership)
00313     {
00314       object->buffer = NULL;
00315       object->max_size = 0;
00316       object->used_size = 0;
00317     }
00318   }
00319   return retval;
00320 }
00321 
00322 /* IStreamable implementation */
00323 /* Reads from this GATStreamable into the given buffer */
00324 GATResult
00325   GATMemoryStream_Read(GATMemoryStream object, void *buffer, 
00326     GATuint32 size, GATuint32 *read_bytes)
00327 {
00328   GATResult retval = GAT_INVALID_HANDLE;
00329   if (NULL != object)
00330   {
00331     GATuint32 available = object->max_size - object->used_size;
00332     GATuint32 toread = (available < size) ? available : size;
00333     
00334     memcpy(buffer, &object->buffer[object->used_size], toread);
00335     object->used_size += toread;
00336     
00337     /* should not exceed used buffer */
00338     assert(object->used_size <= object->max_size);
00339     
00340     if (NULL != read_bytes)
00341     {
00342       *read_bytes = toread;
00343     }
00344     
00345     retval = GAT_SUCCESS;
00346   }
00347   return retval;
00348 }
00349 
00350 /* Writes data from the given Buffer through the GATStreamable */
00351 GATResult
00352 GATMemoryStream_Write(GATMemoryStream object, void const *buffer, 
00353   GATuint32 size, GATuint32 *written_bytes)
00354 {
00355   GATResult retval = GAT_INVALID_HANDLE;
00356   if (NULL != object)
00357   {
00358     GATuint32 available = object->max_size - object->used_size;
00359     
00360     if (available < size)
00361     {
00362       /* auto increase the used buffer */
00363       GATuint32 new_size = object->used_size + size + GATMEMORYSTREAM_BUFFERSIZE_INCREMENT;
00364       int8_t *new_buffer = (int8_t *)realloc(object->buffer, new_size);
00365 
00366       if (NULL != new_buffer)
00367       {
00368         object->buffer = new_buffer;
00369       
00370         memcpy(&object->buffer[object->used_size], buffer, size);
00371         
00372         object->used_size += size;
00373         object->max_size = new_size;
00374         
00375         assert(object->used_size <= object->max_size);
00376         
00377         retval = GAT_SUCCESS;
00378       }
00379       else
00380       {
00381         retval = GAT_MEMORYFAILURE;
00382       }
00383     }
00384     else
00385     {
00386       /* copy the data into our buffer */
00387       memcpy(&object->buffer[object->used_size], buffer, size);
00388       object->used_size += size;
00389 
00390       assert(object->used_size <= object->max_size);
00391       
00392       retval = GAT_SUCCESS;
00393     }
00394 
00395     /* return the number of bytes written */
00396     if (NULL !=  written_bytes)
00397     {
00398       *written_bytes = size;
00399     }
00400   }
00401   return retval;
00402 }
00403 
00404 GATResult
00405 GATMemoryStream_Seek(GATMemoryStream object, GATOrigin origin, 
00406   GATint32 offset, GATuint32 *new_position)
00407 {
00408   GATResult retval = GAT_INVALID_HANDLE;
00409   if (NULL != object)
00410   {
00411     switch(origin)
00412     {
00413       case GATOrigin_Set:
00414         if (offset >= 0 && (GATuint32)offset <= object->max_size)
00415         {
00416           object->used_size = offset;
00417           retval = GAT_SUCCESS;
00418         }
00419         else
00420         {
00421           retval = GAT_INVALID_PARAMETER;
00422         }
00423         break;
00424         
00425       case GATOrigin_Current:
00426         if ((GATint32)object->used_size + offset >= 0 && 
00427             object->used_size + offset <= object->max_size)
00428         {
00429           object->used_size += offset;
00430           retval = GAT_SUCCESS;
00431         }
00432         else
00433         {
00434           retval = GAT_INVALID_PARAMETER;
00435         }
00436         break;
00437         
00438       case GATOrigin_End:
00439         if ((GATint32)object->max_size + offset >= 0 && offset <= 0)
00440         {
00441           object->max_size += offset;
00442           retval = GAT_SUCCESS;
00443         }
00444         else
00445         {
00446           retval = GAT_INVALID_PARAMETER;
00447         }
00448         break;
00449         
00450       default:
00451         retval = GAT_INVALID_PARAMETER;
00452         break;
00453     }
00454     
00455     if (GAT_SUCCESS == retval && NULL != new_position)
00456     {
00457       *new_position = object->used_size;
00458     }
00459   }
00460   return retval;
00461 }
00462 
00463 /* Closes this GATStreamable instance. */
00464 GATResult
00465   GATMemoryStream_Close(GATMemoryStream object)
00466 {
00467   GATResult retval = GAT_SUCCESS;
00468   GAT_UNUSED_PARAMETER(object);
00469   return retval;
00470 }
00471 
00472 #if 0
00473 /* Reads from this GATStreamable into the given Buffer, but returning 
00474    immediately */
00475 GATResult
00476 GATMemoryStream_IRead(GATMemoryStream object, void *buffer, 
00477   GATuint32 size)
00478 {
00479   GATResult retval = GAT_NOTIMPL;
00480   return retval;
00481 }
00482 
00483 /* This finishes the current IRead call on this GATStreamable */
00484 GATResult
00485 GATMemoryStream_ReadFinish(GATMemoryStream object, GATBool *got_data,
00486   GATuint32 *got_bytes)
00487 {
00488   GATResult retval = GAT_NOTIMPL;
00489   return retval;
00490 }
00491 
00492 /* This tests if data has been received in the current IRead */
00493 GATResult
00494 GATMemoryStream_ReadTest(GATMemoryStream object, GATBool *can_read)
00495 {
00496   GATResult retval = GAT_NOTIMPL;
00497   return retval;
00498 }
00499 
00500 /* Writes data from the given Buffer through the GATStreamable, but returns 
00501    immediately */
00502 GATResult
00503 GATMemoryStream_IWrite(GATMemoryStream object, void const *buffer,  
00504   GATuint32 size)
00505 {
00506   GATResult retval = GAT_NOTIMPL;
00507   return retval;
00508 }
00509  
00510 /* This finishes the current IWrite call on this GATStreamable */
00511 GATResult
00512 GATMemoryStream_WriteFinish(GATMemoryStream object, 
00513   GATuint32 *written_bytes)
00514 {
00515   GATResult retval = GAT_NOTIMPL;
00516   return retval;
00517 }
00518 
00519 /* Tests if data has been sent from the current IWrite call on this 
00520    GATStreamable */
00521 GATResult
00522 GATMemoryStream_WriteTest(GATMemoryStream object, 
00523   GATuint32 *written_bytes)
00524 {
00525   GATResult retval = GAT_NOTIMPL;
00526   return retval;
00527 }
00528 #endif /* 0 */
00529 
00530 /* Local functions */