tags:

views:

1145

answers:

6

I've got a C++ program that uses SQLite. I want to store the SQL queries in a separate file -- a plain-text file, not a source code file -- but embed that file in the executable file like a resource.

(This has to run on Linux, so I can't store it as an actual resource as far as I know, though that would be perfect if it were for Windows.)

Is there any simple way to do it, or will it effectively require me to write my own resource system for Linux? (Easily possible, but it would take a lot longer.)

+1  A: 

Use macros. Technically that file would be source code file but it wouldn't look like this. Example:

//queries.incl - SQL queries
Q(SELECT * FROM Users)
Q(INSERT [a] INTO Accounts)


//source.cpp
#define Q(query) #query,
char * queries[] = {
#include "queries.incl"
};
#undef Q

Later on you could do all sorts of other processing on that file by the same file, say you'd want to have array and a hash map of them, you could redefine Q to do another job and be done with it.

vava
+1  A: 

It's slightly ugly, but you can always use something like:

const char *query_foo =
#include "query_foo.txt"

const char *query_bar =
#include "query_bar.txt"

Where query_foo.txt would contain the quoted query text.

introp
+3  A: 

You can always write a small program or script to convert your text file into a header file and run it as part of your build process.

Trent
A: 

I have seen this to be done by converting the resource file to a C source file with only one char array defined containing the content of resource file in a hexadecimal format (to avoid problems with malicious characters). This automatically generated source file is then simply compiled and linked to the project.

It should be pretty easy to implement the convertor to dump C file for each resource file also as to write some facade functions for accessing the resources.

Matej
+15  A: 

You can use objcopy to bind the contents of the file to a symbol your program can use. See, for instance, here for more information.

moonshadow
Beautiful! Thank you!
Head Geek
+1  A: 

Here's a sample that we used for cross-platform embeddeding of files. It's pretty simplistic, but will probably work for you.

You may also need to change how it's handling linefeeds in the escapeLine function.

#include <string>
#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

std::string escapeLine( std::string orig )
{
    string retme;
    for (unsigned int i=0; i<orig.size(); i++)
    {
     switch (orig[i])
     {
     case '\\':
      retme += "\\\\";
      break;
     case '"':
      retme += "\\\"";
      break;
     case '\n': // Strip out the final linefeed.
      break;
     default:
      retme += orig[i];
     }
    }
    retme += "\\n"; // Add an escaped linefeed to the escaped string.
    return retme;
}

int main( int argc, char ** argv )
{
    string filenamein, filenameout;

    if ( argc > 1 )
     filenamein = argv[ 1 ];
    else
    {
     // Not enough arguments
     fprintf( stderr, "Usage: %s <file to convert.mel> [ <output file name.mel> ]\n", argv[0] );
     exit( -1 );
    }

    if ( argc > 2 )
     filenameout = argv[ 2 ];
    else
    {
     string new_ending = "_mel.h";
     filenameout = filenamein;
     std::string::size_type pos;
     pos = filenameout.find( ".mel" );
     if (pos == std::string::npos)
      filenameout += new_ending;
     else
      filenameout.replace( pos, new_ending.size(), new_ending );
    }

    printf( "Converting \"%s\" to \"%s\"\n", filenamein.c_str(), filenameout.c_str() );

    ifstream filein( filenamein.c_str(), ios::in );
    ofstream fileout( filenameout.c_str(), ios::out );

    if (!filein.good())
    {
     fprintf( stderr, "Unable to open input file %s\n", filenamein.c_str() );
     exit( -2 );
    }
    if (!fileout.good())
    {
     fprintf( stderr, "Unable to open output file %s\n", filenameout.c_str() );
     exit( -3 );
    }

    // Write the file.
    fileout << "tempstr = ";

    while( filein.good() )
    {
     string buff;
     if ( getline( filein, buff ) )
     {
      fileout << "\"" << escapeLine( buff ) << "\"" << endl;
     }
    }

    fileout << ";" << endl;

    filein.close();
    fileout.close();

    return 0;
}
tfinniga