Author: mysqlpp
Date: Thu Nov 26 21:06:58 2009
New Revision: 2584

URL: http://svn.gna.org/viewcvs/mysqlpp?rev=2584&view=rev
Log:
Reworked the load_jpeg example code for clarity, extracting
load_jpeg_file() routine as an implementation detail and making that use
the C++ stringstream "slurp into string" idiom instead of allocating a C
char buffer and copying that into a std::string.

Modified:
    trunk/examples/load_jpeg.cpp

Modified: trunk/examples/load_jpeg.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/load_jpeg.cpp?rev=2584&r1=2583&r2=2584&view=diff
==============================================================================
--- trunk/examples/load_jpeg.cpp (original)
+++ trunk/examples/load_jpeg.cpp Thu Nov 26 21:06:58 2009
@@ -35,6 +35,8 @@
 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.
 static bool
 is_jpeg(const char* img_data)
 {
@@ -43,6 +45,62 @@
        return (idp[0] == 0xFF) && (idp[1] == 0xD8) &&
                        ((memcmp(idp + 6, "JFIF", 4) == 0) ||
                         (memcmp(idp + 6, "Exif", 4) == 0));
+}
+
+
+// Another implementation detail.  Skip to main().
+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::ate | ios::binary);
+       if (img_file) {
+               // File opened, so try to slurp its contents into RAM.  The key
+               // thing to get from this function is that we're storing the
+               // binary data in a mysqlpp::sql_blob value, which we assign 
from
+               // a C++ string (stringstream::str()), thus not truncating the
+               // string at the first embedded null character.
+               stringstream sstr;
+               sstr << img_file.rdbuf();
+               img.data.data = sstr.str();
+
+               // Check JPEG data for sanity
+               if (img.data.data.size() > 10) {
+                       // The following triple 'data' sure does look foolish,
+                       // doesn't it?  Sorry, we're not trying to be obscure 
here,
+                       // it's just a coincidence of naming.  Right-to-left, 
what
+                       // we have here is:
+                       //
+                       // 1. A call to mysqlpp::sql_blob::data() (mirroring 
C++'s
+                       //    std::string:data() interface) to get the raw C 
data
+                       //    pointer without null-terminating it first.
+                       // 2. Access to the mysqlpp::sql_blob object through its
+                       //    mysqlpp::Null<> wrapper, which lets us have a 
"NULL
+                       //    JPEG" in the DB when the file doesn't exist.
+                       // 3. Access to the JPEG BLOB column, images.data.
+                       if (is_jpeg(img.data.data.data())) {
+                               return true;
+                       }
+                       else {
+                               cerr << '"' << img_file <<
+                                               "\" isn't a JPEG!" << endl;
+                               cmdline.print_usage("[jpeg_file]");
+                               return false;
+                       }
+               }
+               else {
+                       cerr << "File is too short to be a JPEG!" << endl;
+                       cmdline.print_usage("[jpeg_file]");
+                       return false;
+               }
+       }
 }
 
 
@@ -60,58 +118,27 @@
                mysqlpp::Connection con(mysqlpp::examples::db_name,
                                cmdline.server(), cmdline.user(), 
cmdline.pass());
 
-               // Try to create a new item in the images table, based on what
-               // we got on the command line.
+               // Load the file named on the command line
                images img(mysqlpp::null, mysqlpp::null);
-               string img_name = "NULL";
-               if (cmdline.extra_args().size()) {
-                       // We received at least one non-option argument on the
-                       // command line, so treat it as a file name 
-                       img_name = cmdline.extra_args()[0];
-                       ifstream img_file(img_name.c_str(), ios::ate | 
ios::binary);
-                       if (img_file) {
-                               size_t img_size = img_file.tellg();
-                               if (img_size > 10) {
-                                       img_file.seekg(0, ios::beg);
-                                       char* img_buffer = new char[img_size];
-                                       img_file.read(img_buffer, img_size);
-                                       if (is_jpeg(img_buffer)) {
-                                               img.data = 
mysqlpp::sql_blob(img_buffer, img_size);
-                                       }
-                                       else {
-                                               cerr << '"' << img_file <<
-                                                               "\" isn't a 
JPEG!" << endl;
-                                       }
-                                       delete[] img_buffer;
-                               }
-                               else {
-                                       cerr << "File is too short to be a 
JPEG!" << endl;
-                               }
-                       }
+               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();
 
-                       if (img.data.data.empty()) {
-                               // File name was bad, or file contents aren't 
JPEG.  
-                               cmdline.print_usage("[jpeg_file]");
-                               return 1;
-                       }
+                       // Report successful insertion
+                       cout << "Inserted \"" << img_name <<
+                                       "\" into images table, " << 
img.data.data.size() <<
+                                       " bytes, ID " << res.insert_id() << 
endl;
                }
-               // else, no image given on command line, so insert SQL NULL
-               // instead of image data.  NULL BLOB columns in SSQLS is
-               // legal as of MySQL++ v3.0.7.
-
-               // Insert image data or SQL NULL into the images.data BLOB
-               // column.  By inserting it as an SSQLS with a mysqlpp::sql_blob
-               // member, we avoid truncating it at the first embedded C null
-               // character ('\0'), as would happen if we used the raw
-               // character buffer we allocated above.
-               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


_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits

Reply via email to