github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/Gold.pas (about) 1 namespace go.builtin; 2 3 uses 4 go.builtin 5 {$IFDEF ECHOES} , System.Linq, System.Collections, System.Collections.Generic{$ENDIF} 6 7 ; 8 9 type 10 [AttributeUsage(AttributeTargets.Assembly, AllowMultiple := true)] 11 PackageNameAttribute = public class(Attribute) 12 public 13 constructor(aNamespace, aName: System.String); 14 begin 15 &Namespace := aNamespace; 16 Name := aName; 17 end; 18 19 property Name: System.String; readonly; 20 property &Namespace: System.String; readonly; 21 end; 22 23 24 VTCheck<V> = class 25 public 26 class var IsVT := false; readonly; 27 28 class constructor; 29 begin 30 var lType := typeOf(V); 31 {$IFDEF ISLAND} 32 if not lType.IsValueType and (lType.Methods.Any(a -> a.Name = '__Set')) then 33 IsVT := true; 34 {$ELSE} 35 if not lType.IsValueType and (lType.GetMethods.Any(a -> a.Name = '__Set')) then 36 IsVT := true; 37 {$ENDIF} 38 end; 39 end; 40 41 CloneHelper<T> = class 42 {$IF ISLAND} 43 class var CloneMethod: MethodInfo := typeOf(T).Methods.FirstOrDefault(a -> a.Name = '__Clone'); readonly; 44 {$ELSE} 45 class var CloneMethod: System.Reflection.MethodInfo := typeOf(T).GetMethods.FirstOrDefault(a -> a.Name = '__Clone'); readonly; 46 {$ENDIF} 47 end; 48 49 IMap = public interface 50 method GetReflectSequence: sequence of tuple of(go.reflect.Value, go.reflect.Value); 51 method GetReflectValue(aKey: go.reflect.Value): go.reflect.Value; 52 method GetReflectKeys: Slice<go.reflect.Value>; 53 method SetReflectKeyValue(aKey: go.reflect.Value; aValue: go.reflect.Value); 54 method GetLen: Integer; 55 end; 56 57 [ValueTypeSemantics] 58 Map<K, V> = public class(IMap) 59 private 60 {$IFDEF ECHOES} 61 fDict: System.Collections.Generic.Dictionary<K, V> := new System.Collections.Generic.Dictionary<K, V>; 62 {$ELSEIF ISLAND} 63 fDict: Dictionary<K, V> := new Dictionary<K, V>; 64 {$ELSE} 65 {$ERROR NOT SUPPORTED} 66 {$ENDIF} 67 68 method set_Item(aItem: K; aVal: V); 69 begin 70 fDict[aItem] := aVal; 71 end; 72 73 public 74 method __Set(v: Object); 75 begin 76 if (v <> nil) and (v <> self) then begin 77 fDict.Clear(); 78 for each el in Map<K, V>(v):fDict do 79 fDict.Add(el.Key, el.Value); 80 end; 81 end; 82 83 constructor(aArgs: array of tuple of (K, V)); 84 begin 85 for each el in aArgs do 86 fDict[el[0]] := el[1]; 87 end; 88 89 constructor(aCap: Integer); 90 begin 91 //fDict.Capacity := aCap; 92 end; 93 94 constructor(aCap: go.builtin.int); 95 begin 96 //fDict.Capacity := aCap; 97 end; 98 99 constructor(); 100 begin 101 end; 102 {$IFDEF ECHOES} 103 class operator implicit(aVal: System.Collections.Generic.Dictionary<K, V>): Map<K, V>; 104 begin 105 result := new Map<K, V>; 106 for each el in aVal do 107 result.fDict.Add(el.Key, el.Value); 108 end; 109 110 class operator implicit(aVal: Map<K, V>): System.Collections.Generic.Dictionary<K, V>; 111 begin 112 result := new System.Collections.Generic.Dictionary<K, V>; 113 114 for each el in aVal.fDict do 115 result.Add(el.Key, el.Value); 116 end; 117 {$ELSEIF ISLAND} 118 class operator implicit(aVal: Dictionary<K, V>): Map<K, V>; 119 begin 120 result := new Map<K, V>; 121 for each el in aVal do 122 result.fDict.Add(el.Key, el.Value); 123 end; 124 125 class operator implicit(aVal: Map<K, V>): Dictionary<K, V>; 126 begin 127 result := new Dictionary<K, V>; 128 129 for each el in aVal.fDict do 130 result.Add(el.Key, el.Value); 131 end; 132 {$ELSE} 133 {$ERROR NOT SUPPORTED} 134 {$ENDIF} 135 136 constructor(aKeys: array of K; aValues: array of V); 137 begin 138 if aKeys.Length <> aValues.Length then raise new Exception('Keys/Values do not match!'); 139 for i: Integer := 0 to aKeys.Length -1 do 140 fDict[aKeys[i]] := aValues[i]; 141 end; 142 143 class var fZero: Map<K, V> := new Map<K, V>(); 144 class property Zero: Map<K, V> := fZero; published; 145 146 method __Clone: Map<K, V>; 147 begin 148 exit self; 149 end; 150 151 class operator IsNil(aVal: Map<K, V>): Boolean; 152 begin 153 result := (Object(aVal) = nil) or (Object(aVal) = Object(fZero)); 154 end; 155 156 class operator Equal(Value1, Value2: Map<K, V>): Boolean; 157 begin 158 if ((Object(Value1) = nil) and (Object(Value2) = Object(fZero))) or ((Object(Value1) = Object(fZero)) and (Object(Value2) = nil)) then 159 exit true; 160 161 exit Object(Value1) = Object(Value2); 162 end; 163 164 class operator NotEqual(Value1, Value2: Map<K, V>): Boolean; 165 begin 166 result := not (Value1 = Value2); 167 end; 168 169 property Item[aItem: K]: V write set_Item; default; 170 property Item[aItem: K]: tuple of (V, Boolean) read get_Item; default; 171 172 method Get(aItem: K): V; 173 begin 174 exit Item[aItem][0]; 175 end; 176 177 method Add(a: K; b: V); 178 begin 179 fDict[a] := b; 180 end; 181 182 method get_Item(aItem: K): tuple of (V, Boolean); 183 begin 184 var val: V; 185 if fDict.TryGetValue(aItem,out val) then 186 exit (val, true); 187 188 {$IFDEF ISLAND} 189 if VTCheck<V>.IsVT then 190 exit (typeOf(V).Instantiate as V, false); 191 {$ELSE} 192 if VTCheck<V>.IsVT then 193 exit (Activator.CreateInstance<V>(), false); 194 {$ENDIF} 195 var lZero := go.reflect.Zero(new go.reflect.TypeImpl(typeOf(V))); 196 if lZero.fValue <> nil then 197 exit (lZero.fValue as V, false); 198 199 exit (default(V), false); 200 end; 201 202 method Delete(aKey: K); 203 begin 204 fDict.Remove(aKey); 205 end; 206 207 method GetLen: Integer; 208 begin 209 result := Length; 210 end; 211 212 property Length: Integer read fDict.Count; 213 214 method GetSequence: sequence of tuple of (K, V); 215 begin 216 {$IFDEF ISLAND} 217 exit fDict.GetSequence.Select(a -> (a.Key, a.Value)); 218 {$ELSE} 219 exit fDict.Select(a -> (a.Key, a.Value)); 220 {$ENDIF} 221 end; 222 223 method GetReflectSequence: sequence of tuple of(go.reflect.Value, go.reflect.Value); 224 begin 225 {$IFDEF ISLAND} 226 exit fDict.GetSequence.Select(a -> (new go.reflect.Value(a.Key), new go.reflect.Value(a.Value))); 227 {$ELSE} 228 exit fDict.Select(a -> (new go.reflect.Value(a.Key), new go.reflect.Value(a.Value))); 229 {$ENDIF} 230 end; 231 232 method GetReflectValue(aKey: go.reflect.Value): go.reflect.Value; 233 begin 234 result := new go.reflect.Value(Item[K(aKey.fValue)]); 235 end; 236 237 method GetReflectKeys: Slice<go.reflect.Value>; 238 begin 239 {$IFDEF ISLAND} 240 exit fDict.GetSequence.Select(a -> (new go.reflect.Value(a.Key))).ToArray; 241 {$ELSE} 242 exit fDict.Select(a -> (new go.reflect.Value(a.Key))).ToArray; 243 {$ENDIF} 244 end; 245 246 method SetReflectKeyValue(aKey: go.reflect.Value; aValue: go.reflect.Value); 247 begin 248 if aValue.IsValid then 249 &Add(aKey.fValue as K, aValue.fValue as V) 250 else 251 Delete(aKey.fValue as K); 252 end; 253 end; 254 255 {$IFDEF ISLAND} 256 IndexOutOfRangeException = public class(Exception) end; 257 {$ENDIF} 258 ISlice = public interface 259 method getAtIndex(i: Integer): Object; 260 method setAtIndex(i: Integer; aValue: Object); 261 method getCap: Integer; 262 method setCap: Integer; 263 method getLen: Integer; 264 method setLen(aValue: Integer): Integer; 265 method setFrom(aSrc: ISlice); 266 method getReflectSlice(i: Integer; j: Integer): go.reflect.Value; 267 method AppendObject(aObject: Object): go.reflect.Value; 268 method CloneElems: Object; 269 end; 270 271 272 [ValueTypeSemantics] 273 Slice<T> = public class(go.sort.Interface, ISlice) 274 assembly 275 fArray: array of T; 276 fStart, fCount: Integer; 277 278 method get_Item(i: Integer): T; 279 begin 280 if (i < 0) or (i ≥ fCount) then raise new IndexOutOfRangeException('Index out of range'); 281 {$IFDEF ISLAND} 282 if VTCheck<T>.IsVT and (Object(fArray[i + fStart]) = nil) then 283 fArray[i + fStart] := typeOf(T).Instantiate as T; 284 {$ELSE} 285 if VTCheck<T>.IsVT and (Object(fArray[i + fStart]) = nil) then 286 fArray[i + fStart] := Activator.CreateInstance<T>(); 287 {$ENDIF} 288 exit fArray[i + fStart]; 289 end; 290 291 method set_Item(i: Integer; aVal: T); 292 begin 293 if (i < 0) or (i ≥ Capacity) then raise new IndexOutOfRangeException('Index out of range'); 294 fArray[i + fStart] := aVal; 295 end; 296 class var EmptyArray: array of T := []; 297 public 298 299 constructor(aArray: array of T; aStart, aCount: Integer); 300 begin 301 if (aStart < 0) or (aStart + aCount > aArray.Length) then raise new IndexOutOfRangeException('Index out of range'); 302 fArray := aArray; 303 fStart := aStart; 304 fCount := aCount; 305 end; 306 307 method Ref(i: int64): Memory<T>; unsafe; 308 begin 309 exit @fArray[i]; 310 end; 311 312 constructor; 313 begin 314 constructor(EmptyArray, 0, 0); 315 end; 316 317 constructor(params aArray: array of T); 318 begin 319 constructor(aArray, 0, aArray.Length); 320 end; 321 322 constructor(aSize, aCap: go.builtin.int); 323 begin 324 if aCap < aSize then aCap := aSize; 325 constructor(new T[aCap], 0, aSize); 326 end; 327 328 constructor(aSize, aCap: int64); 329 begin 330 if aCap < aSize then aCap := aSize; 331 constructor(new T[aCap], 0, aSize); 332 end; 333 334 constructor(aSize: go.builtin.int; aCap: int64); 335 begin 336 if aCap < aSize then aCap := aSize; 337 constructor(new T[aCap], 0, aSize); 338 end; 339 constructor(aSize: int64; aCap: go.builtin.int); 340 begin 341 if aCap < aSize then aCap := aSize; 342 constructor(new T[aCap], 0, aSize); 343 end; 344 345 constructor(aSize: go.builtin.int); 346 begin 347 constructor(aSize, aSize); 348 end; 349 350 constructor(aSize: int64); 351 begin 352 constructor(aSize, aSize); 353 end; 354 355 class var fZero: Slice<T> := new Slice<T>; 356 //class property Zero: Slice<T> := fZero; published; 357 class property Zero: Slice<T> read new Slice<T>; 358 359 class operator IsNil(aVal: Slice<T>): Boolean; 360 begin 361 result := (Object(aVal) = nil) or (Object(aVal) = Object(fZero)) or ((aVal.fArray = EmptyArray) and (aVal.Length = 0) and (aVal.Capacity = 0)); 362 end; 363 364 method Assign(aOrg: array of T); 365 begin 366 if aOrg <> nil then 367 for i: Integer := 0 to aOrg. Length -1 do begin 368 self[i] := aOrg[i]; 369 end; 370 end; 371 372 method Assign(aOrg: Slice<T>); 373 begin 374 if aOrg <> nil then 375 for i: Integer := 0 to aOrg. Length -1 do begin 376 self[i] := aOrg[i]; 377 end; 378 end; 379 380 method getAtIndex(i: Integer): Object; 381 begin 382 result := get_Item(i); 383 end; 384 385 method AppendObject(aObject: Object): go.reflect.Value; 386 begin 387 exit new go.reflect.Value(append(self, T(aObject))); 388 end; 389 390 method setAtIndex(i: Integer; aValue: Object); 391 begin 392 set_Item(i, T(aValue)); 393 end; 394 395 method getCap: Integer; 396 begin 397 result := Capacity; 398 end; 399 400 method setCap: Integer; 401 begin 402 403 end; 404 405 method setLen(aValue: Integer): Integer; 406 begin 407 fCount := aValue; 408 end; 409 410 method getLen: Integer; 411 begin 412 result := Length; 413 end; 414 415 method setFrom(aSrc: go.builtin.ISlice); 416 begin 417 fArray := new T[aSrc.getCap]; 418 fStart := 0; 419 //fStart := aSrc.fStart; 420 fCount := aSrc.getLen; 421 end; 422 423 method ToArray: array of T; 424 begin 425 result := new T[Length]; 426 &Array.Copy(fArray, fStart, result, 0, fCount); 427 end; 428 429 method Len: go.builtin.int; 430 begin 431 result := fCount; 432 end; 433 434 method getReflectSlice(i: Integer; j: Integer): go.reflect.Value; 435 begin 436 result := new go.reflect.Value(new Slice<T>(fArray, i, j-i)); 437 end; 438 439 method Less(a, b: go.builtin.int): go.builtin.bool; 440 begin 441 442 end; 443 444 method Swap(a, b: go.builtin.int); 445 begin 446 var p := self[a]; 447 self[a] := self[b]; 448 self[b] := p; 449 end; 450 451 // helper; for contructor calls. 452 method Add(a: Integer; b: T); 453 begin 454 Item[a] := b; 455 end; 456 457 property Capacity: Integer read fArray.Length - fStart; 458 property Length: Integer read fCount; 459 property Item[i: Integer]: T read get_Item write set_Item; default; 460 461 class method Copy(aSource, aDest: Slice<T>); 462 begin 463 var lCopy := Math.Min(aSource.Length, aDest.Length); 464 for i: Integer := 0 to lCopy -1 do 465 aDest[i] := aSource[i]; 466 end; 467 468 method CloneElems: Object; 469 begin 470 if CloneHelper<T>.CloneMethod <> nil then begin 471 var lNewArray := new T[Capacity]; 472 for i: Integer := 0 to fArray.Length -1 do 473 if fArray[i] <> nil then 474 lNewArray[i] := T(CloneHelper<T>.CloneMethod.Invoke(fArray[i], [])) 475 else 476 lNewArray[i] := nil; 477 478 exit new Slice<T>(lNewArray, fStart, fCount); 479 end 480 else 481 exit self; 482 end; 483 484 method Grow(aNewLen: Integer): Slice<T>; 485 begin 486 if aNewLen > Capacity then raise new ArgumentException('Length larger than capacity!'); 487 488 exit new Slice<T>(fArray, fStart, aNewLen); 489 end; 490 491 class operator implicit(aVal: array of T): Slice<T>; 492 begin 493 exit new Slice<T>(aVal); 494 end; 495 496 method GetSequence: sequence of tuple of (Integer, T); iterator; 497 begin 498 for i: Integer := 0 to Length -1 do 499 yield (i, self[i]); 500 end; 501 502 class operator implicit(aVal: Slice<T>): array of T; 503 begin 504 if aVal = nil then 505 exit new T[0]; 506 507 exit aVal.ToArray(); 508 end; 509 510 class operator Equal(Value1, Value2: Slice<T>): Boolean; published; 511 begin 512 // Compare also if both are nil, sice fZero is not the same for all instances. 513 if ((Object(Value1) = nil) and (Object(Value2) = Object(fZero))) or ((Object(Value1) = Object(fZero)) and (Object(Value2) = nil)) or 514 (((Value1.fArray = EmptyArray) and (Value1.Length = 0) and (Value1.Capacity = 0)) and ((Value2.fArray = EmptyArray) and (Value2.Length = 0) and (Value2.Capacity = 0))) then 515 exit true; 516 517 exit Object(Value1) = Object(Value2); 518 end; 519 520 class operator NotEqual(Value1, Value2: Slice<T>): Boolean; 521 begin 522 result := not (Value1 = Value2); 523 end; 524 525 /*method Get(idxs: Slice<go.builtin.int32>; idx1: go.builtin.int32; idx2: go.builtin.int32): T; 526 begin 527 raise new NotImplementedException; 528 end; 529 530 method Get(idxs: Slice<go.builtin.int32>; idx1: go.builtin.int32): T; 531 begin 532 raise new NotImplementedException; 533 end;*/ 534 535 method Get(idx1: go.builtin.int32; idx2: go.builtin.int32): T; 536 begin 537 raise new NotImplementedException; 538 end; 539 540 541 end; 542 543 error = public soft interface 544 method Error: string; 545 end; 546 547 548 IWaitMessage = public interface 549 method Cancel; 550 method Start(aNotifier: Func<Func<Boolean>, Boolean>): Boolean; 551 end; 552 553 IWaitSendMessage = public interface(IWaitMessage) 554 end; 555 556 IWaitReceiveMessage<T> = public interface(IWaitMessage) 557 method TryHandOff(aVal: T): Boolean; 558 property Data: tuple of (T, Boolean) read; 559 end; 560 561 IChannel = public interface 562 property Length: Integer read; 563 end; 564 565 Channel<T> = public interface 566 property Capacity: Integer read; 567 method Close; 568 end; 569 570 ReceivingChannel<T> = public interface(Channel<T>) 571 method Receive: tuple of (T, Boolean); 572 method TryReceive: IWaitReceiveMessage<T>; 573 method GetSequence: sequence of T; 574 end; 575 576 SendingChannel<T> = public interface(Channel<T>) 577 method Send(aVal: T); 578 method TrySend(aVal: T): IWaitSendMessage; 579 end; 580 581 GoException = public class(Exception) 582 public 583 property Value: Object; readonly; 584 constructor(aVal: Object); 585 begin 586 inherited constructor(aVal.ToString); 587 Value := aVal; 588 end; 589 end; 590 591 method copy<T>(dst, src: Slice<T>): Integer; 592 begin 593 result := Math.Min(if src = nil then 0 else src.Length, if dst = nil then 0 else dst.Length); 594 for i: Integer := 0 to result -1 do 595 dst[i] := src[i]; 596 end; 597 598 method copy(dst: Slice<byte>; src: string): Integer; 599 begin 600 {$IFDEF ISLAND} 601 exit copy(dst, new Slice<byte>(Encoding.UTF8.GetBytes(src))); 602 {$ELSE} 603 exit copy(dst, new Slice<byte>(System.Text.Encoding.UTF8.GetBytes(src))); 604 {$ENDIF} 605 end; 606 607 method append<T>(sl: Slice<T>; elems: T): Slice<T>; 608 begin 609 var slc := if sl = nil then 0 else sl.Length; 610 var lNew := new T[slc + 1]; 611 for i: Integer := 0 to slc -1 do 612 lNew[i] := sl[i]; 613 614 if (elems is IList) then begin 615 {$IF ECHOES} 616 var lType := typeOf(T); 617 var lElementsType := lType.GetElementType(); 618 var CloneMethod: System.Reflection.MethodInfo := lElementsType.GetMethods.FirstOrDefault(a -> a.Name = '__Clone'); 619 var lTmp := Array.CreateInstance(lElementsType, IList(elems).Count); 620 for i: Integer := 0 to IList(elems).Count - 1 do begin 621 if CloneMethod <> nil then 622 lTmp.SetValue(CloneMethod.Invoke(IList(elems)[i], []), i) 623 else 624 lTmp.SetValue(IList(elems)[i], i); 625 end; 626 {$ELSE} 627 var lType := typeOf(sl); 628 var lGeneric := lType.GenericArguments.First; 629 var lElementsType := lGeneric.GenericArguments.First; 630 var CloneMethod: MethodInfo := lElementsType.Methods.FirstOrDefault(a -> a.Name = '__Clone'); 631 var lTmp := InternalCalls.Cast<&Array>(Utilities.NewArray(lGeneric.RTTI, lElementsType.SizeOfType, IList(elems).Count)); 632 for i: Integer := 0 to IList(elems).Count - 1 do begin 633 if CloneMethod <> nil then 634 IList(lTmp)[i] := CloneMethod.Invoke(IList(elems)[i], []) 635 else 636 IList(lTmp)[i]:= IList(elems)[i]; 637 end; 638 {$ENDIF} 639 lNew[slc] := T(lTmp); 640 end 641 else 642 //if (elems is go.builtin.ISlice) then begin 643 //lNew[slc] := T(go.builtin.ISlice(elems).CloneElems); 644 //end 645 //else 646 lNew[slc] := elems; 647 648 exit lNew; 649 end; 650 651 method append<T>(sl: Slice<T>; a: T; params elems: array of T): Slice<T>; 652 begin 653 var c := if elems = nil then 0 else IList<T>(elems).Count; 654 var slc := if sl = nil then 0 else sl.Length; 655 if c + slc + 1 ≤ sl.Capacity then begin 656 sl[slc] := a; 657 for i: Integer := 0 to c -1 do 658 sl[slc + i + 1] := IList<T>(elems)[i]; 659 sl.setLen(slc + c + 1); 660 exit sl; 661 end 662 else begin 663 var lNew := new T[slc + c + 1]; 664 for i: Integer := 0 to slc -1 do 665 lNew[i] := sl[i]; 666 lNew[slc] := a; 667 for i: Integer := 0 to c -1 do 668 lNew[i + slc + 1] := IList<T>(elems)[i]; 669 exit lNew; 670 end; 671 end; 672 673 method append<T>(sl, elems: Slice<T>): Slice<T>; 674 begin 675 var c := if elems = nil then 0 else elems.Length; 676 var slc := if sl = nil then 0 else sl.Length; 677 var slCap := if sl = nil then 0 else sl.Capacity; 678 var lNew := new T[if (slc + c) <= slCap then slCap else slc + c]; 679 for i: Integer := 0 to slc -1 do 680 lNew[i] := sl[i]; 681 for i: Integer := 0 to c -1 do 682 lNew[i + slc] := elems[i]; 683 exit new Slice<T>(lNew, 0, slc + c); 684 end; 685 686 method append(sl: Slice<byte>; elems: string): Slice<byte>; 687 begin 688 exit append(sl, elems.Value); 689 end; 690 691 method close<T>(v: Channel<T>); public; 692 begin 693 v.Close; 694 end; 695 696 method cap<T>(v: Channel<T>): Integer; public; 697 begin 698 if v = nil then exit 0; 699 exit v.Capacity; 700 end; 701 702 method cap<T>(v: Slice<T>): Integer; public; 703 begin 704 if Object(v) = nil then exit -1; 705 exit v.Capacity; 706 end; 707 708 method len(v: string): Integer; public; 709 begin 710 //exit v.Value.Length; 711 exit v.Length; 712 end; 713 714 method len<T>(v: array of T): Integer; public; 715 begin 716 exit length(v); 717 end; 718 719 method len<T>(v: Slice<T>): Integer; public; 720 begin 721 if v = nil then exit 0; 722 exit v.Length; 723 end; 724 725 method len<K, V>(v: Map<K, V>): Integer; public; 726 begin 727 if v = nil then exit 0; 728 exit v.Length; 729 end; 730 731 method Start(v: Action); public; 732 begin 733 {$IFDEF ISLAND} 734 Task.Run(v); 735 {$ELSE} 736 System.Threading.Tasks.Task.Factory.StartNew(v); 737 {$ENDIF} 738 end; 739 740 method AssignArray<T>(aDest, aSource: array of T); public; 741 begin 742 for i: Integer := 0 to Math.Min(length(aDest), length(aSource)) -1 do 743 aDest[i] := aSource[i]; 744 end; 745 746 method Send<T>(aChannel: SendingChannel<T>; aVal: T); public; 747 begin 748 if aChannel ≠ nil then 749 aChannel.Send(aVal); 750 end; 751 752 method Receive<T>(aChannel: ReceivingChannel<T>): tuple of (T, Boolean); public; 753 begin 754 if aChannel = nil then 755 exit (nil, false); 756 757 exit aChannel.Receive(); 758 end; 759 760 method delete<K,V>(aMap: Map<K, V>; aKey: K); public; 761 begin 762 aMap.Delete(aKey); 763 end; 764 765 method Slice<T>(aSlice: Slice<T>; aStart, aEnd: nullable Integer): Slice<T>; public; 766 begin 767 if aSlice = nil then 768 exit nil; 769 var lStart := valueOrDefault(aStart, 0); 770 var lEnd := valueOrDefault(aEnd, aSlice.Length); 771 //if Integer(lEnd) > aSlice.Length then lEnd := aSlice.Length; 772 if (lStart = 0) and (lEnd = aSlice.Length) then exit aSlice; 773 lStart := lStart + aSlice.fStart; 774 lEnd := lEnd + aSlice.fStart; 775 exit new Slice<T>(aSlice.fArray, lStart, lEnd - lStart); 776 end; 777 778 method Slice<T>(aSlice: Slice<T>; aStart, aEnd: nullable Integer; aCap: Integer): Slice<T>; public; 779 begin 780 var lStart := valueOrDefault(aStart, 0); 781 var lEnd := valueOrDefault(aEnd, aSlice.Length); 782 var lCap := aCap - aStart; 783 if Integer(lEnd) > aSlice.Length then lEnd := aSlice.Length; 784 if (lStart = 0) and (lEnd = aSlice.Length) then exit aSlice; 785 lStart := lStart + aSlice.fStart; 786 lEnd := lEnd + aSlice.fStart; 787 if lCap > lEnd then begin 788 var 789 lSlice := new T[lCap]; 790 Array.Copy(aSlice.fArray, lStart, lSlice, 0, lEnd - lStart); 791 exit new Slice<T>(lSlice, lStart, lEnd - lStart); 792 end; 793 exit new Slice<T>(aSlice.fArray, lStart, lEnd - lStart); 794 end; 795 796 method Slice<T>(aSlice: array of T; aStart, aEnd: nullable Integer; aCap: Integer): Slice<T>; public; 797 begin 798 var lStart := valueOrDefault(aStart, 0); 799 var lEnd := valueOrDefault(aEnd, aSlice.Length); 800 var lCap := aCap - aStart; 801 if Integer(lEnd) > aSlice.Length then lEnd := aSlice.Length; 802 if (lStart = 0) and (lEnd = aSlice.Length) then exit aSlice; 803 if lCap > lEnd then begin 804 var 805 lSlice := new T[lCap]; 806 Array.Copy(aSlice, lStart, lSlice, 0, lEnd - lStart); 807 exit new Slice<T>(lSlice, lStart, lEnd - lStart); 808 end; 809 exit new Slice<T>(aSlice, lStart, lEnd - lStart); 810 end; 811 812 813 method Slice(aSlice: string; aStart, aEnd: nullable Integer): string; public; 814 begin 815 var lStart := valueOrDefault(aStart, 0); 816 var lEnd := valueOrDefault(aEnd, aSlice.Length); 817 if Integer(lEnd) > aSlice.Length then lEnd := aSlice.Length; 818 if (lStart = 0) and (lEnd = aSlice.Length) then exit aSlice; 819 exit new string(new Slice<byte>(aSlice.Value, lStart, lEnd - lStart)); 820 end; 821 822 method Slice<T>(aSlice: array of T; aStart, aEnd: nullable Integer): Slice<T>; public; 823 begin 824 exit Slice(new Slice<T>(aSlice), aStart, aEnd); 825 end; 826 827 method TypeAssert<T>(v: Object): tuple of (T, Boolean); 828 begin 829 if (v ≠ nil) and (v is Memory<T>) then begin 830 exit (Memory<T>(v)^, true); 831 end; 832 833 if v is T then 834 exit (T(v), true); 835 836 if v is IMemory then begin 837 if IMemory(v).GetValue is T then 838 exit (IMemory(v).GetValue as T, true); 839 end; 840 {$IFDEF ISLAND} 841 if VTCheck<T>.IsVT then 842 exit (typeOf(T).Instantiate as T, false); 843 {$ELSE} 844 if VTCheck<T>.IsVT then 845 exit (Activator.CreateInstance<T>(), false); 846 {$ENDIF} 847 var lZero := go.reflect.Zero(new go.reflect.TypeImpl(typeOf(T))); 848 if lZero.fValue <> nil then 849 exit (lZero.fValue as T, false); 850 851 exit (default(T), false); // for integers, T(V) cast would fail otherwise. 852 end; 853 854 method TypeAssertReference<T>(v: Object): tuple of (&Memory<T>, Boolean); 855 begin 856 result := TypeAssert<Memory<T>>(v); 857 if result[1] then exit; 858 if v is T then 859 exit (new Memory<T>(T(v)), true); 860 end; 861 862 method panic(v: Object); 863 begin 864 raise new GoException(v); 865 end; 866 867 method recover: Object; 868 begin 869 exit nil; 870 end; 871 872 extension method ISequence<T>.GoldIterate: sequence of tuple of (Integer, T); iterator; public; 873 begin 874 for each el in self index n do 875 yield (n, el); 876 end; 877 878 type 879 IntExtension = extension class(Integer, go.fmt.Stringer) 880 public 881 method String: string; 882 begin 883 exit self.ToString; 884 end; 885 end; 886 887 [AttributeUsage(AttributeTargets.Field)] 888 TagAttribute = public class(Attribute) 889 private 890 fTag: string; 891 public 892 constructor(aTag: PlatformString); 893 begin 894 fTag := aTag; 895 end; 896 897 property Tag: string read fTag; 898 end; 899 900 go.crypto.internal.subtle.__Global = public partial class 901 public 902 class method InexactOverlap(x, y: go.builtin.Slice<byte>): Boolean; 903 begin 904 if (x.Length = 0) or (y.Length = 0) or (x.fArray <> y.fArray) or ((x.fArray = y.fArray) and (x.fStart = y.fStart)) then 905 exit false; 906 907 if (x.fArray = y.fArray) and ((x.fStart ≤ (y.fStart + y.Length)) and (y.fStart ≤ (x.fStart + x.Length))) then 908 exit true 909 else 910 exit false; 911 end; 912 end; 913 914 [assembly:GoldAspect.GoldFixer] 915 916 917 extension method go.reflect.Kind.String(): go.builtin.string; public; 918 begin 919 case Integer(self) of 920 0: exit 'Invalid'; 921 1: exit 'Bool'; 922 2: exit 'Int'; 923 3: exit 'Int8'; 924 4: exit 'Int16'; 925 5: exit 'Int32'; 926 6: exit 'Int64'; 927 7: exit 'Uint'; 928 8: exit 'Uint8'; 929 9: exit 'Uint16'; 930 10: exit 'Uint32'; 931 11: exit 'Uint64'; 932 12: exit 'Uintptr'; 933 13: exit 'Float32'; 934 14: exit 'Float64'; 935 15: exit 'Complex64'; 936 16: exit 'Complex128'; 937 17: exit '&Array'; 938 18: exit 'Chan'; 939 19: exit 'Func'; 940 20: exit '&Interface'; 941 21: exit 'Map'; 942 22: exit 'Ptr'; 943 23: exit 'Slice'; 944 24: exit 'String'; 945 25: exit 'Struct'; 946 26: exit 'UnsafePointer'; 947 end; 948 exit 'Unknown'; 949 end; 950 951 952 953 end.