corona  1.0.2
MemoryFile.cpp
Go to the documentation of this file.
00001 #include <string.h>
00002 #include "MemoryFile.h"
00003 #include "Utility.h"
00004 
00005 namespace corona {
00006 
00007   namespace hidden {
00008 
00009     COR_EXPORT(File*) CorCreateMemoryFile(const void* buffer, int size) {
00010       if (size && !buffer) {
00011         return 0;
00012       }
00013       if (size < 0) {
00014         return 0;
00015       }
00016 
00017       return new MemoryFile(buffer, size);
00018     }
00019     
00020   }
00021 
00022 
00023   int getNextPowerOfTwo(int value) {
00024     int i = 1;
00025     while (i < value) {
00026       i *= 2;
00027     }
00028     return i;
00029   }
00030 
00031   MemoryFile::MemoryFile(const void* buffer, int size) {
00032     m_capacity = getNextPowerOfTwo(size);
00033     m_size = size;
00034     m_buffer = new byte[m_capacity];
00035     memcpy(m_buffer, buffer, size);
00036 
00037     m_position = 0;
00038   }
00039 
00040   MemoryFile::~MemoryFile() {
00041     delete[] m_buffer;
00042   }
00043 
00044   int COR_CALL MemoryFile::read(void* buffer, int size) {
00045     int real_read = std::min((m_size - m_position), size);
00046     memcpy(buffer, m_buffer + m_position, real_read);
00047     m_position += real_read;
00048     return real_read;
00049   }
00050 
00051   int COR_CALL MemoryFile::write(const void* buffer, int size) {
00052     ensureSize(m_position + size);
00053     memcpy(m_buffer + m_position, buffer, size);
00054     m_position += size;
00055     return size;
00056   }
00057 
00058   bool COR_CALL MemoryFile::seek(int position, SeekMode mode) {
00059     int real_pos;
00060     switch (mode) {
00061       case BEGIN:   real_pos = position;              break;
00062       case CURRENT: real_pos = m_position + position; break;
00063       case END:     real_pos = m_size + position;     break;
00064       default:      return false;
00065     }
00066 
00067     if (real_pos < 0 || real_pos > m_size) {
00068       m_position = 0;
00069       return false;
00070     } else {
00071       m_position = real_pos;
00072       return true;
00073     }
00074   }
00075 
00076   int COR_CALL MemoryFile::tell() {
00077     return m_position;
00078   }
00079 
00080   void MemoryFile::ensureSize(int min_size) {
00081     bool realloc_needed = false;
00082     while (m_capacity < min_size) {
00083       m_capacity *= 2;
00084       realloc_needed = true;
00085     }
00086 
00087     if (realloc_needed) {
00088       byte* new_buffer = new byte[m_capacity];
00089       memcpy(new_buffer, m_buffer, m_size);
00090       delete[] m_buffer;
00091       m_buffer = new_buffer;
00092     }
00093 
00094     m_size = min_size;
00095   }
00096 
00097 };