1// File: gettingStartedCommon.hpp
2
3#ifndef GETTINGSTARTEDCOMMON_H
4#define GETTINGSTARTEDCOMMON_H
5
6class InventoryData
7{
8public:
9    inline void setPrice(double price) {price_ = price;}
10    inline void setQuantity(long quantity) {quantity_ = quantity;}
11    inline void setCategory(std::string &category) {category_ = category;}
12    inline void setName(std::string &name) {name_ = name;}
13    inline void setVendor(std::string &vendor) {vendor_ = vendor;}
14    inline void setSKU(std::string &sku) {sku_ = sku;}
15
16    inline double& getPrice() {return(price_);}
17    inline long& getQuantity() {return(quantity_);}
18    inline std::string& getCategory() {return(category_);}
19    inline std::string& getName() {return(name_);}
20    inline std::string& getVendor() {return(vendor_);}
21    inline std::string& getSKU() {return(sku_);}
22
23    /* Initialize our data members */
24    void clear()
25    {
26        price_ = 0.0;
27        quantity_ = 0;
28        category_ = "";
29        name_ = "";
30        vendor_ = "";
31        sku_ = "";
32    }
33
34    // Default constructor
35    InventoryData() { clear(); }
36
37    // Constructor from a void *
38    // For use with the data returned from a bdb get
39    InventoryData(void *buffer)
40    {
41        char *buf = (char *)buffer;
42
43        price_ = *((double *)buf);
44        bufLen_ = sizeof(double);
45
46        quantity_ = *((long *)(buf + bufLen_));
47        bufLen_ += sizeof(long);
48
49        name_ = buf + bufLen_;
50        bufLen_ += name_.size() + 1;
51
52        sku_ = buf + bufLen_;
53        bufLen_ += sku_.size() + 1;
54
55        category_ = buf + bufLen_;
56        bufLen_ += category_.size() + 1;
57
58        vendor_ = buf + bufLen_;
59        bufLen_ += vendor_.size() + 1;
60    }
61
62    /*
63     * Marshalls this classes data members into a single
64     * contiguous memory location for the purpose of storing
65     * the data in a database.
66     */
67    char *
68    getBuffer()
69    {
70        // Zero out the buffer
71        memset(databuf_, 0, 500);
72        /*
73         * Now pack the data into a single contiguous memory location for
74         * storage.
75         */
76        bufLen_ = 0;
77        int dataLen = 0;
78
79        dataLen = sizeof(double);
80        memcpy(databuf_, &price_, dataLen);
81        bufLen_ += dataLen;
82
83        dataLen = sizeof(long);
84        memcpy(databuf_ + bufLen_, &quantity_, dataLen);
85        bufLen_ += dataLen;
86
87        packString(databuf_, name_);
88        packString(databuf_, sku_);
89        packString(databuf_, category_);
90        packString(databuf_, vendor_);
91
92        return (databuf_);
93    }
94
95    /*
96     * Returns the size of the buffer. Used for storing
97     * the buffer in a database.
98     */
99    inline size_t getBufferSize() { return (bufLen_); }
100
101    /* Utility function used to show the contents of this class */
102    void
103    show() {
104        std::cout << "\nName:           " << name_ << std::endl;
105        std::cout << "    SKU:        " << sku_ << std::endl;
106        std::cout << "    Price:      " << price_ << std::endl;
107        std::cout << "    Quantity:   " << quantity_ << std::endl;
108        std::cout << "    Category:   " << category_ << std::endl;
109        std::cout << "    Vendor:     " << vendor_ << std::endl;
110    }
111
112private:
113
114    /*
115     * Utility function that appends a char * to the end of
116     * the buffer.
117     */
118    void
119    packString(char *buffer, std::string &theString)
120    {
121        size_t string_size = theString.size() + 1;
122        memcpy(buffer+bufLen_, theString.c_str(), string_size);
123        bufLen_ += string_size;
124    }
125
126    /* Data members */
127    std::string category_, name_, vendor_, sku_;
128    double price_;
129    long quantity_;
130    size_t bufLen_;
131    char databuf_[500];
132
133};
134
135#define MAXFIELD 20
136
137typedef struct vendor {
138    char name[MAXFIELD];             /* Vendor name */
139    char street[MAXFIELD];           /* Street name and number */
140    char city[MAXFIELD];             /* City */
141    char state[3];                   /* Two-digit US state code */
142    char zipcode[6];                 /* US zipcode */
143    char phone_number[13];           /* Vendor phone number */
144    char sales_rep[MAXFIELD];        /* Name of sales representative */
145    char sales_rep_phone[MAXFIELD];  /* Sales rep's phone number */
146} VENDOR;
147
148// Forward declarations
149class Db;
150class Dbt;
151
152// Used to extract an inventory item's name from an
153// inventory database record. This function is used to create
154// keys for secondary database records.
155int
156get_item_name(Db *dbp, const Dbt *pkey, const Dbt *pdata, Dbt *skey)
157{
158    /*
159     * First, obtain the buffer location where we placed the item's name. In
160     * this example, the item's name is located in the primary data. It is the
161     * first string in the buffer after the price (a double) and the quantity
162     * (a long).
163     */
164    u_int32_t offset = sizeof(double) + sizeof(long);
165    char *itemname = (char *)pdata->get_data() + offset;
166
167    // unused
168    (void)pkey;
169
170    /*
171     * If the offset is beyond the end of the data, then there was a problem
172     * with the buffer contained in pdata, or there's a programming error in
173     * how the buffer is marshalled/unmarshalled.  This should never happen!
174     */
175    if (offset > pdata->get_size()) {
176        dbp->errx("get_item_name: buffer sizes do not match!");
177        // When we return non-zero, the index record is not added/updated.
178        return (-1);
179    }
180
181    /* Now set the secondary key's data to be the item name */
182    skey->set_data(itemname);
183    skey->set_size((u_int32_t)strlen(itemname) + 1);
184
185    return (0);
186};
187#endif
188