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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
// File: excxx_example_database_load.cpp
#include <iostream>
#include <fstream>
#include <cstdlib>
#include "MyDb.hpp"
#include "gettingStartedCommon.hpp"
#ifdef _WIN32
extern "C" {
extern int getopt(int, char * const *, const char *);
extern char *optarg;
}
#else
#include <unistd.h>
#endif
// Forward declarations
void loadInventoryDB(MyDb &, std::string &);
void loadVendorDB(MyDb &, std::string &);
using namespace std;
int
usage()
{
std::cout << "example_database_load [-b <path to data files>]"
<< " [-h <database home directory>]" << std::endl;
std::cout << "Note: If -b -h is specified, then the path must end"
<< " with your system's path delimiter (/ or \\)"
<< std::endl;
return (-1);
}
// Loads the contents of vendors.txt and inventory.txt into
// Berkeley DB databases.
int
main (int argc, char *argv[])
{
char ch, lastChar;
// Initialize the path to the database files
std::string basename("./");
std::string databaseHome("./");
// Database names
std::string vDbName("vendordb.db");
std::string iDbName("inventorydb.db");
std::string itemSDbName("itemname.sdb");
// Parse the command line arguments
while ((ch = getopt(argc, argv, "b:h:")) != EOF)
switch (ch) {
case 'h':
databaseHome = optarg;
lastChar = databaseHome[databaseHome.size() -1];
if (lastChar != '/' && lastChar != '\\')
return (usage());
break;
case 'b':
basename = optarg;
lastChar = basename[basename.size() -1];
if (lastChar != '/' && lastChar != '\\')
return (usage());
break;
case '?':
default:
return (usage());
break;
}
// Identify the full name for our input files, which should
// also include some path information.
std::string inventoryFile = basename + "inventory.txt";
std::string vendorFile = basename + "vendors.txt";
try
{
// Open all databases.
MyDb inventoryDB(databaseHome, iDbName);
MyDb vendorDB(databaseHome, vDbName);
MyDb itemnameSDB(databaseHome, itemSDbName, true);
// Associate the primary and the secondary
inventoryDB.getDb().associate(NULL,
&(itemnameSDB.getDb()),
get_item_name,
0);
// Load the inventory database
loadInventoryDB(inventoryDB, inventoryFile);
// Load the vendor database
loadVendorDB(vendorDB, vendorFile);
} catch(DbException &e) {
std::cerr << "Error loading databases. " << std::endl;
std::cerr << e.what() << std::endl;
return (e.get_errno());
} catch(std::exception &e) {
std::cerr << "Error loading databases. " << std::endl;
std::cerr << e.what() << std::endl;
return (-1);
}
// MyDb class constructors will close the databases when they
// go out of scope.
return (0);
} // End main
// Used to locate the first pound sign (a field delimiter)
// in the input string.
size_t
getNextPound(std::string &theString, std::string &substring)
{
size_t pos = theString.find("#");
substring.assign(theString, 0, pos);
theString.assign(theString, pos + 1, theString.size());
return (pos);
}
// Loads the contents of the inventory.txt file into a database
void
loadInventoryDB(MyDb &inventoryDB, std::string &inventoryFile)
{
InventoryData inventoryData;
std::string substring;
size_t nextPound;
std::ifstream inFile(inventoryFile.c_str(), std::ios::in);
if ( !inFile )
{
std::cerr << "Could not open file '" << inventoryFile
<< "'. Giving up." << std::endl;
throw std::exception();
}
while (!inFile.eof())
{
inventoryData.clear();
std::string stringBuf;
std::getline(inFile, stringBuf);
// Now parse the line
if (!stringBuf.empty())
{
nextPound = getNextPound(stringBuf, substring);
inventoryData.setName(substring);
nextPound = getNextPound(stringBuf, substring);
inventoryData.setSKU(substring);
nextPound = getNextPound(stringBuf, substring);
inventoryData.setPrice(strtod(substring.c_str(), 0));
nextPound = getNextPound(stringBuf, substring);
inventoryData.setQuantity(strtol(substring.c_str(), 0, 10));
nextPound = getNextPound(stringBuf, substring);
inventoryData.setCategory(substring);
nextPound = getNextPound(stringBuf, substring);
inventoryData.setVendor(substring);
void *buff = (void *)inventoryData.getSKU().c_str();
size_t size = inventoryData.getSKU().size()+1;
Dbt key(buff, (u_int32_t)size);
buff = inventoryData.getBuffer();
size = inventoryData.getBufferSize();
Dbt data(buff, (u_int32_t)size);
inventoryDB.getDb().put(NULL, &key, &data, 0);
}
}
inFile.close();
}
// Loads the contents of the vendors.txt file into a database
void
loadVendorDB(MyDb &vendorDB, std::string &vendorFile)
{
std::ifstream inFile(vendorFile.c_str(), std::ios::in);
if ( !inFile )
{
std::cerr << "Could not open file '" << vendorFile
<< "'. Giving up." << std::endl;
throw std::exception();
}
VENDOR my_vendor;
while (!inFile.eof())
{
std::string stringBuf;
std::getline(inFile, stringBuf);
memset(&my_vendor, 0, sizeof(VENDOR));
// Scan the line into the structure.
// Convenient, but not particularly safe.
// In a real program, there would be a lot more
// defensive code here.
sscanf(stringBuf.c_str(),
"%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
my_vendor.name, my_vendor.street,
my_vendor.city, my_vendor.state,
my_vendor.zipcode, my_vendor.phone_number,
my_vendor.sales_rep, my_vendor.sales_rep_phone);
Dbt key(my_vendor.name, (u_int32_t)strlen(my_vendor.name) + 1);
Dbt data(&my_vendor, sizeof(VENDOR));
vendorDB.getDb().put(NULL, &key, &data, 0);
}
inFile.close();
}
|