sbDurationPropertyInfo.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 #include "sbDurationPropertyInfo.h"
28 #include <nsAutoPtr.h>
29 #include <nsComponentManagerUtils.h>
30 #include <nsServiceManagerUtils.h>
31 
32 #include <prtime.h>
33 #include <prprf.h>
34 
35 #include <sbLockUtils.h>
36 
37 static const char *gsFmtRadix10 = "%lld";
38 static const char *gsSortFmtRadix10 = "%+020lld";
39 static const char *gsFmtMilliseconds10 = "%04d";
40 
43 
44 NS_INTERFACE_TABLE_HEAD(sbDurationPropertyInfo)
45 NS_INTERFACE_TABLE_BEGIN
46 NS_INTERFACE_TABLE_ENTRY(sbDurationPropertyInfo, sbIDurationPropertyInfo)
47 NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(sbDurationPropertyInfo, sbIPropertyInfo, sbIDurationPropertyInfo)
48 NS_INTERFACE_TABLE_END
49 NS_INTERFACE_TABLE_TAIL_INHERITING(sbPropertyInfo)
50 
51 sbDurationPropertyInfo::sbDurationPropertyInfo()
52 : mDurationInversed(PR_FALSE)
53 , mDurationDisplayMillisec(PR_FALSE)
54 , mMinMaxDurationLock(nsnull)
55 , mMinDuration(0)
56 , mMaxDuration(LL_MAXINT)
57 , mAppLocaleLock(nsnull)
58 , mDateTimeFormatLock(nsnull)
59 {
60  mType = NS_LITERAL_STRING("duration");
61 
62  mMinMaxDurationLock = PR_NewLock();
63  NS_ASSERTION(mMinMaxDurationLock,
64  "sbDurationPropertyInfo::mMinMaxDurationLock failed to create lock!");
65 
66  mAppLocaleLock = PR_NewLock();
67  NS_ASSERTION(mAppLocaleLock,
68  "sbDurationPropertyInfo::mAppLocaleLock failed to create lock!");
69 
70  mDateTimeFormatLock = PR_NewLock();
71  NS_ASSERTION(mDateTimeFormatLock,
72  "sbDurationPropertyInfo::mDateTimeFormatLock failed to create lock!");
73 }
74 
76 {
78  PR_DestroyLock(mMinMaxDurationLock);
79  }
80  if(mAppLocaleLock) {
81  PR_DestroyLock(mAppLocaleLock);
82  }
84  PR_DestroyLock(mDateTimeFormatLock);
85  }
86 }
87 
89 {
90  nsresult rv;
91 
92  rv = sbPropertyInfo::Init();
93  NS_ENSURE_SUCCESS(rv, rv);
94 
95  rv = InitializeOperators();
96  NS_ENSURE_SUCCESS(rv, rv);
97 
98  return NS_OK;
99 }
100 
101 nsresult
103 {
104  nsresult rv;
105  nsAutoString op;
106  nsRefPtr<sbPropertyOperator> propOp;
107 
108  rv = sbPropertyInfo::GetOPERATOR_EQUALS(op);
109  NS_ENSURE_SUCCESS(rv, rv);
110  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.equal"));
111  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
112  rv = mOperators.AppendObject(propOp);
113  NS_ENSURE_SUCCESS(rv, rv);
114 
115  rv = sbPropertyInfo::GetOPERATOR_NOTEQUALS(op);
116  NS_ENSURE_SUCCESS(rv, rv);
117  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.notequal"));
118  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
119  rv = mOperators.AppendObject(propOp);
120  NS_ENSURE_SUCCESS(rv, rv);
121 
122  rv = sbPropertyInfo::GetOPERATOR_GREATER(op);
123  NS_ENSURE_SUCCESS(rv, rv);
124  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.greater"));
125  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
126  rv = mOperators.AppendObject(propOp);
127  NS_ENSURE_SUCCESS(rv, rv);
128 
129  rv = sbPropertyInfo::GetOPERATOR_GREATEREQUAL(op);
130  NS_ENSURE_SUCCESS(rv, rv);
131  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.greaterequal"));
132  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
133  rv = mOperators.AppendObject(propOp);
134  NS_ENSURE_SUCCESS(rv, rv);
135 
136  rv = sbPropertyInfo::GetOPERATOR_LESS(op);
137  NS_ENSURE_SUCCESS(rv, rv);
138  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.less"));
139  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
140  rv = mOperators.AppendObject(propOp);
141  NS_ENSURE_SUCCESS(rv, rv);
142 
143  rv = sbPropertyInfo::GetOPERATOR_LESSEQUAL(op);
144  NS_ENSURE_SUCCESS(rv, rv);
145  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.lessequal"));
146  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
147  rv = mOperators.AppendObject(propOp);
148  NS_ENSURE_SUCCESS(rv, rv);
149 
150  rv = sbPropertyInfo::GetOPERATOR_BETWEEN(op);
151  NS_ENSURE_SUCCESS(rv, rv);
152  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.duration.between"));
153  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
154  rv = mOperators.AppendObject(propOp);
155  NS_ENSURE_SUCCESS(rv, rv);
156 
157  return NS_OK;
158 }
159 
160 NS_IMETHODIMP sbDurationPropertyInfo::Validate(const nsAString & aValue, PRBool *_retval)
161 {
162  NS_ENSURE_ARG_POINTER(_retval);
163 
164  PRInt64 value = 0;
165  NS_ConvertUTF16toUTF8 narrow(aValue);
166  *_retval = PR_TRUE;
167 
168  if(PR_sscanf(narrow.get(), gsFmtRadix10, &value) != 1) {
169  *_retval = PR_FALSE;
170  return NS_OK;
171  }
172 
174  if(value < mMinDuration ||
175  value > mMaxDuration) {
176  *_retval = PR_FALSE;
177  }
178 
179  return NS_OK;
180 }
181 
182 NS_IMETHODIMP sbDurationPropertyInfo::Sanitize(const nsAString & aValue, nsAString & _retval)
183 {
184  return NS_ERROR_NOT_IMPLEMENTED;
185 }
186 
187 NS_IMETHODIMP sbDurationPropertyInfo::Format(const nsAString & aValue, nsAString & _retval)
188 {
189  PRInt64 value = 0;
190  NS_ConvertUTF16toUTF8 narrow(aValue);
191 
192  if(PR_sscanf(narrow.get(), gsFmtRadix10, &value) != 1) {
193  return NS_ERROR_INVALID_ARG;
194  }
195 
196 /*
197  XXXlone> There is fundamentally no reason for Format to validate the range of
198  its input. it does make sense to validate that the value is a number, but we
199  want to let people format values that are lower than MinDuration and longer
200  than MaxDuration. Ultimately, we should review Format, MakeSortable and
201  makeSearchable in all sbIPropertyInfo classes, and go through the steps needed
202  to make them all 'permissive', ie, accepting any value that can be interpreted
203  as the right type, but regardless of what the value is and whether or not it
204  matches the constraints on the property (eg, min/max).
205 
206  {
207  sbSimpleAutoLock lock(mMinMaxDurationLock);
208  if(value < mMinDuration ||
209  value > mMaxDuration) {
210  return NS_ERROR_INVALID_ARG;
211  }
212  }
213 */
214 
215  nsAutoString out;
216  sbSimpleAutoLock lockLocale(mAppLocaleLock);
217 
218  nsresult rv;
219 
220  if(!mAppLocale) {
221  nsCOMPtr<nsILocaleService> localeService =
222  do_GetService("@mozilla.org/intl/nslocaleservice;1", &rv);
223  NS_ENSURE_SUCCESS(rv, rv);
224 
225  rv = localeService->GetApplicationLocale(getter_AddRefs(mAppLocale));
226  NS_ENSURE_SUCCESS(rv, rv);
227  }
228 
229  sbSimpleAutoLock lockFormatter(mDateTimeFormatLock);
230  if(!mDateTimeFormat) {
231  mDateTimeFormat = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
232  NS_ENSURE_SUCCESS(rv, rv);
233  }
234 
235  PRExplodedTime referenceTime = {0}, explodedTime = {0};
236  PR_ExplodeTime((PRTime) 0, PR_GMTParameters, &referenceTime);
237  PR_ExplodeTime((PRTime)value, PR_GMTParameters, &explodedTime);
238 
239  PRInt32 delta = explodedTime.tm_year - referenceTime.tm_year;
240  if(delta) {
241  out.AppendInt(delta);
242  out.AppendLiteral("Y");
243  }
244 
245  delta = explodedTime.tm_month - referenceTime.tm_month;
246  if(delta) {
247  out.AppendInt(delta);
248  out.AppendLiteral("M");
249  }
250 
251  delta = explodedTime.tm_mday - referenceTime.tm_mday;
252  if(delta) {
253  out.AppendInt(delta);
254  out.AppendLiteral("D ");
255  }
256 
257  PRInt32 hours = explodedTime.tm_hour - referenceTime.tm_hour;
258  if(hours) {
259  out.AppendInt(hours);
260  out.AppendLiteral(":");
261  }
262 
263  PRInt32 mins = explodedTime.tm_min - referenceTime.tm_min;
264  if(hours && mins < 10 ) {
265  out.AppendLiteral("0");
266  }
267 
268  out.AppendInt(mins);
269  out.AppendLiteral(":");
270 
271  PRInt32 secs = explodedTime.tm_sec - referenceTime.tm_sec;
272  if(secs < 10) {
273  out.AppendLiteral("0");
274  }
275 
276  out.AppendInt(secs);
277 
279  delta = (explodedTime.tm_usec - referenceTime.tm_usec)
280  / PR_USEC_PER_MSEC;
281 
282  char c[32] = {0};
283  PR_snprintf(c, 32, gsFmtMilliseconds10, delta);
284 
285  out.AppendLiteral(".");
286  out.Append(NS_ConvertUTF8toUTF16(c));
287  }
288 
289  _retval = out;
290 
291  return NS_OK;
292 }
293 
294 NS_IMETHODIMP sbDurationPropertyInfo::MakeSearchable(const nsAString & aValue, nsAString & _retval)
295 {
296  nsresult rv;
297  PRInt64 value = 0;
298  NS_ConvertUTF16toUTF8 narrow(aValue);
299 
300  _retval = aValue;
301  _retval.StripWhitespace();
302 
304 
305  if(PR_sscanf(narrow.get(), gsFmtRadix10, &value) != 1) {
306  _retval = EmptyString();
307  return NS_ERROR_INVALID_ARG;
308  }
309 
310  char out[32] = {0};
311  if(PR_snprintf(out, 32, gsSortFmtRadix10, value) == (PRUint32)-1) {
312  rv = NS_ERROR_FAILURE;
313  _retval = EmptyString();
314  }
315  else {
316  NS_ConvertUTF8toUTF16 wide(out);
317  rv = NS_OK;
318  _retval = wide;
319  }
320 
321  return rv;
322 }
323 
324 NS_IMETHODIMP sbDurationPropertyInfo::GetMinDuration(PRInt64 *aMinDuration)
325 {
326  NS_ENSURE_ARG_POINTER(aMinDuration);
327 
329  *aMinDuration = mMinDuration;
330 
331  return NS_OK;
332 }
333 NS_IMETHODIMP sbDurationPropertyInfo::SetMinDuration(PRInt64 aMinDuration)
334 {
335  NS_ENSURE_ARG(aMinDuration > -1);
336 
338  mMinDuration = aMinDuration;
339 
340  return NS_OK;
341 }
342 
343 NS_IMETHODIMP sbDurationPropertyInfo::GetMaxDuration(PRInt64 *aMaxDuration)
344 {
345  NS_ENSURE_ARG_POINTER(aMaxDuration);
346 
348  *aMaxDuration = mMaxDuration;
349 
350  return NS_OK;
351 }
352 NS_IMETHODIMP sbDurationPropertyInfo::SetMaxDuration(PRInt64 aMaxDuration)
353 {
354  NS_ENSURE_ARG(aMaxDuration > -1);
355 
357  mMaxDuration = aMaxDuration;
358 
359  return NS_OK;
360 }
361 
362 NS_IMETHODIMP sbDurationPropertyInfo::GetDurationInverse(PRBool *aDurationInverse)
363 {
364  NS_ENSURE_ARG_POINTER(aDurationInverse);
365  *aDurationInverse = mDurationInversed;
366  return NS_OK;
367 }
368 NS_IMETHODIMP sbDurationPropertyInfo::SetDurationInverse(PRBool aDurationInverse)
369 {
370  mDurationInversed = aDurationInverse;
371  return NS_OK;
372 }
373 
374 NS_IMETHODIMP sbDurationPropertyInfo::GetDurationWithMilliseconds(PRBool *aDurationWithMilliseconds)
375 {
376  NS_ENSURE_ARG_POINTER(aDurationWithMilliseconds);
377  *aDurationWithMilliseconds = mDurationDisplayMillisec;
378  return NS_OK;
379 }
380 NS_IMETHODIMP sbDurationPropertyInfo::SetDurationWithMilliseconds(PRBool aDurationWithMilliseconds)
381 {
382  mDurationDisplayMillisec = aDurationWithMilliseconds;
383  return NS_OK;
384 }
return NS_OK
onPageChanged aValue
Definition: FeedWriter.js:1395
static const char * gsFmtMilliseconds10
The property information specific to date/time fields.
NS_IMETHOD Validate(const nsAString &aValue, PRBool *_retval)
NS_IMPL_ADDREF_INHERITED(sbDurationPropertyInfo, sbPropertyInfo)
NS_IMPL_RELEASE_INHERITED(sbDurationPropertyInfo, sbPropertyInfo)
NS_IMETHOD Format(const nsAString &aValue, nsAString &_retval)
An interface used to describe a metadata property for use by the UI and other sbILibrary interfaces (...
NS_IMETHOD MakeSearchable(const nsAString &aValue, nsAString &_retval)
nsCOMPtr< nsILocale > mAppLocale
countRef value
Definition: FeedWriter.js:1423
static const char * gsSortFmtRadix10
nsCOMArray< sbIPropertyOperator > mOperators
static const char * gsFmtRadix10
nsCOMPtr< nsIDateTimeFormat > mDateTimeFormat
NS_IMETHOD Sanitize(const nsAString &aValue, nsAString &_retval)