home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / smc / outfile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  9.8 KB  |  382 lines

  1. /*****************************************************************************/
  2.  
  3. #include "smcPCH.h"
  4. #pragma hdrstop
  5.  
  6. #include "outfile.h"
  7.  
  8. /*****************************************************************************/
  9.  
  10. #include <io.h>
  11. #include <conio.h>
  12. #include <fcntl.h>
  13. #include <sys/stat.h>
  14.  
  15. /*****************************************************************************
  16.  *
  17.  *  Open an output file by path name; the 'buffSize' paremeter specifies
  18.  *  the output buffer size, and 'buffAddr' (when NULL) is the address of
  19.  *  a caller-supplied output buffer (if NULL, we allocate one locally).
  20.  */
  21.  
  22. void                outFile::outFileOpen(Compiler       comp,
  23.                                          const char *   name,
  24.                                          bool           tempFile,
  25.                                          size_t         buffSize,
  26.                                          char *         buffAddr)
  27. {
  28.     outFileComp      = comp;
  29.  
  30.     /* Assume we won't be allocating a buffer */
  31.  
  32.     outFileBuffAlloc = false;
  33.     outFileBuffAddr  = buffAddr;
  34.  
  35.     /* Save the output file name (for error messages and deletion upon error) */
  36.  
  37.     strcpy(outFileName, name);
  38.  
  39.     /* Open/create the output file */
  40.  
  41.     cycleCounterPause();
  42.     outFileHandle = _open(name, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC|_O_SEQUENTIAL, _S_IWRITE|_S_IREAD);
  43.     cycleCounterResume();
  44.  
  45.     if  (outFileHandle == -1)
  46.         comp->cmpGenFatal(ERRopenWrErr, name);
  47.  
  48.     /* Use default buffer size if caller didn't choose */
  49.  
  50.     if  (!buffSize)
  51.         buffSize = 4*1024;      // 4K seems a good size
  52.  
  53.     outFileBuffSize = buffSize;
  54.  
  55.     /* Do we need to allocate a buffer? */
  56.  
  57.     if  (!buffAddr)
  58.     {
  59.         outFileBuffAddr = (char *)VirtualAlloc(NULL, buffSize, MEM_COMMIT, PAGE_READWRITE);
  60.         if  (!outFileBuffAddr)
  61.             comp->cmpFatal(ERRnoMemory);
  62.         outFileBuffAlloc = true;
  63.     }
  64.  
  65.     /* Set the next and last free byte values */
  66.  
  67.     outFileBuffNext = outFileBuffAddr;
  68.     outFileBuffLast = outFileBuffAddr + outFileBuffSize;
  69.  
  70.     /* We are at the beginning of the file */
  71.  
  72.     outFileBuffOffs = 0;
  73. }
  74.  
  75. #ifdef  DLL
  76.  
  77. void                outFile::outFileOpen(Compiler comp, void *dest)
  78. {
  79.     outFileBuffAlloc = false;
  80.     outFileBuffAddr  = (char*)dest;
  81.     outFileBuffSize  = UINT_MAX;
  82.     outFileBuffOffs  = 0;
  83.  
  84.     outFileBuffNext  = outFileBuffAddr;
  85.     outFileBuffLast  = outFileBuffAddr + outFileBuffSize;
  86.  
  87.     outFileHandle    = -1; strcpy(outFileName, ":memory:");
  88. }
  89.  
  90. #endif
  91. /*****************************************************************************
  92.  *
  93.  *  Flush and close the file.
  94.  */
  95.  
  96. void                outFile::outFileClose()
  97. {
  98.     if  (outFileHandle == -1)
  99.         return;
  100.  
  101.     assert(outFileBuffAddr);
  102.     assert(outFileBuffNext >= outFileBuffAddr);
  103.     assert(outFileBuffNext <  outFileBuffLast);
  104.  
  105.     /* Flush the output buffer */
  106.  
  107.     outFileFlushBuff();
  108.  
  109.     /* Free up the output buffer if we allocated it on the heap */
  110.  
  111.     if  (outFileBuffAlloc)
  112.     {
  113.         VirtualFree(outFileBuffAddr, 0, MEM_RELEASE);
  114.                     outFileBuffAddr = NULL;
  115.     }
  116.  
  117. #ifndef NDEBUG
  118.  
  119.     /* To catch any abuses, zero everything */
  120.  
  121.     outFileBuffAddr =
  122.     outFileBuffNext =
  123.     outFileBuffLast = NULL;
  124.  
  125. #endif
  126.  
  127.     /* Close the file */
  128.  
  129.     cycleCounterPause();
  130.     _close(outFileHandle); outFileHandle = -1;
  131.     cycleCounterResume();
  132. }
  133.  
  134. /*****************************************************************************
  135.  *
  136.  *  Close the given file, free up the resources owned by it, and (optionally)
  137.  *  delete it.
  138.  */
  139.  
  140. void                outFile::outFileDone(bool delFlag)
  141. {
  142.     /* If we're not deleting the file, make sure the output buffer is flushed */
  143.  
  144.     if  (!delFlag)
  145.         outFileClose();
  146.  
  147.     cycleCounterPause();
  148.  
  149.     /* Close the file */
  150.  
  151.     if  (outFileHandle != -1)
  152.     {
  153.         _close(outFileHandle);
  154.                outFileHandle = -1;
  155.     }
  156.  
  157.     /* Delete the file if the caller wishes so */
  158.  
  159.     if  (delFlag)
  160.         _unlink(outFileName);
  161.  
  162.     cycleCounterResume();
  163.  
  164.     /* Free up the output buffer if we allocated it on the heap */
  165.  
  166.     if  (outFileBuffAlloc)
  167.     {
  168.         VirtualFree(outFileBuffAddr, 0, MEM_RELEASE);
  169.                     outFileBuffAddr = NULL;
  170.     }
  171. }
  172.  
  173. /*****************************************************************************
  174.  *
  175.  *  Flush whatever is in the output buffer, and reset it to be empty.
  176.  */
  177.  
  178. void                outFile::outFileFlushBuff()
  179. {
  180.     /* Compute the number of bytes waiting to be written */
  181.  
  182.     size_t          size = outFileBuffNext - outFileBuffAddr;
  183.  
  184.     /* Now that we know the size, reset the buffer pointer */
  185.  
  186.     outFileBuffNext = outFileBuffAddr;
  187.  
  188.     /* If there was anything in the buffer, write it out */
  189.  
  190.     if  (size)
  191.     {
  192.         size_t          written;
  193.  
  194.         cycleCounterPause();
  195.         written = _write(outFileHandle, outFileBuffAddr, size);
  196.         cycleCounterResume();
  197.  
  198.         if  (written != size)
  199.             outFileComp->cmpGenFatal(ERRwriteErr, outFileName);
  200.  
  201.         /* Update the current buffer offset */
  202.  
  203.         outFileBuffOffs += size;
  204.     }
  205. }
  206.  
  207. /*****************************************************************************
  208.  *
  209.  *  Write the given number of bytes from the specified address.
  210.  */
  211.  
  212. void                outFile::outFileWriteData(const void *data, size_t size)
  213. {
  214.     assert  (size);
  215.  
  216.     for (;;)
  217.     {
  218.         size_t      room;
  219.         size_t      copy;
  220.  
  221.         /* Figure out how much room is in the output buffer */
  222.  
  223.         room = outFileBuffLast - outFileBuffNext; assert(room);
  224.  
  225.         /* We'll copy "min(room, size)" bytes */
  226.  
  227.         copy = room;
  228.         if  (copy > size)
  229.             copy = size;
  230.  
  231.         memcpy(outFileBuffNext, data, copy); outFileBuffNext += copy;
  232.  
  233.         /* Did we fill all of the remaining buffer space? */
  234.  
  235.         if  (copy == room)
  236.         {
  237.             assert(outFileBuffNext == outFileBuffLast);
  238.  
  239.             outFileFlushBuff();
  240.         }
  241.  
  242.         /* Did we copy everything? */
  243.  
  244.         size -= copy;
  245.         if  (!size)
  246.             return;
  247.  
  248.         /* We have more data to write */
  249.  
  250.         *(char **)&data += copy;
  251.     }
  252. }
  253.  
  254. /*****************************************************************************/
  255. #ifdef  OLD_IL
  256. /*****************************************************************************
  257.  *
  258.  *  Go back to the given offset in the output file and patch one byte.
  259.  */
  260.  
  261. void        outFile::outFilePatchByte(unsigned long offset, int value)
  262. {
  263.     /* We must be patching something that is already written */
  264.  
  265.     assert(outFileOffset() > offset);
  266.  
  267.     /* Has the byte being patched gone to disk? */
  268.  
  269.     if  (outFileBuffOffs > offset)
  270.     {
  271.         /* Make sure we remember the correct file position */
  272.  
  273.         assert((unsigned long)outFileBuffOffs == (unsigned long)_lseek(outFileHandle, 0, SEEK_CUR));
  274.  
  275.         /* Seek to the patch position */
  276.  
  277.         _lseek(outFileHandle, offset, SEEK_SET);
  278.  
  279.         /* Write the patch value out */
  280.  
  281.         if  (_write(outFileHandle, &value, 1) != 1)
  282.             outFileComp->cmpGenFatal(ERRwriteErr, outFileName);
  283.  
  284.         /* Seek back to where we were to begin with */
  285.  
  286.         _lseek(outFileHandle, outFileBuffOffs, SEEK_SET);
  287.     }
  288.     else
  289.     {
  290.         /* The patch byte must be in the output buffer */
  291.  
  292.         outFileBuffAddr[offset - outFileBuffOffs] = value;
  293.     }
  294. }
  295.  
  296. /*****************************************************************************
  297.  *
  298.  *  Go back to the given offset in the output file and patch the given
  299.  *  number of bytes with a new value.
  300.  */
  301.  
  302. void        outFile::outFilePatchData(unsigned long offset,
  303.                                       const void *  data,
  304.                                       size_t        size)
  305. {
  306.     /* We must be patching something that is already written */
  307.  
  308.     assert(outFileOffset() >= offset + size);
  309.  
  310.     /* Has the entire section being patched gone to disk? */
  311.  
  312.     if  (outFileBuffOffs >= offset + size)
  313.     {
  314.         /* Make sure we remember the correct file position */
  315.  
  316.         assert((unsigned long)outFileOffset() == (unsigned long)_lseek(outFileHandle, 0, SEEK_CUR));
  317.  
  318.         /* Seek to the patch position */
  319.  
  320.         _lseek(outFileHandle, offset, SEEK_SET);
  321.  
  322.         /* Write the patch value out */
  323.  
  324.         if  (_write(outFileHandle, data, size) != (int)size)
  325.             outFileComp->cmpGenFatal(ERRwriteErr, outFileName);
  326.  
  327.         /* Seek back to where we were to begin with */
  328.  
  329.         _lseek(outFileHandle, outFileBuffOffs, SEEK_SET);
  330.  
  331.         return;
  332.     }
  333.  
  334.     /* Is the entire patch section within the output buffer? */
  335.  
  336.     if  (outFileBuffOffs <= offset)
  337.     {
  338.         /* Patch the data in memory */
  339.  
  340.         memcpy(outFileBuffAddr + offset - outFileBuffOffs, data, size);
  341.  
  342.         return;
  343.     }
  344.  
  345.     /* The patch section spans the output buffer - do it one byte at a time */
  346.  
  347.     char    *   temp = (char *)data;
  348.  
  349.     do
  350.     {
  351.         outFilePatchByte(offset, *temp);
  352.     }
  353.     while   (++offset, ++temp, --size);
  354. }
  355.  
  356. /*****************************************************************************/
  357. #endif//OLD_IL
  358. /*****************************************************************************
  359.  *
  360.  *  Append the specified number of 0 bytes to the file.
  361.  */
  362.  
  363. void                outFile::outFileWritePad (size_t size)
  364. {
  365.     assert((int)size > 0);
  366.  
  367.     static
  368.     BYTE            zeros[32];
  369.  
  370.     /* This is a bit lame .... */
  371.  
  372.     while (size >= sizeof(zeros))
  373.     {
  374.         outFileWriteData(zeros, sizeof(zeros)); size -= sizeof(zeros);
  375.     }
  376.  
  377.     if  (size)
  378.         outFileWriteData(zeros, size);
  379. }
  380.  
  381. /*****************************************************************************/
  382.