aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-04-12 14:47:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-04-12 14:47:24 +0200
commit238dab322a630b493843a6bdf3203e93db87469a (patch)
treece17e0be8dd7a4e3d016384c920b60f8b9942563
parent853cfe927fd656a2688ac2bfc81c69e1004c44df (diff)
downloadbusybox-w32-238dab322a630b493843a6bdf3203e93db87469a.tar.gz
busybox-w32-238dab322a630b493843a6bdf3203e93db87469a.tar.bz2
busybox-w32-238dab322a630b493843a6bdf3203e93db87469a.zip
shuf: add (disabled) code to support very long numbers in -i LO-HI
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/shuf.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/coreutils/shuf.c b/coreutils/shuf.c
index 337366b45..fe0358e07 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 3333333333333333333333333333333333333333333333333333333333333123456789001-3333333333333333333333333333333333333333333333333333333333333123456789019
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,46 @@ 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++;
133 b++;
134 }
135 if (*a == '\0') {
136 /* "123456-123456", and we 'ate' all of them */
137 /* prevent trying to xatoull("") */
138 a--;
139 b--;
140 }
141 pfx_len = a - opt_i_str; /* can end up being 0 */
142 padding_width -= pfx_len;
143 lo = xatoull(a);
144 hi = xatoull(b);
145 } else {
146 /* Undo leading zero 'eating' (think "0-9") */
147 a = opt_i_str;
148 b = dash;
149 }
150 lo = xatoull(a);
151 hi = xatoull(b);
152 }
153#else
108 lo = xatoull(opt_i_str); 154 lo = xatoull(opt_i_str);
109 hi = xatoull(dash + 1); 155 hi = xatoull(dash);
110 *dash = '-'; 156#endif
157 dash[-1] = '-';
111 if (hi < lo) 158 if (hi < lo)
112 bb_error_msg_and_die("bad range '%s'", opt_i_str); 159 bb_error_msg_and_die("bad range '%s'", opt_i_str);
113 hi -= lo; 160 hi -= lo;
@@ -165,9 +212,14 @@ int shuf_main(int argc, char **argv)
165 eol = '\0'; 212 eol = '\0';
166 213
167 for (i = numlines - outlines; i < numlines; i++) { 214 for (i = numlines - outlines; i < numlines; i++) {
168 if (opts & OPT_i) 215 if (opts & OPT_i) {
169 printf("%llu%c", lo + (uintptr_t)lines[i], eol); 216#if COMMON_PREFIX_HACK
170 else 217 if (pfx_len != 0)
218 printf("%.*s%0*llu%c", pfx_len, pfx, padding_width, lo + (uintptr_t)lines[i], eol);
219 else
220#endif
221 printf("%llu%c", lo + (uintptr_t)lines[i], eol);
222 } else
171 printf("%s%c", lines[i], eol); 223 printf("%s%c", lines[i], eol);
172 } 224 }
173 225