Antes de nada, perdón, pués yo puse un mensaje (que deben haber borrado) de "Esto es Spam", por la simple razón de que solo había 2 líneas de texto y un enlace (apuntando fuera del foro), además juraría que vi repetido el mensaje en otro lado... Sin más explicaciones, ni ningún simple ejemplo de nada, sonaba claramente a Spam.
Mirando así por encima, veo cosas muy mejorables.. por ejemplo la simple función de invertir una cadena de texto:
Function ReverseStr(_cIn)
* Invierte el orden de los caracteres de una cadena.
Local _rStr := ""
Local _nB00 := 0
For _nB00 = Len(_cIn) To 1 Step (-1)
_rStr := (_rStr + SubStr(_cIn, _nB00, 1))
Next _nB00
Return (_rStr)
Concatenar una cadena es algo que no debe hacerse más de 1 ó 2 veces para obtener un contenido, por que cada concatenación exige buscar memoria libre con la suma total de caracteres y copiar ahí las partes a unir... luego en un bucle de por ejemplo 100 caracteres invertir esa cadena supone crear 100 veces una cadena y copiar cada vez las partes que la componen, total para ir añadiendo cada vez un solo carácter respecto del contenido previo...
Crea una cadena del largo total (cuando se conoce) o más (si no se conoce y al final se devuelve el 'substring' de solo la parte ocupada)... "_rStr" será igual de larga finalmente que "_cIn", luego procede al comienzo hacerla del mismo tamaño.
... y vas tomando caracteres del final de la cadena y poniéndolos al comienzo, o al revés, los tomas del comienzo y los vas poniendo al final retrocediendo. Así a lo sumo creas solo 2 veces la cadena, independientemente del largo que tenga.
Una forma sencilla de probar ambas funciones (la que tienes y la que tendrías que rehacer), sería usar una cadena de por ejemplo 100Mb. y comparar tiempos, en la que te falta por hacer (la óptima), no llevaría más de unos segundos, en la que tienes posiblemente varios minutos (no sé si bastarían 20)...
Cansa ver la forma en que nombras las variables locales y parámetros:
La barra baja "_cStr", suele usarse en los lenguajes para:
- Separar visualmente palabras en identificadores largos, como en: "Precio_Articulo".
- También para unir 'gramáticamente' el nombre de un objeto al nombre de un evento, como en: "Precio_Changed", existiendo un objeto llamado "Precio" que pertenece a un tipo de datos que tiene un evento llamado "Changed".
- Microsoft, cuando finalmente dió facilidades para crear las propiedades autoimplementadas (yo mismo solicité esa característica... hace ya un chorro de años), usa precisamente la barra baja al comienzo del nombre con el mismo nombre de la propiedad para dar respaldo al campo que ha de mantener el valor de la propiedad, dando así oportunidad al usuario de no usar nombres en tal forma, para evitar errores por duplicidad de declaraciones, es una buena alternativa peor para usar exclusivamente en la parte del compilador, no para que un usuario deba enfrentarse a nombres así formados.
Sugiero que como mínimo remplaces esa barra baja por algún carácter legible... por ejemplo para las locales: "lcStr", para los parámetros: "pcStr", para las locales a nivel de módulo: "mcStr"... etc...
Fíjate que incluso leerlo obliga a decir "barra baja cStr", una vez no importa, pero por cada una es requetecansimo... intenta leer tu propio código para que otro lo copie a medida que te oye, y entenderás el absurdo. Y todas las excusas que te inventes, como indicarle de antemano que es 'una regla', sigue siendo absurda... cambia de interlocutor y verás que resulta absurdo explicarle a cada interlocutor una regla, innecesaria... porque para esos existen las letras del abecedario.. son legibles ocupan lo mismo y dispones de 26 mayúsculas y 26 minúdculas... si tienes una regla para señalar que "los nombres d evariables en parámetros las comienzo con 'p', es una regla que no hay necesidad de explicar a nadie, porque 'pcStr', podría llamarse de cualquier otra manera todo el mundo entenderá que hayas elegido ese nombre por alguna razón.
...de todos modos, es siempre preferible poner nombres significativos a las variables (significativas, los parámetros lo son, las variables de tipo contador por ejemplo no y para ellas les baste j, k, t, n, v, etc...).
...en el mismo sentido los nombres de la mayoría de funciones son amorfas... si el códiigo es para tí, no tiene más importancia, tu sabes 'tus reglas', pero si ofeces tu código a otros, complicas innecesariamente las cosas... de qué sirve poner debajo luego un comentario de lo que hace la función, cuando el propio nombre de la función debería sugerir bastante claro lo que debe hacer...
ejemplo: Tu nombre:
Function "SB"Lo adecuado:
Function "StringToBase36"O como mínimo:
Function "StrToB36"
Otro ejemplo de ineficiencia es ese par de funciones de conversión de ASCII a base 36 y viceversa
Function SB(_cIn)
* Conversor de cadenas de caracteres a cadenas en Base-36.
Local _SB := ""
Local _cTemp00 := ""
Local _cTemp01 := ""
Local _nTemp00 := 0
Local _nB00 := 0
For _nB00 = 1 To Len(_cIn) Step 1
_cTemp00 := (_cTemp00 + AS(Str(Asc(SubStr(_cIn, _nB00, 1)) + 256), 3, (-1), 48))
Next _nB00
Do While (Len(_cTemp00) > 0)
_cTemp01 := Left(_cTemp00, 9)
_nTemp00 := (Val(_cTemp01) + 10^9)
_SB := (_SB + NToC(_nTemp00, 36))
_cTemp00 := Right(_cTemp00, (Len(_cTemp00) - 9))
EndDo
Return (Lower(_SB))
Function BS(_cIn)
* Conversor de cadenas en Base-36 a cadena de caracteres original.
Local _BS := ""
Local _cTemp00 := _cIn
Local _cTemp01 := ""
Local _cTemp02 := ""
Local _cTemp03 := ""
Local _cTemp04 := ""
Local _nTemp00 := 0
Local _nTemp01 := 0
Do While (Len(_cTemp00) > 0)
_cTemp01 := Left(_cTemp00, 6)
_nTemp00 := (CToN(_cTemp01, 36) - 10^9)
_cTemp03 := AllTrim(Str(_nTemp00, 9, 0))
_nTemp01 := IIf((Len(_cTemp03) > 6), 9, IIf((Len(_cTemp03) > 3), 6, 3))
_cTemp04 := AS(_cTemp03, _nTemp01, (-1), 48)
_cTemp02 := (_cTemp02 + _cTemp04)
_cTemp00 := Right(_cTemp00, (Len(_cTemp00) - 6))
EndDo
Do While (Len(_cTemp02) > 0)
_cTemp01 := Left(_cTemp02, 3)
_nTemp00 := xVal(_cTemp01)
_BS := (_BS + Chr(_nTemp00))
_cTemp02 := Right(_cTemp02, (Len(_cTemp02) - 3))
EndDo
Return (_BS)
De entrada el código es tortuoso, mareante y pecas de nuevo con concatenaciones...
Cuando una conversion forma parte de un proyecto, forozoso es, crear sendos arrays para convertir a y desde usando un simple bucle con apenas 1-4 líneas dentro del bucle, tanto para la codificación como para la decodificación...
Incluso en el caso de tener que hacer variadas conversiones tal que no resulte adecuado tener tablar para cada base usada, entonces procede in situ hacer la conversión de forma matemática (división y módulo para codificar y multiplicación y suma para decodificar).
Siempre que se pueda es preferible crear arrays para una traducción rápida, ya que luego el compilador, viendo que tiene un bucle y un array, tratará la direcciones con registro de índice, lo que acelerará las conversiones, pués evita calcular la dirección absoluta para cada índice del array con multiplicaciones...
Encuentro iguales problemas de inficiencia en muchas otras funciones...
También juraría que las funciones "SHCrypt" y "SHDeCrypt" son idénticas... Procede hacerlo más coherente, una sola función basta, puede llamarse "Crypt" y que acepte un parámetro adicional con valor buelano: Si FALSE=SHDeCrypt y si TRUE=SHCrypt, aunque como no hay diferencias en lo que hace da igual.
Otra forma si prefieres mantener los nombres, es dejar una sola funcion, y la otra compleamente vacía se remite simplemente a invocar a la que tiene el código... (porque hacen exactamente lo mismo, solo cambia el nombre de la función).
Además en esa función de cifrado veo muchos 'modulo', pero no veo ningún 'xor'. Ya te digo por descontado que funciones de cifrado basadas exclusivamente en operaciones aritméticas, son proclives a generar patrones reproducibles de los que aprovecharse. Incluso teniendo operaciones 'xor' si no se controlan adecuadamente también están sujetas a lo mismo, como le pasa por ejemplo al algoritmo RC4.
...
En fin, solo he mirado el fichero "S-Hash.Prg" y si no me gusta lo que veo, no creo que el resto vaya a ser distinto...
p.d.: He tenido que retirar las etiqeutas GEsHI, porque al parecer duplica el contenido cuando el lenguaje es "visualfoxpro", y se ve mal...