Subversion Repositories Games.Chess Giants

Rev

Rev 154 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // buffer.cpp
  2.  
  3. #include "common.h"
  4.  
  5.  
  6. // cross-platform facilities
  7. #ifndef _WIN32
  8. #define fopen_s(fp,filename,mode) *(fp) = fopen (filename, mode)
  9. #endif // _WIN32
  10.  
  11.  
  12. void Buffer_Initialize (buffer_t *buffer)
  13. {
  14.    // this function initializes a new buffer_t structure, resetting its data pointer and size.
  15.  
  16.    buffer->data = NULL; // allocate max_size bytes for data
  17.    buffer->size = 0; // reset size
  18.  
  19.    return; // finished, buffer structure is empty
  20. }
  21.  
  22.  
  23. void Buffer_Forget (buffer_t *buffer)
  24. {
  25.    // this function forgets a buffer's contents, freeing its associated memory buffer,
  26.    // and resets the buffer_t structure.
  27.  
  28.    if (buffer->data != NULL)
  29.       free (buffer->data); // free buffer data
  30.    buffer->data = NULL;
  31.    buffer->size = 0; // reset data size
  32.  
  33.    return; // finished, buffer structure is virgin again
  34. }
  35.  
  36.  
  37. int Buffer_Append (buffer_t *buffer, char *data, unsigned long data_size)
  38. {
  39.    // this function appends the content of data to a buffer's data.
  40.    // Returns 1 on success, 0 on error.
  41.  
  42.    char *new_data;
  43.  
  44.    // first, reallocate space to hold data_size bytes more
  45.    new_data = (char *) realloc (buffer->data, buffer->size + data_size + 2);
  46.    if (new_data == NULL)
  47.       return (0); // on failure, return an error value
  48.  
  49.    buffer->data = new_data; // save pointer to reallocated data
  50.    memcpy (&buffer->data[buffer->size], data, data_size); // write new data at the end
  51.    buffer->data[buffer->size + data_size + 0] = 0; // always null-terminate buffers, silently
  52.    buffer->data[buffer->size + data_size + 1] = 0; // always null-terminate buffers, silently
  53.    buffer->size += data_size; // and increment buffer size
  54.  
  55.    return (1); // buffer appended successfully, return SUCCESS
  56. }
  57.  
  58.  
  59. int Buffer_Prepend (buffer_t *buffer, char *data, unsigned long data_size)
  60. {
  61.    // this function prepends the content of data to a buffer's data.
  62.    // Returns 1 on success, 0 on error.
  63.  
  64.    char *new_data;
  65.  
  66.    // first, reallocate space to hold data_size bytes more
  67.    new_data = (char *) realloc (buffer->data, data_size + buffer->size + 2);
  68.    if (new_data == NULL)
  69.       return (0); // on failure, return an error value
  70.  
  71.    buffer->data = new_data; // save pointer to reallocated data
  72.    if (buffer->size > 0)
  73.       memmove (&buffer->data[data_size], buffer->data, buffer->size); // move existing data to the end
  74.    memcpy (buffer->data, data, data_size); // write new data at the beginning
  75.    buffer->data[buffer->size + data_size + 0] = 0; // always null-terminate buffers, silently
  76.    buffer->data[buffer->size + data_size + 1] = 0; // always null-terminate buffers, silently
  77.    buffer->size += data_size; // and increment buffer size
  78.  
  79.    return (1); // buffer appended successfully, return SUCCESS
  80. }
  81.  
  82.  
  83. int Buffer_WriteAt (buffer_t *buffer, unsigned long write_index, char *data, unsigned long data_size)
  84. {
  85.    // this function writes the content of data to a buffer's data at position write_index.
  86.    // Returns 1 on success, 0 on error.
  87.  
  88.    char *new_data;
  89.    char *dest;
  90.  
  91.    // see if we need to grow the data
  92.    if (write_index + data_size > buffer->size)
  93.    {
  94.       // if so, reallocate data buffer at the right size
  95.       new_data = (char *) realloc (buffer->data, write_index + data_size + 2);
  96.       if (new_data == NULL)
  97.          return (0); // on failure, return an error value
  98.  
  99.       buffer->data = new_data; // save pointer to reallocated data
  100.    }
  101.  
  102.    // do dest and source overlap ?
  103.    dest = &buffer->data[write_index];
  104.    if (((data <= dest) && (data + data_size > dest)) || ((dest <= data) && (dest + data_size > data)))
  105.       memmove (&buffer->data[write_index], data, data_size); // if so, move data in place
  106.    else
  107.       memcpy (&buffer->data[write_index], data, data_size); // else write data in place (faster)
  108.    if (write_index + data_size > buffer->size)
  109.    {
  110.       buffer->data[write_index + data_size + 0] = 0; // always null-terminate buffers, silently
  111.       buffer->data[write_index + data_size + 1] = 0; // always null-terminate buffers, silently
  112.       buffer->size = write_index + data_size; // update data size only if it growed
  113.    }
  114.  
  115.    return (1); // buffer written successfully, return SUCCESS
  116. }
  117.  
  118.  
  119. int Buffer_ReadFromFile (buffer_t *buffer, const char *file_pathname)
  120. {
  121.    // this function copies the contents of file_pathname in a newly allocated data buffer
  122.    // and fills in the buffer size accordingly. It is up to the caller to free that buffer.
  123.    // Returns 1 on success, 0 on error.
  124.  
  125.    struct stat stat_buffer;
  126.    FILE *fp;
  127.  
  128.    // start by reporting a zero length
  129.    buffer->size = 0;
  130.  
  131.    // figure out file existence and size
  132.    if (stat (file_pathname, &stat_buffer) != 0)
  133.       return (0); // on failure, return an error value
  134.  
  135.    // allocate enough space for it
  136.    if ((buffer->data = (char *) malloc (stat_buffer.st_size + 2)) == NULL)
  137.       return (0); // on failure, return an error value
  138.  
  139.    // open it for binary reading
  140.    fopen_s (&fp, file_pathname, "rb");
  141.    if (fp == NULL)
  142.    {
  143.       free (buffer->data);
  144.       return (0); // on failure, return an error value
  145.    }
  146.  
  147.    // and read it at once
  148.    if (fread (buffer->data, 1, stat_buffer.st_size, fp) != (size_t) stat_buffer.st_size)
  149.    {
  150.       free (buffer->data);
  151.       return (0); // on failure, return an error value
  152.    }
  153.  
  154.    fclose (fp); // finished, close file
  155.    buffer->data[stat_buffer.st_size + 0] = 0; // always null-terminate buffers, silently
  156.    buffer->data[stat_buffer.st_size + 1] = 0; // always null-terminate buffers, silently
  157.    buffer->size = stat_buffer.st_size; // report its size
  158.  
  159.    return (1); // and return SUCCESS
  160. }
  161.  
  162.  
  163. int Buffer_ReadFromFileW (buffer_t *buffer, const wchar_t *file_pathname)
  164. {
  165.    // this function copies the contents of file_pathname in a newly allocated data buffer
  166.    // and fills in the buffer size accordingly. It is up to the caller to free that buffer.
  167.    // Returns 1 on success, 0 on error.
  168.  
  169.    struct _stat stat_buffer;
  170.    FILE *fp;
  171.  
  172.    // start by reporting a zero length
  173.    buffer->size = 0;
  174.  
  175.    // figure out file existence and size
  176.    if (_wstat (file_pathname, &stat_buffer) != 0)
  177.       return (0); // on failure, return an error value
  178.  
  179.    // allocate enough space for it
  180.    if ((buffer->data = (char *) malloc (stat_buffer.st_size + 2)) == NULL)
  181.       return (0); // on failure, return an error value
  182.  
  183.    // open it for binary reading
  184.    _wfopen_s (&fp, file_pathname, L"rb");
  185.    if (fp == NULL)
  186.    {
  187.       free (buffer->data);
  188.       return (0); // on failure, return an error value
  189.    }
  190.  
  191.    // and read it at once
  192.    if (fread (buffer->data, 1, stat_buffer.st_size, fp) != (size_t) stat_buffer.st_size)
  193.    {
  194.       free (buffer->data);
  195.       return (0); // on failure, return an error value
  196.    }
  197.  
  198.    fclose (fp); // finished, close file
  199.    buffer->data[stat_buffer.st_size + 0] = 0; // always null-terminate buffers, silently
  200.    buffer->data[stat_buffer.st_size + 1] = 0; // always null-terminate buffers, silently
  201.    buffer->size = stat_buffer.st_size; // report its size
  202.  
  203.    return (1); // and return SUCCESS
  204. }
  205.  
  206.  
  207. int Buffer_WriteToFile (buffer_t *buffer, const char *file_pathname)
  208. {
  209.    // this function copies the contents of buffer's data into the file pointed to by
  210.    // file_pathname. Returns 1 on success, 0 on error.
  211.  
  212.    FILE *fp;
  213.  
  214.    // open file for binary writing
  215.    fopen_s (&fp, file_pathname, "wb");
  216.    if (fp == NULL)
  217.       return (0);
  218.  
  219.    // and write it at once
  220.    if (fwrite (buffer->data, 1, buffer->size, fp) != (size_t) buffer->size)
  221.       return (0);
  222.  
  223.    fclose (fp); // finished, close file
  224.    return (1); // and return SUCCESS
  225. }
  226.  
  227.  
  228. int Buffer_WriteToFileW (buffer_t *buffer, const wchar_t *file_pathname)
  229. {
  230.    // this function copies the contents of buffer's data into the file pointed to by
  231.    // file_pathname. Returns 1 on success, 0 on error.
  232.  
  233.    FILE *fp;
  234.  
  235.    // open file for binary writing
  236.    _wfopen_s (&fp, file_pathname, L"wb");
  237.    if (fp == NULL)
  238.       return (0);
  239.  
  240.    // and write it at once
  241.    if (fwrite (buffer->data, 1, buffer->size, fp) != (size_t) buffer->size)
  242.       return (0);
  243.  
  244.    fclose (fp); // finished, close file
  245.    return (1); // and return SUCCESS
  246. }
  247.  
  248.  
  249. char *Buffer_Find (buffer_t *buffer, char *needle, unsigned long needle_length)
  250. {
  251.    // returns a pointer to the first occurence of needle in buffer haystack, or NULL if not found
  252.  
  253.    unsigned long byte_index;
  254.  
  255.    if (buffer->size < needle_length)
  256.       return (NULL); // consistency check: if buffer is too small for needle, return NULL
  257.  
  258.    // parse buffer from start to end
  259.    for (byte_index = 0; byte_index < buffer->size - needle_length; byte_index++)
  260.       if (memcmp (&buffer->data[byte_index], needle, needle_length) == 0)
  261.          return (&buffer->data[byte_index]); // return the first match we find
  262.  
  263.    return (NULL); // definitely no needle in buffer
  264. }
  265.  
  266.  
  267. int Buffer_Compare (buffer_t *buffer1, buffer_t *buffer2)
  268. {
  269.    // compares two buffers and return 0 if they match, non-zero if they differ.
  270.    // If their size differ, the difference between both is returned.
  271.    // If their content differ, the result of memcmp() is returned.
  272.  
  273.    if (buffer1->size != buffer2->size)
  274.       return (buffer2->size - buffer1->size); // buffers differ in size
  275.  
  276.    return (memcmp (buffer1->data, buffer2->data, buffer1->size)); // do a memcmp() on both buffers
  277. }
  278.  
  279.  
  280. unsigned long Buffer_OffsetOf (buffer_t *buffer, void *something)
  281. {
  282.    // returns the absolute offset of the data pointed to by something relatively to the beginning of buffer data
  283.  
  284.    return ((unsigned long) something - (unsigned long) buffer->data);
  285. }
  286.