aboutsummaryrefslogtreecommitdiff
path: root/libcontextsubscriber/src/cdbreader.cpp
blob: f4e3b7036f1ae69744e735cfb6728d6535bbe911 (plain)
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
/*
 * Copyright (C) 2008 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <stdlib.h>
#include <cdb.h>
#include <fcntl.h>
#include <QDebug>
#include <QByteArray>
#include <QFile>
#include <QDataStream>
#include "cdbreader.h"
#include "logging.h"
#include "loggingfeatures.h"


/*!
    \class CDBReader

    \brief A wrapper class to read data from a tiny-cdb database.

    This class is not a part of the public API.  The reader operates
    on string-qvariant pairs: can read a qvariant value for a string
    key or a list of qvariant values for a string key. The reader
    automatically closes the underlying filesystem resource on
    destruction but can be also closed manually.

    Reading from a closed reader will return empty strings.
*/

/// Constructs a new CDBReader reading from cdb database at \a dbpath
/// \param dbpath Path to the database.
CDBReader::CDBReader(const QString &dbpath, QObject *parent)
    : QObject(parent), path(dbpath)
{
    contextDebug() << F_CDB << "cdb reader created for:" << dbpath;
    cdb = NULL;
    fd = 0;

    reopen();
}

/// Destroys the object automatically closing the database and file.
CDBReader::~CDBReader()
{
    close();
}

/// Closes the reader and the underlying file on the filesystem.
void CDBReader::close()
{
    if (cdb) {
        free(cdb);
        cdb = NULL;
    }

    if (fd > 0) {
        ::close(fd);
        fd = 0;
    }
}

/// Reopens the reader for reading.
/// It will first close the current reader if it's open.
void CDBReader::reopen()
{
    close();

    if (! QFile::exists(path))
        return;

    fd = open(path.toLocal8Bit().constData(), O_RDONLY);

    if (fd > 0) {
        cdb = calloc(1, sizeof(struct cdb));
        if (cdb_init((struct cdb*) cdb, fd) != 0) {
            free(cdb);
            cdb = NULL;
        }
    }
}

/// Returns all values associated with the given key from the database.
/// \param key The key name in the database.
QVariantList CDBReader::valuesForKey(const QString &key) const
{
    if (! cdb) {
        contextDebug() << F_CDB << "Trying to read values for key:" << key << "from database that is closed!";
        return QVariantList();
    }

    QVariantList list;
    QByteArray utf8Data = key.toUtf8();
    unsigned int klen = utf8Data.size();
    const char *kval = utf8Data.constData();

    struct cdb_find cdbf;
    cdb_findinit(&cdbf, (struct cdb*) cdb, kval, klen);

    while(cdb_findnext(&cdbf) > 0) {
        unsigned int vpos = cdb_datapos((struct cdb*) cdb);
        unsigned int vlen = cdb_datalen((struct cdb*) cdb);
        char *val = (char *) malloc(vlen);
        cdb_read((struct cdb*) cdb, val, vlen, vpos);
        QByteArray valArray(val, vlen);
        QDataStream ds(&valArray, QIODevice::ReadOnly);
        QVariant valVariant;
        ds >> valVariant;
        list << valVariant;
        free(val);
    }

    return list;
}

/// Returns a value for the given \a key.
/// First value is returned if there are many values for one key.
/// \param key The key name in the database.
QVariant CDBReader::valueForKey(const QString &key) const
{
    QVariantList ret = valuesForKey(key);
    if (ret.size() == 0) return QVariant();
    return ret[0];
}

/// Returns the current state of the reader. Reader is not readable if
/// it was created with a path that doesn't exist or if it was closed.
bool CDBReader::isReadable()
{
    return (fd > 0);
}

/// Returns the file descriptor used by the reader. Returns 0
/// when the reader is closed.
int CDBReader::fileDescriptor() const
{
    return fd;
}