Guest User

Untitled

a guest
Feb 5th, 2017
122
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. unit EnumHelper;
  2.  
  3. interface
  4.  
  5. {$mode delphi}
  6.  
  7. uses
  8.   SysUtils,
  9.   TypInfo;
  10.  
  11. type
  12.   EEnumOutOfRange = class(EArgumentOutOfRangeException);
  13.   EEnumNameNotFound = class(Exception);
  14.   EEnumParseError = class(Exception);
  15.  
  16. {$REGION 'ContainedEnum<T>'}
  17.   ContainedEnum<T> = record
  18.   strict private
  19.     FEnumValue: T;
  20.     constructor Create(const Value: T);
  21.   public
  22.     class operator Implicit(const Value: T): ContainedEnum<T>; inline;
  23.     class operator Implicit(const Value: Integer): ContainedEnum<T>;
  24.     class operator Implicit(const Value: string): ContainedEnum<T>;
  25.     class operator Implicit(const Value: ContainedEnum<T>): string;
  26.     class operator Implicit(const Value: ContainedEnum<T>): Integer;
  27.     // class operator Implicit(const Value: ContainedEnum<T>): T;
  28.     function ToInteger: Integer;
  29.     function ToString: string;
  30.     property Value: T read FEnumValue;
  31.   end;
  32. {$ENDREGION}
  33.  
  34.   TArray<T> = array of T;
  35.   EnumArray<T> = array of ContainedEnum<T>;
  36.  
  37. {$REGION 'Enum<T>'}
  38.   /// <summary> Record que contiene metodos estaticos para trabajar con tipos enums </summary>
  39.   Enum<T> = record
  40.   strict private
  41.     class function EnumTypeInfo: PTypeInfo; static;
  42.     class function EnumTypeData: PTypeData; static;
  43.     class procedure NameNotFound(const Identifier: string; const Value: T); static;
  44.     class procedure OutOfRange(const Value: T; const Namespace, MethodName: string); static;
  45.     class procedure StringParseError(const Value: string); static;
  46.   public
  47.     /// <summary> El nombre del tipo enum </summary>
  48.     class function TypeName: string; static;
  49.     /// <summary> El nombre del valor enum </summary>
  50.     class function ValueName(const Value: T): string; static;
  51.     /// <summary> Devuelve el valor enum dado un Ordinal </summary>
  52.     class function Parse(const Ordinal: Integer): ContainedEnum<T>; overload; static;
  53.     /// <summary> Devuelve el valor enum dado el nombre de su declaracion </summary>
  54.     class function Parse(const EnumValueName: string): ContainedEnum<T>; overload; static;
  55.     /// <summary> Convierte el valor enum a su correspondiente Ordinal </summary>
  56.     class function ToInteger(const Value: T): Integer; static;
  57.     /// <summary> El valor maximo del enum. Equivalente a Ord(High(T)) </summary>
  58.     class function MaxValue: Integer; static;
  59.     /// <summary> El valor maximo del enum. Equivalente a Ord(Low(T)) </summary>
  60.     class function MinValue: Integer; static;
  61.     /// <summary> Devuelve True si el valor del tipo enum se encuentra dentro del rango permitido </summary>
  62.     class function TypeInRange(const Value: T): Boolean; static;
  63.     /// <summary> Devuelve True si el entero se encuentra dentro del rango permitido del tipo enum </summary>
  64.     class function IntegerInRange(const Value: Integer): Boolean; static;
  65.     /// <summary> Eleva una excepcion EEnumOutOfRange si el valor del tipo enum esta fuera del rango
  66.     // permitido </summary>
  67.     /// <param name="Value"> El valor a testear </param>
  68.     /// <param name="Namespace"> Describe el "contexto" de quien invoca a este metodo (ej clase o unidad) </param>
  69.     /// <param name="MethodName"> Nombre del metodo que invoco a esta rutina </param>
  70.     class procedure CheckInRange(const Value: T; const Namespace, MethodName: string); static;
  71.     /// <summary> Cantidad de elementos del enum </summary>
  72.     class function Count: Integer; static;
  73.     /// <summary> Devuelve un Array con los elementos del enum </summary>
  74.     class function AsArray: EnumArray<T>; static;
  75.   end;
  76. {$ENDREGION}
  77.  
  78. implementation
  79.  
  80. uses
  81.   Types,
  82.   Math,
  83.   StrUtils;
  84.  
  85. {$REGION 'Enum<T>'}
  86.  
  87. class function Enum<T>.TypeInRange(const Value: T): Boolean;
  88. begin
  89.   Result := IntegerInRange(ToInteger(Value));
  90. end;
  91.  
  92. class function Enum<T>.IntegerInRange(const Value: Integer): Boolean;
  93. begin
  94.   Result := InRange(Value, MinValue, MaxValue);
  95. end;
  96.  
  97. class function Enum<T>.MaxValue: Integer;
  98. begin
  99.   Result := Enum<T>.EnumTypeData.MaxValue;
  100. end;
  101.  
  102. class function Enum<T>.MinValue: Integer;
  103. begin
  104.   Result := Enum<T>.EnumTypeData.MinValue;
  105. end;
  106.  
  107. class function Enum<T>.ToInteger(const Value: T): Integer;
  108. begin
  109.   Result := 0;
  110.   System.Move(Value, Result, System.SizeOf(Value));
  111. end;
  112.  
  113. class function Enum<T>.TypeName: string;
  114. begin
  115.   Result := string(Enum<T>.EnumTypeInfo.Name);
  116. end;
  117.  
  118. class function Enum<T>.ValueName(const Value: T): string;
  119. begin
  120.   Result := TypInfo.GetEnumName(Enum<T>.EnumTypeInfo, Enum<T>.ToInteger(Value));
  121. end;
  122.  
  123. class function Enum<T>.EnumTypeData: PTypeData;
  124. begin
  125.   Result := TypInfo.GetTypeData(Enum<T>.EnumTypeInfo);
  126. end;
  127.  
  128. class function Enum<T>.EnumTypeInfo: PTypeInfo;
  129. begin
  130.   Result := TypeInfo(T);
  131. end;
  132.  
  133. class procedure Enum<T>.CheckInRange(const Value: T; const Namespace, MethodName: string);
  134. begin
  135.   if not IntegerInRange(ToInteger(Value)) then
  136.     Enum<T>.OutOfRange(Value, Namespace, MethodName);
  137. end;
  138.  
  139. class function Enum<T>.Count: Integer;
  140. begin
  141.   Result := MaxValue - MinValue + 1;
  142. end;
  143.  
  144. class procedure Enum<T>.OutOfRange(const Value: T; const Namespace, MethodName: string);
  145. const
  146.   SEnumOutOfRange = '%s.%s :: %d is out of range for enum %s';
  147. begin
  148.   raise EEnumOutOfRange.CreateFmt(SEnumOutOfRange, [Namespace, MethodName, ToInteger(Value), TypeName]);
  149. end;
  150.  
  151. class function Enum<T>.Parse(const Ordinal: Integer): ContainedEnum<T>;
  152. begin
  153.   Assert(System.SizeOf(Result) <= System.SizeOf(Ordinal));
  154.   Move(Ordinal, Result, System.SizeOf(Result));
  155. end;
  156.  
  157. class function Enum<T>.Parse(const EnumValueName: string): ContainedEnum<T>;
  158. var
  159.   Each: ContainedEnum<T>;
  160. begin
  161.   for Each in Enum<T>.AsArray do
  162.   begin
  163.     if Enum<T>.ValueName(Each.Value) = EnumValueName then
  164.       Exit(Each);
  165.   end;
  166.  
  167.   StringParseError(EnumValueName);
  168. end;
  169.  
  170. class procedure Enum<T>.NameNotFound(const Identifier: string; const Value: T);
  171. const
  172.   SEnumNameNotFound = 'EnumName not found for %s.%s with identifier %s';
  173. begin
  174.   raise EEnumNameNotFound.CreateFmt(SEnumNameNotFound, [TypeName, ValueName(Value), Identifier]);
  175. end;
  176.  
  177. class procedure Enum<T>.StringParseError(const Value: string);
  178. const
  179.   SCannotParseString = '%s is not defined in enum %s';
  180. begin
  181.   raise EEnumParseError.CreateFmt(SCannotParseString, [Value, TypeName]);
  182. end;
  183.  
  184. class function Enum<T>.AsArray: EnumArray<T>;
  185. var
  186.   I: Integer;
  187. begin
  188.   System.SetLength(Result, Enum<T>.Count);
  189.   for I := System.Low(Result) to System.High(Result) do
  190.     Result[I] := Enum<T>.Parse(I);
  191. end;
  192.  
  193. {$ENDREGION}
  194.  
  195. constructor ContainedEnum<T>.Create(const Value: T);
  196. begin
  197.   FEnumValue := Value;
  198. end;
  199.  
  200. class operator ContainedEnum<T>.Implicit(const Value: T): ContainedEnum<T>;
  201. begin
  202.   Result := ContainedEnum<T>.Create(Value);
  203. end;
  204.  
  205. class operator ContainedEnum<T>.Implicit(const Value: Integer): ContainedEnum<T>;
  206. begin
  207.   Result := ContainedEnum<T>.Create(Enum<T>.Parse(Value).Value);
  208. end;
  209.  
  210. class operator ContainedEnum<T>.Implicit(const Value: string): ContainedEnum<T>;
  211. begin
  212.   Result := ContainedEnum<T>.Create(Enum<T>.Parse(Value).Value);
  213. end;
  214.  
  215. class operator ContainedEnum<T>.Implicit(const Value: ContainedEnum<T>): Integer;
  216. begin
  217.   Result := Enum<T>.ToInteger(Value.FEnumValue);
  218. end;
  219.  
  220. class operator ContainedEnum<T>.Implicit(const Value: ContainedEnum<T>): string;
  221. begin
  222.   Result := Enum<T>.ValueName(Value.FEnumValue);
  223. end;
  224.  
  225. { class operator ContainedEnum<T>.Implicit(const Value: ContainedEnum<T>): T;
  226. begin
  227.   Result := Value.FEnumValue;
  228. end; }
  229.  
  230. function ContainedEnum<T>.ToInteger: Integer;
  231. begin
  232.   Result := Self;
  233. end;
  234.  
  235. function ContainedEnum<T>.ToString: string;
  236. begin
  237.   Result := Self;
  238. end;
  239.  
  240. end.
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×