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 // cmpForType returns a cmpFn which sorts the data for some type t in the same |
| 353 // order that a go-native map key is compared for equality. |
| 354 func cmpForType(t reflect.Type) cmpFn { |
| 355 switch t.Kind() { |
| 356 case reflect.String: |
| 357 return func(av, bv reflect.Value) int { |
| 358 a, b := av.String(), bv.String() |
| 359 if a < b { |
| 360 return -1 |
| 361 } else if a > b { |
| 362 return 1 |
| 363 } |
| 364 return 0 |
| 365 } |
| 366 |
| 367 case reflect.Bool: |
| 368 return func(av, bv reflect.Value) int { |
| 369 a, b := av.Bool(), bv.Bool() |
| 370 if !a && b { |
| 371 return -1 |
| 372 } else if a && !b { |
| 373 return 1 |
| 374 } |
| 375 return 0 |
| 376 } |
| 377 |
| 378 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In
t64: |
| 379 return func(av, bv reflect.Value) int { |
| 380 a, b := av.Int(), bv.Int() |
| 381 if a < b { |
| 382 return -1 |
| 383 } else if a > b { |
| 384 return 1 |
| 385 } |
| 386 return 0 |
| 387 } |
| 388 |
| 389 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, |
| 390 reflect.Uint64, reflect.Uintptr, reflect.UnsafePointer: |
| 391 return func(av, bv reflect.Value) int { |
| 392 a, b := av.Uint(), bv.Uint() |
| 393 if a < b { |
| 394 return -1 |
| 395 } else if a > b { |
| 396 return 1 |
| 397 } |
| 398 return 0 |
| 399 } |
| 400 |
| 401 case reflect.Float32, reflect.Float64: |
| 402 return func(av, bv reflect.Value) int { |
| 403 a, b := av.Float(), bv.Float() |
| 404 if a < b { |
| 405 return -1 |
| 406 } else if a > b { |
| 407 return 1 |
| 408 } |
| 409 return 0 |
| 410 } |
| 411 |
| 412 case reflect.Interface: |
| 413 return func(av, bv reflect.Value) int { |
| 414 a, b := av.InterfaceData(), bv.InterfaceData() |
| 415 if a[0] < b[0] { |
| 416 return -1 |
| 417 } else if a[0] > b[0] { |
| 418 return 1 |
| 419 } |
| 420 if a[1] < b[1] { |
| 421 return -1 |
| 422 } else if a[1] > b[1] { |
| 423 return 1 |
| 424 } |
| 425 return 0 |
| 426 } |
| 427 |
| 428 case reflect.Complex64, reflect.Complex128: |
| 429 return func(av, bv reflect.Value) int { |
| 430 a, b := av.Complex(), bv.Complex() |
| 431 if real(a) < real(b) { |
| 432 return -1 |
| 433 } else if real(a) > real(b) { |
| 434 return 1 |
| 435 } |
| 436 if imag(a) < imag(b) { |
| 437 return -1 |
| 438 } else if imag(a) > imag(b) { |
| 439 return 1 |
| 440 } |
| 441 return 0 |
| 442 } |
| 443 |
| 444 case reflect.Ptr, reflect.Chan: |
| 445 return func(av, bv reflect.Value) int { |
| 446 a, b := av.Pointer(), bv.Pointer() |
| 447 if a < b { |
| 448 return -1 |
| 449 } else if a > b { |
| 450 return 1 |
| 451 } |
| 452 return 0 |
| 453 } |
| 454 |
| 455 case reflect.Struct: |
| 456 cmpLst := make([]cmpFn, t.NumField()) |
| 457 for i := range cmpLst { |
| 458 cmpLst[i] = cmpForType(t.Field(i).Type) |
| 459 } |
| 460 return func(a, b reflect.Value) int { |
| 461 for i, cmp := range cmpLst { |
| 462 if rslt := cmp(a.Field(i), b.Field(i)); rslt !=
0 { |
| 463 return rslt |
| 464 } |
| 465 } |
| 466 return 0 |
| 467 } |
| 468 } |
| 469 |
| 470 return nil |
| 471 } |
| 472 |
359 func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) { | 473 func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) { |
360 » // Try our stock sortable values. | 474 » if cmp := cmpForType(mt.Key()); cmp != nil { |
361 » switch mt.Key().Kind() { | 475 » » 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 } | 476 } |
369 } | 477 } |
OLD | NEW |