Thread: Buffering read.

    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0

    Buffering read.


    I am improving a driver, but I am newbie about C programming.

    I want to know if this function that I wrote is correct, it is for reading inputed buffer.

    Code:
    int RawGet(LPBYTE  pBuffer, DWORD   cbBuf, LPDWORD pcbWritten)
    {
    	// It verifies if there is some byte in the buffer to be readed.
    	if ((cbBuf - *pcbWritten) > 0) // bufferSize - already readed bytes > 0.
    	{
    		// There is some byte.
    		*pcbWritten++;
    		return *pBuffer[*pcbWritten - 1];
    	}
    	else return EOF;
    }
    I haven't experience in pointer indirect indexation so I feels like I have a lot of doubts. It is correct or I must looking for the problem elsewhere?


    or maybe the problem is in this one.

    Code:
    int RawRead(LPBYTE pBuffer, DWORD cbBuf, LPDWORD pcbWritten, LPBYTE lpOutPutBuffer, DWORD WantedRead, LPDWORD WantedReallyReaded)
    {
    	// How many is in the buffer?.
    	DWORD InBuffer = (cbBuf - *pcbWritten);
    
    	// Is there something to read?.
    	if (InBuffer)
    	{
    		// There is enough as wanted?.
    		if (InBuffer >= WantedRead)
    		{
    			// Is enough.
    			lpOutPutBuffer = *pBuffer + *pcbWritten;
    			*pcbWritten += WantedRead;
    			*WantedReallyReaded = WantedRead;
    			return -1; // Meaning total read. (faster procedure can be used as optimization).
    		}
    		else
    		{
    			// Is not enough.
    			lpOutPutBuffer = *pBuffer + *pcbWritten;
    			*pcbWritten += InBuffer;
    			*WantedReallyReaded = InBuffer;
    			return -2; // Meaning partial read. (checked procedure needed).
    		}
    	}
    	else return 0; // Meaning FAIL, there was nothing to read.
    }
  2. #2
  3. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    those was buggy, but still with problems.

    last edition

    Code:
    int RawGet(LPBYTE pBuffer, DWORD   cbBuf, LPDWORD pcbWritten)
    {
    	// is something in the buffer?
    	if ((cbBuf - *pcbWritten) > 0) // buffersize - already readed bytes > 0.
    	{
    		// there is atleast one byte.
    		*pcbWritten++;
    		return pBuffer[*pcbWritten - 1];
    	}
    	else return EOF;
    }
    
    
    
    int RawRead(LPBYTE pBuffer, DWORD cbBuf, LPDWORD pcbWritten, LPBYTE lpOutPutBuffer, int WantedRead, LPINT WantedReallyReaded)
    {
    	// how many is in the buffer?.
    	int InBuffer = (cbBuf - *pcbWritten);
    
    	// buffer has something?.
    	if (InBuffer)
    	{
    		// there is enough?.
    		if (InBuffer >= WantedRead)
    		{
    			// will return all the wanted.
    			lpOutPutBuffer = &pBuffer[*pcbWritten];
    			*pcbWritten += WantedRead;
    			*WantedReallyReaded = WantedRead;
    			return -1; // Meaning total read. (faster procedure can be used as optimization).
    		}
    		else
    		{
    			// can't read all the wanted demand.
    			lpOutPutBuffer = &pBuffer[*pcbWritten];
    			*pcbWritten += InBuffer;
    			*WantedReallyReaded = InBuffer;
    			return -2; // Meaning partial read. (checked procedure needed).
    		}
    	}
    	else return 0; // Meaning FAIL, there was nothing to read.
    }


    the actual cuestion is about this line

    lpOutPutBuffer = &pBuffer[*pcbWritten]

    QUESTION: is that line correct?


    NOTES:
    that line must return a POINTER that points TO somewhere inside the input buffer, skipping all that was already readed from the input buffer.

    the DWORD variable pcbWritten (passed by reference), is suppose to account what is already used from the input buffer.



    ...(LPBYTE pBuffer, DWORD cbBuf, LPDWORD pcbWritten....

    those 3 variables are the ones supplied by the windows driver framework, when the driver function is called, the service fills in those three. My driver must use them and return that he already use some of the data just receive (total or partial).

    RawGet function must extract only one BYTE data from the buffer, but if there is nothing to read It must return EOF (a integer -1).

    RawRead function must extract as much as wanted, it can returns partial or total results returning the condition.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    Code:
    int RawGet(LPBYTE pBuffer, DWORD   cbBuf, LPDWORD pcbWritten)
    {
    	// is something in the buffer?
    	if ((cbBuf - *pcbWritten) > 0) // buffersize - already readed bytes > 0.
    	{
    		// there is atleast one byte.
    		*pcbWritten++;
    		return pBuffer[*pcbWritten - 1];
    	}
    	else return EOF;
    }
    definitelly this expression pBuffer[*pcbWritten - 1] is not returning the value to read from the buffer ...... WHYYYYYYYYYYYY?

    I already tested this pBuffer[ (*pcbWritten) - 1]

    And also tested this other version of the function.

    Code:
    int RawGet(LPBYTE pBuffer, DWORD   cbBuf, LPDWORD pcbWritten)
    {
    	HANDLE i_InkResultFileHandle;
    	char ch;
    	int ret = 0;
    
    	// Verifica si hay un caracter en el buffer como para leerlo.
    	if ((cbBuf - (*pcbWritten)) > 0) // Tamaño del buffer - bytes que ya se han leido > 0.
    	{
    		// Aún hay para extraer un caracter.
    		*pcbWritten++;
    		ch = pBuffer[(*pcbWritten) - 1];
    		memcpy( &ret, &ch, sizeof(ch) );
    	
    		return ret;
    	}
    	else return EOF;
    }
    But, the same, don't works, is not reading a legal / expected value.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    another try

    Code:
    int RawGet(LPBYTE pBuffer, DWORD   cbBuf, LPDWORD pcbWritten)
    {
    	
    	char ch;
    	int ret = 0;
    
    	
    	if ( (cbBuf - *pcbWritten) ) 
    	{
    		
    		ch = *(pBuffer + *pcbWritten);
    		*pcbWritten++;
    		memcpy ( &ret, &ch, sizeof(ch) );
    	
    		return ret;
    	}
    	else
    	{
    		return EOF;
    	}
    }
    ch = *(pBuffer + *pcbWritten);

    note the change on that line, and still don't reading the data from the buffer?.

    somebody any idea? is too hard that nobody replied?
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    40
    Rep Power
    19
    Originally Posted by flyguille
    another try

    Code:
    int RawGet(LPBYTE pBuffer, DWORD   cbBuf, LPDWORD pcbWritten)
    {
    	
    	char ch;
    	int ret = 0;
    
    	
    	if ( (cbBuf - *pcbWritten) ) 
    	{
    		
    		ch = *(pBuffer + *pcbWritten);
    		*pcbWritten++;
    		memcpy ( &ret, &ch, sizeof(ch) );
    	
    		return ret;
    	}
    	else
    	{
    		return EOF;
    	}
    }
    ch = *(pBuffer + *pcbWritten);

    note the change on that line, and still don't reading the data from the buffer?.

    somebody any idea? is too hard that nobody replied?

    You didn't describe what do you use this var. for: pBufferpcb, Written, cbBuf, etc.

    I guess what you are trying is looks like this...
    Code:
        pBuffer
        |              pBuffer + *pcbWritten
        |              |                                    pBuffer + cbBu
        |              |                                    |  
        v              v                                    v
        [a] [b] [c] [0] [* ] [* ] [* ] [* ] [* ] [* ]
         0    1   2    3    ...
        ------>
        Address
    If you want to get a char from a buffer, you have to decrease *pcbWritten and pick a char up.
    Code:
        (*pcbWritten)--;
        ch = *(pBuffer + *pcbWritten);
    If you want to put a char in a buffer, you put it and increase *pcbWritten.
    Code:
        
        *(pBuffer +*pcbWritten) = ch;
        (*pcbWritten)++;
    You need paper and pencil.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    as said is the buffer supplied by the driver framework so, is a pointer to the buffer. Is cbBuf indicating its size. And 'written' must indicate how many bytes extracted from the buffer or i thinks that (IT IS NOT A CYCLIC BUFFER, just a STREAM INPUT like a PIPE). The working old version of this was doing a 'WriteFile' passing those variables directly saving all the buffer to file then, the RawGet was reading the file one byte each time. That is very inefficient. So I deleted all that and interpreting the inputed buffer directly for rendering its PCL data on the fly. And that does RawGet . Reads a char from start to end from the buffer. But isn't not working the loop that interprets never is reading valid data and it never gets EOF indication from RawGet.

    PHP Code:
    int RawGet(LPBYTE pBufferDWORD   cbBufLPDWORD pcbWritten)
    {
        
        
    char ch;
        
    int ret 0;

        
        if ( (
    cbBuf - *pcbWritten) ) 
        {
            
            
    ch = *(pBuffer + *pcbWritten);
            *
    pcbWritten++;
            
    memcpy ( &ret, &chsizeof(ch) );
        
            return 
    ret;
        }
        else
        {
            return 
    EOF;
        }


    here is the loop in short.

    PHP Code:

    VOID ContinueRender
    (LPBYTE  pBufferDWORD   cbBufLPDWORD pcbWritten)
    {

    ...

    ch RawGet(pBuffercbBufpcbWritten);
        while (
    ch != EOF)
        {

            
    // CPU is going HERE! VERIFIED!!!.        

            
    switch (ch)
            {
                
    // never gets in a valid 'case' here.

                // ... here interprets PCL data taking in account that commands can be incompleted, so capable of interpreting a command partially.

            
    }

            
    // CPU is going HERE! VERIFIED!!!.        

            
    ch RawGet(pBuffercbBufpcbWritten);
        }    
    // Wend EOF.

    // never gets here!!!! WTF!!!!!!!.

        
    return;

    and that function is called from the supplied function to the driver framework that is the next.


    PHP Code:
    BOOL LcmWritePort(
        
    HANDLE  hPort,
        
    LPBYTE  pBuffer,
        
    DWORD   cbBuf,
        
    LPDWORD pcbWritten)
    {
        *
    pcbWritten 0;
        
        
    ContinueRender(pBuffercbBufpcbWritten);

        return 
    TRUE;



    Oh, just take the time to read all the rules of this forums so:

    IT IS PLAIN "C", the builder is the one that comes with DDK 2003, and the platform DEV/TARGET is for Windows 7 64bits. And the last working version but inefficient was compiled this way too.

    And I am trying to improve this way the driver from a working driver.








    THIS IS THE ORIGINAL working version

    PHP Code:
    BOOL LcmWritePort(
        
    HANDLE  hPort,
        
    LPBYTE  pBuffer,
        
    DWORD   cbBuf,
        
    LPDWORD pcbWritten)
    {
        
    PINIPORT    pIniPort = (PINIPORT)hPort;
        
    BOOL    rc;

        if ( !
    pIniPort->hFile || pIniPort->hFile == INVALID_HANDLE_VALUE )
        {
            
    SetLastError(ERROR_INVALID_HANDLE);
            return 
    FALSE;
        }
        else
        {
            
    rc WriteFile(pIniPort->hFilepBuffercbBufpcbWrittenNULL);
            if ( 
    rc && *pcbWritten == )
            {
                
    SetLastError(ERROR_TIMEOUT);
                
    rc FALSE;
            }
        }

        return 
    rc;

    sees how all inputed buffer originally is handled to the WriteFile wellknown function.

    rc = WriteFile(pIniPort->hFile, pBuffer, cbBuf, pcbWritten, NULL);

    first saving all inputed to a file that can be 223MB for 15 printed pages!!! that is too big.

    and originally the RawGet was:

    PHP Code:
    int RawGet(HANDLE hFile)
    {
        
    char ch EOF;
        
    int ret EOF;
        
    DWORD dwReaded 0;
        if( 
    INVALID_HANDLE_VALUE != hFile )
        {
            
    ret 0;
            
    ReadFilehFile, &chsizeof(ch), &dwReaded0);
            
    memcpy( &ret, &chsizeof(ch) ); // Copia solo el LOW BYTE del ch hacia ret.
            
    if( == dwReaded ret EOF;
        }
        return 
    ret;

    The only one reason to use a FILE as intermediate is for having all the printed pages completelly before to RENDER those as images, because the original programmer wasn't smart enough or didn't put time in this for coding render routines capables to be interrupted if the buffers gets unexpectelly empty.

    Maybe somebody sees something that I am not capable to see, I am new in C but in VB and Assembler I have like 20 years of programming, so maybe is not easy but can't be too hard to figure out why.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    OKKKKKKKKKKKKKKKKKKKK!!! FOUND!!!


    *pcbWritten++;



    that line was, just changed it to:

    *pcbWritten = *pcbWritten + 1;

    AND NOW IT WORKS!, SOMEBODY CAN EXPLAIN WHY THEY ARE NOT DOING THE SAME THING?.
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    159
    Rep Power
    19
    SOMEBODY CAN EXPLAIN WHY THEY ARE NOT DOING THE SAME THING?.
    This is a problem with operator precedence. Try:
    Code:
    (*pcbWritten)++;
    Jim
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    another question, because it didn't work totally

    I am having problems with the RawRead, similar but you can extract as much as you want from the buffer.

    PHP Code:
    int RawRead(LPBYTE pBufferDWORD cbBufLPDWORD pcbWrittenLPBYTE lpOutPutBufferint WantedReadLPINT WantedReallyReaded)
    {
        
    // Calcula cuánto realmente podría obtener del buffer.
        
    int InBuffer = (cbBuf - *pcbWritten);

        
    // Verifica si el buffer tiene algo.
        
    if (InBuffer)
        {
            
    // Verifica si puede cubrir la demanda.
            
    if (InBuffer >= WantedRead)
            {
                
    // Puede cubrir toda la demanda.
                
    lpOutPutBuffer pBuffer + *pcbWritten;
                *
    pcbWritten = *pcbWritten WantedRead;
                *
    WantedReallyReaded WantedRead;
                return -
    1// Meaning total read. (faster procedure can be used as optimization).
            
    }
            else
            {
                
    // no puede cubrir toda la demanda.
                
    lpOutPutBuffer pBuffer + *pcbWritten;
                *
    pcbWritten = *pcbWritten InBuffer;
                *
    WantedReallyReaded InBuffer;
                return -
    2// Meaning partial read. (checked procedure needed).
            
    }
        }
        else
        {
            
    lpOutPutBuffer NULL;
            return 
    0// Meaning FAIL, there was nothing to read.
        
    }


    I designed it as LPBYTE lpOutPutBuffer (the forth parameter), returns in the provided pointer, the address of the beggining of the data to be read.

    and I am using it this way

    PHP Code:
    LPBYTE i_raster NULL;

    WhatHappened RawRead(pBuffercbBufpcbWritteni_rasteri_IWantAmmount, &i_OnlyIsAvailableAmmount);

    if (
    i_raster != NULL)
    {
        
    // RENDER THE RASTER INPUTED.

    But it isn't getting IN the render part.

    I thinks is not the correct way to pass the i_raster pointer that the function CAN modifies its value. But I already tried to call it "&i_raster" its address, and that returned a compilation error.

    How is the correct way to pass i_raster (function header + call)?.
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    21
    Rep Power
    0
    SOLVED WITH A WORKAROUND!, just moved the declaration of i_raster pointer at FILE LEVEL. And removed the passing of it off the function.

    But would be nice to know how to do it, the correct way. I will not always have that possibility in the future.

IMN logo majestic logo threadwatch logo seochat tools logo