1 /******************************************************************************
2 * $Id: NSStringAdditions.m 13162 2012-01-14 17:12:04Z livings124 $
4 * Copyright (c) 2005-2012 Transmission authors and contributors
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
25 #import "NSStringAdditions.h"
27 #import <transmission.h>
30 @interface NSString (Private)
32 + (NSString *) stringForFileSize: (uint64_t) size showUnitUnless: (NSString *) notAllowedUnit
33 unitsUsed: (NSString **) unitUsed;
35 + (NSString *) stringForSpeed: (CGFloat) speed kb: (NSString *) kb mb: (NSString *) mb gb: (NSString *) gb;
39 @implementation NSString (NSStringAdditions)
41 + (NSString *) ellipsis
43 return [NSString stringWithUTF8String: "\xE2\x80\xA6"];
46 - (NSString *) stringByAppendingEllipsis
48 return [self stringByAppendingString: [NSString ellipsis]];
51 + (NSString *) formattedUInteger: (NSUInteger) value
53 NSNumberFormatter * numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
54 [numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
55 [numberFormatter setMaximumFractionDigits: 0];
57 return [numberFormatter stringFromNumber: [NSNumber numberWithUnsignedInteger: value]];
60 + (NSString *) stringForFileSize: (uint64_t) size
62 return [self stringForFileSize: size showUnitUnless: nil unitsUsed: nil];
65 + (NSString *) stringForFilePartialSize: (uint64_t) partialSize fullSize: (uint64_t) fullSize
68 NSString * fullString = [self stringForFileSize: fullSize showUnitUnless: nil unitsUsed: &units];
69 NSString * partialString = [self stringForFileSize: partialSize showUnitUnless: units unitsUsed: nil];
71 return [NSString stringWithFormat: NSLocalizedString(@"%@ of %@", "file size string"), partialString, fullString];
74 + (NSString *) stringForSpeed: (CGFloat) speed
76 return [self stringForSpeed: speed
77 kb: NSLocalizedString(@"KB/s", "Transfer speed (kilobytes per second)")
78 mb: NSLocalizedString(@"MB/s", "Transfer speed (megabytes per second)")
79 gb: NSLocalizedString(@"GB/s", "Transfer speed (gigabytes per second)")];
82 + (NSString *) stringForSpeedAbbrev: (CGFloat) speed
84 return [self stringForSpeed: speed kb: @"K" mb: @"M" gb: @"G"];
87 + (NSString *) stringForRatio: (CGFloat) ratio
89 //N/A is different than libtransmission's
90 if ((int)ratio == TR_RATIO_NA)
91 return NSLocalizedString(@"N/A", "No Ratio");
92 else if ((int)ratio == TR_RATIO_INF)
93 return [NSString stringWithUTF8String: "\xE2\x88\x9E"];
97 return [NSString localizedStringWithFormat: @"%.2f", tr_truncd(ratio, 2)];
98 else if (ratio < 100.0)
99 return [NSString localizedStringWithFormat: @"%.1f", tr_truncd(ratio, 1)];
101 return [NSString localizedStringWithFormat: @"%.0f", tr_truncd(ratio, 0)];
105 + (NSString *) percentString: (CGFloat) progress longDecimals: (BOOL) longDecimals
109 else if (longDecimals)
110 return [NSString localizedStringWithFormat: @"%.2f%%", tr_truncd(progress * 100.0, 2)];
112 return [NSString localizedStringWithFormat: @"%.1f%%", tr_truncd(progress * 100.0, 1)];
115 + (NSString *) timeString: (uint64_t) seconds showSeconds: (BOOL) showSeconds
117 return [NSString timeString: seconds showSeconds: showSeconds maxFields: NSUIntegerMax];
120 + (NSString *) timeString: (uint64_t) seconds showSeconds: (BOOL) showSeconds maxFields: (NSUInteger) max
122 NSAssert(max > 0, @"Cannot generate a time string with no fields");
124 NSMutableArray * timeArray = [NSMutableArray arrayWithCapacity: MIN(max, 5)];
125 NSUInteger remaining = seconds; //causes problems for some users when it's a uint64_t
127 if (seconds >= 31557600) //official amount of seconds in one year
129 const NSUInteger years = remaining / 31557600;
131 [timeArray addObject: NSLocalizedString(@"1 year", "time string")];
133 [timeArray addObject: [NSString stringWithFormat: NSLocalizedString(@"%u years", "time string"), years]];
134 remaining %= 31557600;
137 if (max > 0 && seconds >= (24 * 60 * 60))
139 const NSUInteger days = remaining / (24 * 60 * 60);
141 [timeArray addObject: NSLocalizedString(@"1 day", "time string")];
143 [timeArray addObject: [NSString stringWithFormat: NSLocalizedString(@"%u days", "time string"), days]];
144 remaining %= (24 * 60 * 60);
147 if (max > 0 && seconds >= (60 * 60))
149 [timeArray addObject: [NSString stringWithFormat: NSLocalizedString(@"%u hr", "time string"), remaining / (60 * 60)]];
150 remaining %= (60 * 60);
153 if (max > 0 && (!showSeconds || seconds >= 60))
155 [timeArray addObject: [NSString stringWithFormat: NSLocalizedString(@"%u min", "time string"), remaining / 60]];
159 if (max > 0 && showSeconds)
160 [timeArray addObject: [NSString stringWithFormat: NSLocalizedString(@"%u sec", "time string"), remaining]];
162 return [timeArray componentsJoinedByString: @" "];
165 - (NSComparisonResult) compareNumeric: (NSString *) string
167 const NSStringCompareOptions comparisonOptions = NSNumericSearch | NSForcedOrderingSearch;
168 return [self compare: string options: comparisonOptions range: NSMakeRange(0, [self length]) locale: [NSLocale currentLocale]];
171 - (NSArray *) betterComponentsSeparatedByCharactersInSet: (NSCharacterSet *) separator
173 NSMutableArray * components = [NSMutableArray array];
176 while (i < [self length])
178 const NSRange range = [self rangeOfCharacterFromSet: separator options: 0 range: NSMakeRange(i, [self length]-i)];
180 if (range.location == NSNotFound)
182 [components addObject: [self substringFromIndex: i]];
185 else if (range.location != i)
187 const NSUInteger length = range.location - i;
188 [components addObject: [self substringWithRange: NSMakeRange(i, length)]];
201 @implementation NSString (Private)
203 + (NSString *) stringForFileSize: (uint64_t) size showUnitUnless: (NSString *) notAllowedUnit
204 unitsUsed: (NSString **) unitUsed
206 double convertedSize;
209 if (size < pow(1000, 2))
211 convertedSize = size / 1000.0;
212 unit = NSLocalizedString(@"KB", "File size - kilobytes");
213 decimals = convertedSize >= 10.0 ? 0 : 1;
215 else if (size < pow(1000, 3))
217 convertedSize = size / powf(1000.0, 2);
218 unit = NSLocalizedString(@"MB", "File size - megabytes");
221 else if (size < pow(1000, 4))
223 convertedSize = size / powf(1000.0, 3);
224 unit = NSLocalizedString(@"GB", "File size - gigabytes");
229 convertedSize = size / powf(1000.0, 4);
230 unit = NSLocalizedString(@"TB", "File size - terabytes");
231 decimals = 3; //guessing on this one
234 //match Finder's behavior
235 NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
236 [numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
237 [numberFormatter setMinimumFractionDigits: 0];
238 [numberFormatter setMaximumFractionDigits: decimals];
240 NSString * fileSizeString = [numberFormatter stringFromNumber: [NSNumber numberWithFloat: convertedSize]];
241 [numberFormatter release];
243 if (!notAllowedUnit || ![unit isEqualToString: notAllowedUnit])
244 fileSizeString = [fileSizeString stringByAppendingFormat: @" %@", unit];
249 return fileSizeString;
252 + (NSString *) stringForSpeed: (CGFloat) speed kb: (NSString *) kb mb: (NSString *) mb gb: (NSString *) gb
254 if (speed <= 999.95) //0.0 KB/s to 999.9 KB/s
255 return [NSString localizedStringWithFormat: @"%.1f %@", speed, kb];
259 if (speed <= 99.995) //1.00 MB/s to 99.99 MB/s
260 return [NSString localizedStringWithFormat: @"%.2f %@", speed, mb];
261 else if (speed <= 999.95) //100.0 MB/s to 999.9 MB/s
262 return [NSString localizedStringWithFormat: @"%.1f %@", speed, mb];
264 return [NSString localizedStringWithFormat: @"%.2f %@", (speed / 1000.0), gb];