1 /*
2  * Copyright (C) 2009 Tommi Maekitalo
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
11  * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
12  * NON-INFRINGEMENT.  See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  */
19 
20 #ifndef ZIM_WRITER_DIRENT_H
21 #define ZIM_WRITER_DIRENT_H
22 
23 #include "cluster.h"
24 
25 #include "debug.h"
26 
27 namespace zim
28 {
29   namespace writer {
30     class Dirent;
31     struct DirectInfo {
DirectInfoDirectInfo32       DirectInfo() :
33         clusterNumber(0),
34         blobNumber(0)
35       {};
36       cluster_index_t  clusterNumber;
37       blob_index_t     blobNumber;
38     };
39 
40     struct RedirectInfo {
41       const Dirent* redirectDirent = nullptr;
42     };
43 
44     union DirentInfo {
45       DirectInfo d;
46       RedirectInfo r;
47     };
48 
49     class Dirent
50     {
51         static const uint16_t redirectMimeType = 0xffff;
52         static const uint16_t linktargetMimeType = 0xfffe;
53         static const uint16_t deletedMimeType = 0xfffd;
54         static const uint32_t version = 0;
55 
56         uint16_t mimeType;
57         DirentInfo info {};
58         Url url;
59         std::string title;
60         Cluster* cluster = nullptr;
61         Url redirectUrl;
62         article_index_t idx = article_index_t(0);
63         offset_t offset;
64 
65       public:
Dirent()66         Dirent()
67           : mimeType(0),
68             url(),
69             title(),
70             redirectUrl()
71         {
72           info.d.clusterNumber = cluster_index_t(0);
73           info.d.blobNumber = blob_index_t(0);
74         }
75 
Dirent(Url url_)76         explicit Dirent(Url url_ )
77           : Dirent()
78           { url = url_; }
79 
getNamespace()80         char getNamespace() const               { return url.getNs(); }
getTitle()81         const std::string& getTitle() const     { return title.empty() ? url.getUrl() : title; }
setTitle(const std::string & title_)82         void setTitle(const std::string& title_) { title = title_; }
getUrl()83         const std::string& getUrl() const       { return url.getUrl(); }
getFullUrl()84         const Url& getFullUrl() const { return url; }
setUrl(Url url_)85         void setUrl(Url url_) {
86           url = url_;
87         }
88 
getVersion()89         uint32_t getVersion() const            { return version; }
90 
setRedirectUrl(Url redirectUrl_)91         void setRedirectUrl(Url redirectUrl_)     { redirectUrl = redirectUrl_; }
getRedirectUrl()92         const Url& getRedirectUrl() const         { return redirectUrl; }
setRedirect(const Dirent * target)93         void setRedirect(const Dirent* target) {
94           info.r.redirectDirent = target;
95           mimeType = redirectMimeType;
96         }
getRedirectIndex()97         article_index_t getRedirectIndex() const      { return isRedirect() ? info.r.redirectDirent->getIdx() : article_index_t(0); }
98 
setMimeType(uint16_t mime)99         void setMimeType(uint16_t mime)
100         {
101           mimeType = mime;
102         }
103 
setLinktarget()104         void setLinktarget()
105         {
106           ASSERT(mimeType, ==, 0);
107           mimeType = linktargetMimeType;
108         }
109 
setDeleted()110         void setDeleted()
111         {
112           ASSERT(mimeType, ==, 0);
113           mimeType = deletedMimeType;
114         }
115 
116 
setIdx(article_index_t idx_)117         void setIdx(article_index_t idx_)      { idx = idx_; }
getIdx()118         article_index_t getIdx() const         { return idx; }
119 
120 
setCluster(zim::writer::Cluster * _cluster)121         void setCluster(zim::writer::Cluster* _cluster)
122         {
123           ASSERT(isArticle(), ==, true);
124           cluster = _cluster;
125           info.d.blobNumber = _cluster->count();
126         }
127 
getClusterNumber()128         cluster_index_t getClusterNumber() const {
129           return cluster ? cluster->getClusterIndex() : info.d.clusterNumber;
130         }
getBlobNumber()131         blob_index_t  getBlobNumber() const {
132           return isRedirect() ? blob_index_t(0) : info.d.blobNumber;
133         }
134 
isRedirect()135         bool isRedirect() const                 { return mimeType == redirectMimeType; }
isLinktarget()136         bool isLinktarget() const               { return mimeType == linktargetMimeType; }
isDeleted()137         bool isDeleted() const                  { return mimeType == deletedMimeType; }
isArticle()138         bool isArticle() const                  { return !isRedirect() && !isLinktarget() && !isDeleted(); }
getMimeType()139         uint16_t getMimeType() const            { return mimeType; }
getDirentSize()140         size_t getDirentSize() const
141         {
142           size_t ret = (isRedirect() ? 12 : 16) + url.getUrl().size() + 2;
143           if (title != url.getUrl())
144             ret += title.size();
145           return ret;
146         }
147 
getOffset()148         offset_t getOffset() const { return offset; }
setOffset(offset_t o)149         void setOffset(offset_t o) { offset = o; }
150 
setArticle(uint16_t mimeType_,cluster_index_t clusterNumber_,blob_index_t blobNumber_)151         void setArticle(uint16_t mimeType_, cluster_index_t clusterNumber_, blob_index_t blobNumber_)
152         {
153           ASSERT(mimeType, ==, 0);
154           mimeType = mimeType_;
155           info.d.clusterNumber = clusterNumber_;
156           info.d.blobNumber = blobNumber_;
157         }
158 
159         void write(int out_fd) const;
160 
161         friend bool compareUrl(const Dirent* d1, const Dirent* d2);
162         friend inline bool compareTitle(const Dirent* d1, const Dirent* d2);
163     };
164 
165 
compareUrl(const Dirent * d1,const Dirent * d2)166     inline bool compareUrl(const Dirent* d1, const Dirent* d2)
167     {
168       return d1->url < d2->url;
169     }
compareTitle(const Dirent * d1,const Dirent * d2)170     inline bool compareTitle(const Dirent* d1, const Dirent* d2)
171     {
172       return d1->url.getNs() < d2->url.getNs()
173         || (d1->url.getNs() == d2->url.getNs() && d1->getTitle() < d2->getTitle());
174     }
175   }
176 }
177 
178 #endif // ZIM_WRITER_DIRENT_H
179 
180