Tizen 2.0 Release
[framework/web/wrt-commons.git] / modules / utils / src / folder_size.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  *
18  * @file        folder_size.cpp
19  * @author      Jaroslaw Osmanski (j.osmanski@samsung.com)
20  * @version     1.0
21  * @brief       Implementation for function calculating directory size
22  */
23 #include <stddef.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fts.h>
28
29 #include <sstream>
30 #include <vector>
31
32 #include <dpl/log/log.h>
33 #include <dpl/foreach.h>
34 #include <dpl/utils/folder_size.h>
35
36 namespace Utils {
37
38 size_t getFolderSize(const std::string& path)
39 {
40     size_t size = 0;
41     FTS *fts;
42     FTSENT *ftsent;
43     char * const paths[] = {const_cast<char * const>(path.c_str()), NULL};
44
45     if ((fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
46         //ERROR
47         int error = errno;
48         LogWarning(__PRETTY_FUNCTION__ << ": fts_open failed with error: "
49                 << strerror(error));
50         return 0;
51     }
52
53     while ((ftsent = fts_read(fts)) != NULL) {
54         switch (ftsent->fts_info) {
55             case FTS_DP:
56             case FTS_DC:
57                 //directory in postorder and directory causing a loop
58                 break;
59             case FTS_F:
60             case FTS_D:
61             case FTS_NSOK:
62             case FTS_SL:
63             case FTS_SLNONE:
64             case FTS_DEFAULT:
65                 //regular files and other objects that can be counted
66                 size += ftsent->fts_statp->st_size;
67                 break;
68             case FTS_NS:
69             case FTS_DOT:
70             case FTS_DNR:
71             case FTS_ERR:
72             default:
73                 LogWarning(__PRETTY_FUNCTION__
74                         << ": traversal failed on file: "
75                         << ftsent->fts_path
76                         << " with error: "
77                         << strerror(ftsent->fts_errno));
78                 return 0;
79         }
80     }
81
82     if (fts_close(fts) == -1) {
83         int error = errno;
84         LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
85                 << strerror(error));
86         return 0;
87     }
88
89     return size;
90 }
91
92
93
94
95
96 namespace {
97 #define DECLARE_PREFIX_STRUCT(name)     \
98 struct Prefix##name                     \
99 {                                       \
100   static std::string get()              \
101   {                                     \
102         return std::string(#name);      \
103   }                                     \
104 };                                      \
105
106 DECLARE_PREFIX_STRUCT(B)
107 DECLARE_PREFIX_STRUCT(KB)
108 DECLARE_PREFIX_STRUCT(MB)
109 DECLARE_PREFIX_STRUCT(GB)
110
111 #undef DECLARE_PREFIX_STRUCT
112
113
114 const int stepSize = 1024;
115 template<typename... Rest>
116 struct Pre;
117
118
119 template<typename Postfix, typename... Rest>
120 struct Pre<Postfix, Rest...>
121 {
122     static const double value;
123     static std::string printSize(double fileSize)
124     {
125         if(fileSize >= Pre<Rest...>::value) {
126             double now = fileSize / Pre<Rest...>::value;
127             std::ostringstream outputStream;
128             outputStream.setf(std::ios::fixed, std::ios::floatfield);
129             outputStream.precision(2);
130             outputStream << now << Postfix::get();
131             return outputStream.str();
132         } else {
133             return Pre<Rest...>::printSize(fileSize);
134         }
135
136     }
137 };
138
139 template<>
140 struct Pre<>
141 {
142         static const double value;
143         static std::string printSize(double /*fileSize*/)
144         {
145                 return "0B";
146         }
147
148 };
149
150 const double Pre<>::value = 1.0;
151 template<typename Postfix, typename... Params> const double Pre<Postfix, Params...>::value(Pre<>::value * stepSize);
152
153
154 typedef Pre<PrefixGB, PrefixMB, PrefixKB, PrefixB> FolderSizeToStringType;
155
156
157 } //anonymous namespace
158
159
160 DPL::String fromFileSizeString(size_t fileSize)
161 {
162
163     std::string output =
164         FolderSizeToStringType::printSize(static_cast<double>(fileSize));
165     return DPL::FromUTF8String(output);
166 }
167
168 } // end of namespace Utils