VS10 & MCBS:
For this I have created a file called c:\eoftest containing the text "test". The value of ch on the 5th pass in the following code is 65535 returned by fgetwc, but it does not equate to EOF, which we all know is defined in stdio.h as (-1):
#include <stdio.h>
#include <windows.h>
int main()
{
int ch;
FILE *stream = NULL;
wchar_t buf[5];
memset (buf, '\0', sizeof(buf));
stream = _wfopen(L"C:\\eoftest.txt", L"r");
for (int i = 0; (i < (sizeof(buf) - 1) && ((ch = fgetwc(stream)) != EOF) && (ch != '\0')); i++) //we are reading so last null condition mandatory
{
ungetwc(ch, stream);
buf[i] = (wchar_t)(ch = fgetwc(stream));
}
}
Replacing the condition (sic) with (ch = fgetwc(stream)) != 65535) works in this case, but what is not done to ensure the EOF test can succeed?
From MSDN documentation for fgetc, fgetwc
fgetc returns the character read as an int or returns EOF to indicate an error or end of file. fgetwc returns, as a
wint_t, the wide character that corresponds to the character read or
returns WEOF to indicate an error or end of file.
WEOF is defined as 0xFFFF which is what you substituted earlier 65535
#define WEOF ((wint_t)(0xFFFF))
So the EOF test for wide char should be changed to
if ((ch = fgetwc(stream)) != WEOF) ...
Edit
int main()
{
wchar_t buf[5];
memset(buf, '\0', sizeof(buf));
wcscpy(buf, L"1234");
FILE *stream = _wfopen(L"C:\\eoftest.txt", L"rb");
if (!stream)
{
stream = _wfopen(L"C:\\eoftest.txt", L"w+b");
if (!stream)
{
printf("cannot create file\n");
return 0;
}
fwrite((char*)buf, sizeof(buf[0]), wcslen(buf), stream);
fseek(stream, 0, 0);
}
int len = sizeof(buf) / sizeof(buf[0]);
for (int i = 0; i < len; i++)
{
wchar_t ch = fgetwc(stream);
if (ch == WEOF) break;
buf[i] = ch;
}
wprintf(L"result = %s\n", buf);
return 0;
}
Edit 2: This will print content of unicode file line by line:
int main()
{
FILE *stream = _wfopen(L"c:\\test\\test.txt", L"rb");
if (!stream) return 0;
int buflen = 256;
wchar_t* buf = (wchar_t*)malloc(buflen * sizeof(wchar_t));
if (fread(buf, 2, 1, stream))
{
if (buf[0] != 0xFEFF)
{
//BOM not detected, go back to start of file
rewind(stream);
}//else, skip the first 2 bytes
}
int i = 0, line = 0;
wint_t ch = 0;
while (ch != WEOF)
{
ch = fgetwc(stream);
if (ch == L'\n' || ch == WEOF)
{
//null-terminate the buffer at i
buf[i] = L'\0';
//trim the '\r' at the end, if any
if (i > 0 && buf[i - 1] == '\r') buf[i - 1] = L'\0';
wprintf(L"%3d %s\n", ++line, buf);
//start a new line for the next pass
i = 0;
}
else
{
buf[i] = ch;
i++;
if (i == buflen)
{
//increase buffer:
buflen += 256;
buf = (wchar_t*)realloc(buf, buflen * sizeof(wchar_t));
}
}
}
free(buf);
return 0;
}
Related
I have the following code to read from file, it uses byte-at-a-time system call I/O and is thus quite slow
int readc(io61_file* f) {
unsigned char buf[1];
ssize_t nr = read(f->fd, buf, 1);
if (nr == 1) {
return buf[0];
} else if (nr == 0) {
errno = 0; // clear `errno` to indicate EOF
return -1;
} else {
assert(nr == -1 && errno > 0);
return -1;
}
}
This is how I use it
// io_read(f, buf, sz)
// Reads up to `sz` bytes from `f` into `buf`. Returns the number of
// bytes read on success. Returns 0 if end-of-file is encountered before
// any bytes are read, and -1 if an error is encountered before any
// bytes are read.
//
// Note that the return value might be positive, but less than `sz`,
// if end-of-file or error is encountered before all `sz` bytes are read.
// This is called a “short read.”
ssize_t io_read(io61_file* f, unsigned char* buf, size_t sz) {
size_t nread = 0;
while (nread != sz) {
int ch = readc(f);
if (ch == EOF) {
break;
}
buf[nread] = ch;
++nread;
}
if (nread != 0 || sz == 0 || errno == 0) {
return nread;
} else {
return -1;
}
}
I want to speed up this code and as the first step, I want to increase the buf size inside readc to 10. How to do this correctly? As the first step I decided to return an array of size 1 from readc but it doesn't work as expected. Where I made a mistake?
unsigned char* io_readc2(io61_file* f) {
static unsigned char buf[1];
ssize_t nr = read(f->fd, buf, 1);
if (nr > 0 && nr < 2) {
return buf;
} else if (nr == 0) {
errno = 0; // clear `errno` to indicate EOF
static unsigned char t[1];
t[0] = -1;
return t;
} else {
assert(nr == -1 && errno > 0);
static unsigned char t[1];
t[0] = -1;
return t;
}
}
ssize_t io_read(io61_file* f, unsigned char* buf, size_t sz) {
size_t nread = 0;
while (nread != sz) {
unsigned char* chars = io_readc2(f);
int ch = *chars;
if (ch == EOF) {
break;
}
buf[nread] = ch;
++nread;
}
if (nread != 0 || sz == 0 || errno == 0) {
return nread;
} else {
return -1;
}
}
There is no need for an intermediate buffer. Just take the data from the standard library and write it into the output buffer:
// f->fd is the file descriptor to read from
// buf is the output, sz is the maximum bytes to read
// return value is the number of bytes read
// if there was an error, returns -1 with error != 0
// if there was no data available, returns -1 with errno == 0
ssize_t io_read(io61_file* f, unsigned char* buf, size_t sz)
{
ssize_t nr = read(f->fd, buf, sz);
if (nr == 0 && sz != 0)
{
errno = 0;
return -1;
}
return nr;
}
Edit: since you say you need an intermediate buffer, here you go:
// same effect as io_read() but with extra buffering for some reason
ssize_t io_read_extra(io61_file* f, unsigned char* buf, size_t sz)
{
std::vector<char> innerbuf(sz);
ssize_t nr = read(f->fd, innerbuf.data(), sz);
if (nr == 0 && sz != 0)
{
errno = 0;
return -1;
}
if (nr > 0)
{
memcpy(buf, innerbuf.data(), nr);
}
return nr;
}
I am using fread function to read file, which I am sending via TCP. I found out, that fread doesn't read the whole file, if the file is binary. I tried everything what i found on the internet, but nothing helped. My code is:
#define BUFSIZE 1024
char buf[BUFSIZE];
FILE *file = fopen(soubor,"rb"); //I do a check which i won't write here
size_t bytes_loaded = 0;
while (!feof(file))
{
bytes_loaded = fread(buf,1,BUFSIZE,file);
if(bytes_loaded != BUFSIZE)
{
if(!feof(file))
{
for(int i = 0; i < 100;i++)
{
fseek(file,-strlen(buf),SEEK_CUR);
bytes_loaded = fread(buf,1,BUFSIZE,file);
if(bytes_loaded == BUFSIZE)
{
break;
}
else if(i == 99)
{
fprintf(stderr,"C could't read the file\n");
fclose(file);
close(client_socket);
return 1;
}
}
}
}
bytestx = send(client_socket, buf, BUFSIZE, 0);
if (bytestx < 0)
perror("ERROR in sendto");
bzero(buf, BUFSIZE);
bytes_loaded = 0;
}
Am I doing something wrong? For example that fread check...
Your whole fread() error handling is wrong, get rid of it (using strlen() on a binary buffer is wrong anyway).
In fact, you shouldn't be using feof() to control your loop. Simply call fread() in a loop until it returns < 1 on EOF or error (use feof() and ferror() to differentiate). And when it returns > 0, you need to pass that value to send instead of passing BUFSIZE.
Try something more like this:
#define BUFSIZE 1024
char buf[BUFSIZE], *pbuf;
FILE *file = fopen(soubor, "rb");
...
size_t bytes_loaded;
do
{
bytes_loaded = fread(buf, 1, BUFSIZE, file);
if (bytes_loaded < 1)
{
if ((!feof(file)) && ferror(file))
fprintf(stderr, "Couldn't read the file\n");
break;
}
pbuf = buf;
do
{
bytestx = send(client_socket, pbuf, bytes_loaded, 0);
if (bytestx < 0)
{
perror("ERROR in send");
break;
}
pbuf += bytestx;
bytes_loaded -= bytestx;
}
while (bytes_loaded > 0);
}
while (bytes_loaded == 0);
fclose(file);
...
If you are just shifting bytes from the file to the socket then you can just keep looping on the return value from std::fread which tells you how many bytes you read and then send exactly that many bytes to your send() command.
Something like this (untested) code:
if(FILE* fp = std::fopen(soubor, "rb"))
{
char buf[1024];
std::size_t bytesrx;
while((bytesrx = std::fread(0, 1, sizeof(buf), fp)) > 0)
{
int bytestx;
if((bytestx = send(client_socket, buf, bytesrx, 0) < 0))
{
// socket error
std::cout << "socket error: " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
}
if(bytesrx < 0)
{
// file error
std::cout << "file error: " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
}
else
{
// error opening file
}
like title, here is my code:
int decompress_one_file(char *infilename, char *outfilename)
{
gzFile infile = gzopen(infilename, "rb");
FILE *outfile = fopen(outfilename, "wb");
if (!infile || !outfile) return -1;
char buffer[128] = {NULL};
int num_read = 0;
num_read = gzread(infile, buffer, sizeof(buffer)); // crash here
while (num_read > 0) {
fwrite(buffer, 1, num_read, outfile);
}
gzclose(infile);
fclose(outfile);
return 0;
}
when my console-app run to gzread(), its crash, I don't know what type of error is this?. zlib version: 1.2.11
update compress function:
int compress_one_file(char *infilename, char *outfilename)
{
FILE *infile = fopen(infilename, "rb");
gzFile outfile = gzopen(outfilename, "wb");
if (!infile || !outfile) return -1;
char inbuffer[128] = {NULL};
int num_read = 0;
unsigned long total_read = 0, total_wrote = 0;
while ((num_read = fread(inbuffer, 1, sizeof(inbuffer), infile)) > 0) {
total_read += num_read;
gzwrite(outfile, inbuffer, num_read);
}
fclose(infile);
gzclose(outfile);
return 0;
}
Error that shows up:
Anyone got an idea about this error?
I checked and it works fine at my workstation. May be here is a issue with gzipped file?
Could you show a file that give a crash?
But in any case you have a infinity loop of fwrite:
int num_read = 0;
while ((num_read = gzread(infile, buffer, sizeof(buffer))) > 0) {
while (num_read > 0) {
num_read -= fwrite(buffer, 1, num_read, outfile);
}
}
I call the function AES_Dec with the same Parameters. In most of the cases it returns the correct respond. But with a randomness of around 15% the respond is different.
char* AES_Dec(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error)
{
//initialize variables
//initialize key
char *keyPlain = args->args[1];
int keylength = (static_cast<int>(args->lengths[1])) / 2;
uint16_t *key = new uint16_t;
hex2bin(keyPlain, reinterpret_cast<unsigned char*>(key));
//output
char *output = new char;
bin2hex(key , keylength, output);
*length = keylength* 2;
return output;
}
void hex2bin(const char* src, unsigned char* target)
{
while (*src && src[1])
{
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
}
}
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return 0;
}
void bin2hex(unsigned short* pv, size_t len, char *output)
{
const unsigned char * buf = reinterpret_cast<const unsigned char*>(pv);
static const char* hex_lookup = "0123456789ABCDEF";
char *p = output;
for (int i = 0; i < len; i++) {
*p++ = hex_lookup[buf[i] >> 4];
*p++ = hex_lookup[buf[i] & 0x0F];
}
*p = '\0';
}
I call this function with the following parameters:
SELECT AES_Dec('2C4E907536FBB3C9FADD4CFBD45950EF03517AA5F7F402DA9E3ABD03FC6E0068EF39F3DFC26A92B871E8D8CE521EAF6C', 'B99DD1D646CDBC8505419D069B5C0209', '1')
The correct respond which is returned most of the time is:
B99DD1D646CDBC8505419D069B5C0209
And the respond which comes randomly is
B2323332333333323333333333333332
There are only these two responses. And I have no idea why the random respond appears. In a console application it all works fine without any problems. So the code should work.
Have anyone a solution?
Thank you.
Edit: the full quellcode:
#include "Header.h"
#ifdef HAVE_DLOPEN
my_bool AES_Dec_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if (args->arg_count != 3) {
return 1;
}
else if (args->arg_type[0] != STRING_RESULT ||
args->arg_type[1] != STRING_RESULT ||
args->arg_type[2] != STRING_RESULT) {
return 1;
}
return 0;
}
void AES_Dec_clear(UDF_INIT *initid, char *is_null, char *message) {
}
void AES_Dec_add(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *message) {
}
char* AES_Dec(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error)
{
//initialize variables
//initialize modus
char* modChar = args->args[2];
int mod;
if (modChar[0] == '1')
mod = 1;
else
mod = 0;
//initialize key
char *keyPlain = args->args[1];
int keylength = (static_cast<int>(args->lengths[1])) / 2;
uint16_t *key = new uint16_t;
hex2bin(keyPlain, reinterpret_cast<unsigned char*>(key));
//initialize value
const char *plain = args->args[0];
int plainLength = 0;
if (mod == 0)
plainLength = args->lengths[0] / 2;
else
plainLength = args->lengths[0] / 2 - 16;
uint16_t *contentWithIv = new uint16_t;
uint16_t *iv = new uint16_t;
hex2bin(plain, (unsigned char*)contentWithIv);
if (mod == 1) {
for (int i = 0; i < 8; i++) {
iv[i] = *contentWithIv;
contentWithIv++;
}
}
else
iv == NULL;
uint16_t *plaintext = contentWithIv;
// Buffer for the decrypted text
uint16_t *decryptedtext = new uint16_t;
int decryptedtext_len, ciphertext_len;
// Initialise the library
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
// Encrypt the plaintext
decryptedtext_len = decrypt((unsigned char*)plaintext, plainLength, (unsigned char*)key, (unsigned char*)iv, (unsigned char*)decryptedtext, keylength * 8, mod);
// Add a NULL terminator. We are expecting printable text
decryptedtext[decryptedtext_len] = '\0';
// Clean up
EVP_cleanup();
ERR_free_strings();
char *finalDec = (char*)malloc(decryptedtext_len * 2);
bin2hex(decryptedtext, decryptedtext_len, finalDec);
*length = decryptedtext_len * 2;
return finalDec;
}
void AES_Dec_deinit(UDF_INIT *initid) {
free(initid->ptr);
}
void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext, int keylength, int mod)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
// Create and initialise the context
if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
// Initialise the decryption operation.
if (mod == 0) {
if (keylength == 128)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
handleErrors();
if (keylength == 192)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_192_ecb(), NULL, key, NULL))
handleErrors();
if (keylength == 256)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
handleErrors();
}
else if (mod == 1) {
if (keylength == 128)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleErrors();
if (keylength == 192)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_192_cbc(), NULL, key, iv))
handleErrors();
if (keylength == 256)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
}
else
handleErrors();
// Provide the message to be decrypted, and obtain the plaintext output.
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
// Finalise the decryption.
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
plaintext_len += len;
// Clean up
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
void hex2bin(const char* src, unsigned char* target)
{
while (*src && src[1])
{
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
}
}
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return 0;
}
void bin2hex(unsigned short* pv, size_t len, char *output)
{
const unsigned char * buf = reinterpret_cast<const unsigned char*>(pv);
static const char* hex_lookup = "0123456789ABCDEF";
char *p = output;
for (int i = 0; i < len; i++) {
*p++ = hex_lookup[buf[i] >> 4];
*p++ = hex_lookup[buf[i] & 0x0F];
}
*p = '\0';
}
#endif /* HAVE_DLOPEN */
I require an application in which i want to give the byte stream of NAL units to GMFBridge player instead of file.so i did the following
for demo
Takes the file and parse the file so that i can i find the nal unit
FILE* infile;
uint8_t* buf = (uint8_t*)malloc(BUFSIZE );
char* buf1 = new char(BUFSIZE );
h264_stream_t* h = h264_new();
/*if (argc < 2) { usage(); return EXIT_FAILURE; }*/
infile = fopen(Filepath, "rb");
while (1)
{
rsz = fread(buf + sz, 1, BUFSIZE - sz, infile);
fseek (infile , 0 , SEEK_END);
lSize = ftell (infile);
rewind (infile);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{fputs ("Memory error",stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer,1,lSize,infile);
if (result != lSize)
{fputs ("Reading error",stderr); exit (3);}
fprintf( h264_dbgfile1,"data in file is %lld\n",buffer);
int l=strlen(buffer);
fclose (h264_dbgfile1);
if (rsz == 0)
{
if (ferror(infile)) { fprintf( stderr, "!! Error: read failed: %s \n", strerror(errno)); break; }
break; // if (feof(infile))
}
sz += rsz;
while (find_nal_unit(p, sz, &nal_start, &nal_end) > 0)
{
int length =nal_end-nal_start;
int j=0;
while(length!=0)
{
for (int start=nal_start;start<=nal_end;start++)
{
FileData[pointer][j]=buffer[start];
//FileData[pointer][j]=(p[j]);
j++;
length--;
if(length==0)
break;
}
}
HRESULT hr = m_pPlayer->AddClip(ofn.lpstrFile, &pClip);//i am not able to give the data here
Please tell the above solution or can we connect the GMFBridge player to take data from socket and play it continuously.
I tried for socket but i didn't recv the data as connect call was suceessfull
int find_nal_unit(uint8_t* buf, int size, int* nal_start, int* nal_end)
{
int i;
// find start
*nal_start = 0;
*nal_end = 0;
i = 0;
while ( //( next_bits( 24 ) != 0x000001 && next_bits( 32 ) != 0x00000001 )
(buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) &&
(buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0 || buf[i+3] != 0x01)
)
{
i++; // skip leading zero
if (i+4 >= size) { return 0; } // did not find nal start
}
if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) // ( next_bits( 24 ) != 0x000001 )
{
i++;
}
if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) { /* error, should never happen */ return 0; }
i+= 3;
*nal_start = i;
while ( //( next_bits( 24 ) != 0x000000 && next_bits( 24 ) != 0x000001 )
(buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0) &&
(buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01)
)
{
i++;
// FIXME the next line fails when reading a nal that ends exactly at the end of the data
if (i+3 >= size) { *nal_end = size; return -1; } // did not find nal end, stream ended first
}
*nal_end = i;
return (*nal_end - *nal_start);
}
Bridge is connecting two graphs so that you could change their states independently without unnecessary streaming breaks. It has nothing to do with H.264, Sockets, and NAL Units.
If you find or create a filter which can deliver payload received from socket into DirectShow pipeline, the bridge will be able to accept it and deliver into the second graph.