| 264 | */ |
| 265 | // TODO(diamondm) consider using Arrays.toString() for array parameters |
| 266 | public static String lenientFormat( |
| 267 | @Nullable String template, @Nullable Object @Nullable ... args) { |
| 268 | template = String.valueOf(template); // null -> "null" |
| 269 | |
| 270 | if (args == null) { |
| 271 | args = new Object[] {"(Object[])null"}; |
| 272 | } |
| 273 | |
| 274 | // start substituting the arguments into the '%s' placeholders |
| 275 | StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); |
| 276 | int templateStart = 0; |
| 277 | int i = 0; |
| 278 | while (i < args.length) { |
| 279 | int placeholderStart = template.indexOf("%s", templateStart); |
| 280 | if (placeholderStart == -1) { |
| 281 | break; |
| 282 | } |
| 283 | builder.append(template, templateStart, placeholderStart); |
| 284 | builder.append(lenientToString(args[i++])); |
| 285 | templateStart = placeholderStart + 2; |
| 286 | } |
| 287 | builder.append(template, templateStart, template.length()); |
| 288 | |
| 289 | // if we run out of placeholders, append the extra args in square brackets |
| 290 | if (i < args.length) { |
| 291 | String prefix = " ["; |
| 292 | for (; i < args.length; i++) { |
| 293 | builder.append(prefix); |
| 294 | builder.append(lenientToString(args[i])); |
| 295 | prefix = ", "; |
| 296 | } |
| 297 | builder.append(']'); |
| 298 | } |
| 299 | |
| 300 | return builder.toString(); |
| 301 | } |
| 302 | |
| 303 | @SuppressWarnings("CatchingUnchecked") // sneaky checked exception |
| 304 | private static String lenientToString(@Nullable Object o) { |