tags:

views:

533

answers:

6

Is there any way to create a memory buffer as a FILE*. In TiXml it can print the xml to a FILE* but i cant seem to make it print to a memory buffer.

+2  A: 

No, you cannot create a block of memory that looks like a FILE*. When you think about it this would be impossible since there's no way to know how much data would be written.

However with TinyXML using operator << you can write to a C++ stream which can either be an std::string or a stream of your choosing. Alternatively you can use the TiXMLPrinter class.

See the Printing section on the Tiny XML site;

http://www.grinninglizard.com/tinyxmldocs/index.html

Andrew Grant
I got around it using a tmp file (http://www.cplusplus.com/reference/clibrary/cstdio/tmpfile.html) but i will look into the printer
Lodle
Certainly it's not "impossible"? If it were impossible to do for memory, wouldn't it also be impossible for disk, i.e. for regular files? It would be trivial to implement using realloc(). You can always return failure from fwrite() if running out of memory (or, equivalently, disk).
unwind
+1  A: 

You could use the CStr method of TiXMLPrinter which the documentation states:

The TiXmlPrinter is useful when you need to:

  1. Print to memory (especially in non-STL mode)
  2. Control formatting (line endings, etc.)
Kevin Loney
+2  A: 

I guess the proper answer is that by Kevin. But here is a hack to do it with FILE *. Note that if the buffer size (here 100000) is too small then you lose data, as it is written out when the buffer is flushed. Also, if the program calls fflush() you lose the data.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    FILE *f = fopen("/dev/null", "w");
    int i;
    int written = 0;
    char *buf = malloc(100000);
    setbuffer(f, buf, 100000);
    for (i = 0; i < 1000; i++)
    {
        written += fprintf(f, "Number %d\n", i);
    }
    for (i = 0; i < written; i++) {
        printf("%c", buf[i]);
    }
}
antti.huima
cool hack - any idea if it's portable?
Nils Pipenbrinck
It works only if can prevent stdio from flushing the buffer, and I guess the details of that aren't standardized.
antti.huima
`setbuf()` and `setvbuf()` (NOT `setbuffer()`) are ISO-C, so it *should* be portable once you use these. If the bufferering mode is fully buffered, it should try to fill the buffer completely; on windows, you have to use "NUL" instead of "/dev/null"; you should also open the file in binary mode "wb"
Christoph
+1  A: 

Here's some sample code I am using, adapted from the TiXMLPrinter documentation:

TiXmlDocument doc;
// populate document here ...

TiXmlPrinter printer;
printer.SetIndent( "    " );

doc.Accept( &printer );
std::string xmltext = printer.CStr();
Alex B
ill give this a try, Atm i just use a tempory file the os makes via a c library call.
Lodle
+1  A: 

fmemopen can create FILE from buffer, does it make any sense to you?

solotim
A: 

I wrote a simple example how i would create an in-memory FILE:

#include <unistd.h> 
#include <stdio.h> 

int main(){
  int p[2]; pipe(p); FILE *f = fdopen( p[1], "w" );

  if( !fork() ){
    fprintf( f, "working" );
    return 0;
  }

  fclose(f); close(p[1]);
  char buff[100]; int len;
  while( (len=read(p[0], buff, 100))>0 )
    printf(" from child: '%*s'", len, buff );
  puts("");
}
sambowry