aboutsummaryrefslogtreecommitdiff
path: root/coreutils/shuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/shuf.c')
-rw-r--r--coreutils/shuf.c58
1 files changed, 52 insertions, 6 deletions
diff --git a/coreutils/shuf.c b/coreutils/shuf.c
index 56ba03aad..466969745 100644
--- a/coreutils/shuf.c
+++ b/coreutils/shuf.c
@@ -66,6 +66,12 @@ static void shuffle_lines(char **lines, unsigned numlines, unsigned outlines)
66 } 66 }
67} 67}
68 68
69/* We can handle insanity like this:
70 * shuf -i 333333333333333333333333333333001-333333333333333333333333333333019
71 * but do we want to have +200 bytes of code (~40% code growth)?
72 */
73#define COMMON_PREFIX_HACK 0
74
69int shuf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 75int shuf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
70int shuf_main(int argc, char **argv) 76int shuf_main(int argc, char **argv)
71{ 77{
@@ -76,6 +82,11 @@ int shuf_main(int argc, char **argv)
76 unsigned numlines, outlines; 82 unsigned numlines, outlines;
77 unsigned i; 83 unsigned i;
78 char eol; 84 char eol;
85#if COMMON_PREFIX_HACK
86 unsigned pfx_len = 0;
87 unsigned padding_width = padding_width;
88 const char *pfx = pfx;
89#endif
79 90
80 opts = getopt32(argv, "^" 91 opts = getopt32(argv, "^"
81 OPT_STR 92 OPT_STR
@@ -104,10 +115,40 @@ int shuf_main(int argc, char **argv)
104 if (!dash) { 115 if (!dash) {
105 bb_error_msg_and_die("bad range '%s'", opt_i_str); 116 bb_error_msg_and_die("bad range '%s'", opt_i_str);
106 } 117 }
107 *dash = '\0'; 118 *dash++ = '\0';
119#if COMMON_PREFIX_HACK
120 {
121 const char *a = opt_i_str;
122 const char *b = dash;
123 /* Skip leading zeros (they may mask that common prefix does exist) */
124 while (*a == '0') a++;
125 while (*b == '0') b++;
126 /* Do we have a common prefix (long enough to bother)? */
127 padding_width = strlen(a);
128 if (padding_width > 5 && padding_width == strlen(b)) {
129 /* How long is it? */
130 pfx = a;
131 while (isdigit(*a) && *a == *b
132 && a[1] /* "111111-111111" case: avoid xatoull("") */
133 ) {
134 a++;
135 b++;
136 }
137 pfx_len = a - pfx; /* can end up being 0 */
138 padding_width -= pfx_len;
139 } else {
140 /* Undo leading zero 'eating' (think "0-9") */
141 a = opt_i_str;
142 b = dash;
143 }
144 lo = xatoull(a);
145 hi = xatoull(b);
146 }
147#else
108 lo = xatoull(opt_i_str); 148 lo = xatoull(opt_i_str);
109 hi = xatoull(dash + 1); 149 hi = xatoull(dash);
110 *dash = '-'; 150#endif
151 dash[-1] = '-';
111 if (hi < lo) 152 if (hi < lo)
112 bb_error_msg_and_die("bad range '%s'", opt_i_str); 153 bb_error_msg_and_die("bad range '%s'", opt_i_str);
113 hi -= lo; 154 hi -= lo;
@@ -165,9 +206,14 @@ int shuf_main(int argc, char **argv)
165 eol = '\0'; 206 eol = '\0';
166 207
167 for (i = numlines - outlines; i < numlines; i++) { 208 for (i = numlines - outlines; i < numlines; i++) {
168 if (opts & OPT_i) 209 if (opts & OPT_i) {
169 printf("%"LL_FMT"u%c", lo + (uintptr_t)lines[i], eol); 210#if COMMON_PREFIX_HACK
170 else 211 if (pfx_len != 0)
212 printf("%.*s%0*llu%c", pfx_len, pfx, padding_width, lo + (uintptr_t)lines[i], eol);
213 else
214#endif
215 printf("%llu%c", lo + (uintptr_t)lines[i], eol);
216 } else
171 printf("%s%c", lines[i], eol); 217 printf("%s%c", lines[i], eol);
172 } 218 }
173 219