OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package render | 5 package render |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "reflect" | 10 "reflect" |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 | 323 |
324 default: | 324 default: |
325 buf.WriteString(t.String()) | 325 buf.WriteString(t.String()) |
326 } | 326 } |
327 | 327 |
328 if parens { | 328 if parens { |
329 buf.WriteRune(')') | 329 buf.WriteRune(')') |
330 } | 330 } |
331 } | 331 } |
332 | 332 |
333 type cmpFn func(a, b reflect.Value) int | |
334 | |
333 type sortableValueSlice struct { | 335 type sortableValueSlice struct { |
334 » kind reflect.Kind | 336 » cmp cmpFn |
335 elements []reflect.Value | 337 elements []reflect.Value |
336 } | 338 } |
337 | 339 |
338 func (s *sortableValueSlice) Len() int { | 340 func (s sortableValueSlice) Len() int { |
339 return len(s.elements) | 341 return len(s.elements) |
340 } | 342 } |
341 | 343 |
342 func (s *sortableValueSlice) Less(i, j int) bool { | 344 func (s sortableValueSlice) Less(i, j int) bool { |
343 » switch s.kind { | 345 » return s.cmp(s.elements[i], s.elements[j]) < 0 |
344 » case reflect.String: | |
345 » » return s.elements[i].String() < s.elements[j].String() | |
346 | |
347 » case reflect.Int: | |
348 » » return s.elements[i].Int() < s.elements[j].Int() | |
349 | |
350 » default: | |
351 » » panic(fmt.Errorf("unsupported sort kind: %s", s.kind)) | |
352 » } | |
353 } | 346 } |
354 | 347 |
355 func (s *sortableValueSlice) Swap(i, j int) { | 348 func (s sortableValueSlice) Swap(i, j int) { |
356 s.elements[i], s.elements[j] = s.elements[j], s.elements[i] | 349 s.elements[i], s.elements[j] = s.elements[j], s.elements[i] |
357 } | 350 } |
358 | 351 |
352 func cmpForType(t reflect.Type) cmpFn { | |
dnj
2016/02/19 19:31:10
nit: document that this specifically aims to opera
iannucci
2016/02/19 21:18:28
Done.
| |
353 switch t.Kind() { | |
354 case reflect.String: | |
355 return func(av, bv reflect.Value) int { | |
356 a, b := av.String(), bv.String() | |
357 if a < b { | |
358 return -1 | |
359 } else if a > b { | |
360 return 1 | |
361 } | |
362 return 0 | |
363 } | |
364 | |
365 case reflect.Bool: | |
366 return func(av, bv reflect.Value) int { | |
367 a, b := av.Bool(), bv.Bool() | |
368 if !a && b { | |
369 return -1 | |
370 } else if a && !b { | |
371 return 1 | |
372 } | |
373 return 0 | |
374 } | |
375 | |
376 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64: | |
377 return func(av, bv reflect.Value) int { | |
378 a, b := av.Int(), bv.Int() | |
379 if a < b { | |
380 return -1 | |
381 } else if a > b { | |
382 return 1 | |
383 } | |
384 return 0 | |
385 } | |
386 | |
387 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, | |
388 reflect.Uint64, reflect.Uintptr, reflect.UnsafePointer: | |
389 return func(av, bv reflect.Value) int { | |
390 a, b := av.Uint(), bv.Uint() | |
391 if a < b { | |
392 return -1 | |
393 } else if a > b { | |
394 return 1 | |
395 } | |
396 return 0 | |
397 } | |
398 | |
399 case reflect.Float32, reflect.Float64: | |
400 return func(av, bv reflect.Value) int { | |
401 a, b := av.Float(), bv.Float() | |
402 if a < b { | |
403 return -1 | |
404 } else if a > b { | |
405 return 1 | |
406 } | |
407 return 0 | |
408 } | |
409 | |
410 case reflect.Interface: | |
411 return func(av, bv reflect.Value) int { | |
412 a, b := av.InterfaceData(), bv.InterfaceData() | |
413 if a[0] < b[0] { | |
414 return -1 | |
415 } else if a[0] > b[0] { | |
416 return 1 | |
417 } | |
418 if a[1] < b[1] { | |
419 return -1 | |
420 } else if a[1] > b[1] { | |
421 return 1 | |
422 } | |
423 return 0 | |
424 } | |
425 | |
426 case reflect.Complex64, reflect.Complex128: | |
427 return func(av, bv reflect.Value) int { | |
428 a, b := av.Complex(), bv.Complex() | |
429 if real(a) < real(b) { | |
430 return -1 | |
431 } else if real(a) > real(b) { | |
432 return 1 | |
433 } | |
434 if imag(a) < imag(b) { | |
435 return -1 | |
436 } else if imag(a) > imag(b) { | |
437 return 1 | |
438 } | |
439 return 0 | |
440 } | |
441 | |
442 case reflect.Ptr, reflect.Chan: | |
443 return func(av, bv reflect.Value) int { | |
444 a, b := av.Pointer(), bv.Pointer() | |
445 if a < b { | |
446 return -1 | |
447 } else if a > b { | |
448 return 1 | |
449 } | |
450 return 0 | |
451 } | |
452 | |
453 case reflect.Struct: | |
454 cmpLst := make([]cmpFn, t.NumField()) | |
455 for i := range cmpLst { | |
456 cmpLst[i] = cmpForType(t.Field(i).Type) | |
457 } | |
458 return func(a, b reflect.Value) int { | |
459 for i, cmp := range cmpLst { | |
460 rslt := cmp(a.Field(i), b.Field(i)) | |
dnj
2016/02/19 19:31:10
nit: if rstl := cmp(); rstl != 0 { ... }
iannucci
2016/02/19 21:18:28
Done.
| |
461 if rslt != 0 { | |
462 return rslt | |
463 } | |
464 } | |
465 return 0 | |
466 } | |
467 } | |
468 | |
469 return nil | |
470 } | |
471 | |
359 func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) { | 472 func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) { |
360 » // Try our stock sortable values. | 473 » if cmp := cmpForType(mt.Key()); cmp != nil { |
361 » switch mt.Key().Kind() { | 474 » » sort.Sort(sortableValueSlice{cmp, k}) |
362 » case reflect.String, reflect.Int: | |
363 » » vs := &sortableValueSlice{ | |
364 » » » kind: mt.Key().Kind(), | |
365 » » » elements: k, | |
366 » » } | |
367 » » sort.Sort(vs) | |
368 } | 475 } |
369 } | 476 } |
OLD | NEW |