File: load_jpeg.txt

package info (click to toggle)
mysql%2B%2B 3.2.5-2.3
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 18,356 kB
  • sloc: cpp: 35,788; sh: 3,693; perl: 789; makefile: 728
file content (136 lines) | stat: -rw-r--r-- 4,559 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "cmdline.h"
#include "images.h"
#include "printdata.h"

#include <fstream>

using namespace std;
using namespace mysqlpp;


// This is just an implementation detail for the example.  Skip down to
// main() for the concept this example is trying to demonstrate.  You
// can simply assume that, given a BLOB containing a valid JPEG, it
// returns true.
static bool
is_jpeg(const mysqlpp::sql_blob& img, const char** whynot)
{
    // See http://stackoverflow.com/questions/2253404/ for
    // justification for the various tests.
    const unsigned char* idp =
            reinterpret_cast<const unsigned char*>(img.data());
    if (img.size() < 125) {
        *whynot = "a valid JPEG must be at least 125 bytes";
    }
    else if ((idp[0] != 0xFF) || (idp[1] != 0xD8)) {
        *whynot = "file does not begin with JPEG sigil bytes";
    }
    else if ((memcmp(idp + 6, "JFIF", 4) != 0) &&
             (memcmp(idp + 6, "Exif", 4) != 0)) {
        *whynot = "file does not contain JPEG type word";
    }
    else {
        *whynot = 0;
        return true;
    }

    return false;
}


// Skip to main() before studying this.  This is a little too
// low-level to bother with on your first pass thru the code.
static bool
load_jpeg_file(const mysqlpp::examples::CommandLine& cmdline,
        images& img, string& img_name)
{
    if (cmdline.extra_args().size() == 0) {
        // Nothing for us to do here.  Caller will insert NULL BLOB.
        return true;
    }

    // Got a file's name on the command line, so open it.
    img_name = cmdline.extra_args()[0];
    ifstream img_file(img_name.c_str(), ios::binary);
    if (img_file) {
        // Slurp file contents into RAM with minimum copying.  (Idiom
        // explained here: http://stackoverflow.com/questions/116038/)
        //
        // By loading the file into a C++ string (stringstream::str())
        // and assigning that directly to a mysqlpp::sql_blob, we avoid
        // truncating the binary data at the first null character.
        img.data.data = static_cast<const stringstream*>(
                &(stringstream() << img_file.rdbuf()))->str();

        // Check JPEG data for sanity.
        const char* error;
        if (is_jpeg(img.data.data, &error)) {
            return true;
        }
        else {
            cerr << '"' << img_name << "\" isn't a JPEG: " <<
                    error << '!' << endl;
        }
    }

    cmdline.print_usage("[jpeg_file]");
    return false;
}


int
main(int argc, char *argv[])
{
    // Get database access parameters from command line
    mysqlpp::examples::CommandLine cmdline(argc, argv);
    if (!cmdline) {
        return 1;
    }

    try {
        // Establish the connection to the database server.
        mysqlpp::Connection con(mysqlpp::examples::db_name,
                cmdline.server(), cmdline.user(), cmdline.pass());

        // Load the file named on the command line
        images img(mysqlpp::null, mysqlpp::null);
        string img_name("NULL");
        if (load_jpeg_file(cmdline, img, img_name)) {
            // Insert image data or SQL NULL into the images.data BLOB
            // column.  The key here is that we're holding the raw
            // binary data in a mysqlpp::sql_blob, which avoids data
            // conversion problems that can lead to treating BLOB data
            // as C strings, thus causing null-truncation.  The fact
            // that we're using SSQLS here is a side issue, simply
            // demonstrating that mysqlpp::Null<mysqlpp::sql_blob> is
            // now legal in SSQLS, as of MySQL++ 3.0.7.
            Query query = con.query();
            query.insert(img);
            SimpleResult res = query.execute();

            // Report successful insertion
            cout << "Inserted \"" << img_name <<
                    "\" into images table, " << img.data.data.size() <<
                    " bytes, ID " << res.insert_id() << endl;
        }
    }
    catch (const BadQuery& er) {
        // Handle any query errors
        cerr << "Query error: " << er.what() << endl;
        return -1;
    }
    catch (const BadConversion& er) {
        // Handle bad conversions
        cerr << "Conversion error: " << er.what() << endl <<
                "\tretrieved data size: " << er.retrieved <<
                ", actual size: " << er.actual_size << endl;
        return -1;
    }
    catch (const Exception& er) {
        // Catch-all for any other MySQL++ exceptions
        cerr << "Error: " << er.what() << endl;
        return -1;
    }

    return 0;
}