Skip to content

Instantly share code, notes, and snippets.

@JPVenson
Created May 28, 2017 13:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JPVenson/0115abee42379567f72173305b57e611 to your computer and use it in GitHub Desktop.
Save JPVenson/0115abee42379567f72173305b57e611 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Linq;
using System.Text;
namespace JPB.PersonalWebpage.Helper
{
public class Minify
{
private static Encoding DefaultEncoding(Encoding encoding)
{
return encoding ?? Encoding.ASCII;
}
public static Stream MinifyStream(Stream unMinifyed, Encoding encoding = null, bool keepStreamOpen = false)
{
try
{
var memStream = new MemoryStream();
using (var reader = new BinaryReader(unMinifyed))
{
MinifyFromStream(memStream, reader, DefaultEncoding(encoding));
}
return memStream;
}
finally
{
if (!keepStreamOpen)
{
unMinifyed.Dispose();
}
}
}
public static Stream MinifyString(string unMinifyed, Encoding encoding = null)
{
var memStream = new MemoryStream();
encoding = DefaultEncoding(encoding);
using (var stReader = new MemoryStream(encoding.GetBytes(unMinifyed)))
{
using (var reader = new BinaryReader(stReader))
{
MinifyFromStream(memStream, reader, DefaultEncoding(encoding));
}
}
return memStream;
}
/// <summary>
/// Main process
/// </summary>
private static void MinifyFromStream(Stream targetStream, BinaryReader sourceReader, Encoding encoding)
{
var lastChar = 1; // current byte read
var nextChar = -1; // byte read in peek()
var endProcess = false; // loop control
var ignore = false; // if false then add byte to final output
var inComment = false; // true when current bytes are part of a comment
var isDoubleSlashComment = false; // '//' comment
// main processing loop
while (!endProcess)
{
endProcess = sourceReader.PeekChar() == -1; // check for EOF before reading
if (endProcess)
{
break;
}
ignore = false;
int thisChar = sourceReader.ReadByte(); // previous byte read
if (thisChar == '\t')
{
thisChar = ' ';
}
else if (thisChar == '\t')
{
thisChar = '\n';
}
else if (thisChar == '\r')
{
thisChar = '\n';
}
if (thisChar == '\n')
{
ignore = true;
}
if (thisChar == ' ')
{
if (lastChar == ' ' || IsDelimiter(lastChar) == 1)
{
ignore = true;
}
else
{
endProcess = sourceReader.PeekChar() == -1; // check for EOF
if (!endProcess)
{
nextChar = sourceReader.PeekChar();
if (IsDelimiter(nextChar) == 1)
{
ignore = true;
}
}
}
}
if (thisChar == '/')
{
nextChar = sourceReader.PeekChar();
if (nextChar == '/' || nextChar == '*')
{
ignore = true;
inComment = true;
if (nextChar == '/')
{
isDoubleSlashComment = true;
}
else
{
isDoubleSlashComment = false;
}
}
}
// ignore all characters till we reach end of comment
if (inComment)
{
while (true)
{
thisChar = sourceReader.ReadByte();
if (thisChar == '*')
{
nextChar = sourceReader.PeekChar();
if (nextChar == '/')
{
thisChar = sourceReader.ReadByte();
inComment = false;
break;
}
}
if (isDoubleSlashComment && thisChar == '\n')
{
inComment = false;
break;
}
} // while (true)
ignore = true;
} // if (inComment)
if (!ignore)
{
AddToOutput(targetStream, thisChar, encoding);
}
lastChar = thisChar;
} // while (!endProcess)
}
/// <summary>
/// Add character to modified data string
/// </summary>
/// <param name="target">The stream to write to</param>
/// <param name="c">char to add</param>
private static void AddToOutput(Stream target, int c, Encoding encoding)
{
var encoeded = encoding.GetBytes(((char) c).ToString());
target.Write(encoeded, 0, encoeded.Length);
}
/// <summary>
/// Check if a byte is alphanumeric
/// </summary>
/// <param name="c">byte to check</param>
/// <returns>retval - 1 if yes. else 0</returns>
private static int IsAlphanumeric(int c)
{
var retval = 0;
if (c >= 'a' && c <= 'z' ||
c >= '0' && c <= '9' ||
c >= 'A' && c <= 'Z' ||
c == '_' || c == '$' || c == '\\' || c > 126)
{
retval = 1;
}
return retval;
}
private static readonly char[] Delimiter = new[]
{
'(', ',', '=', ':',
'[', '!', '&', '|',
'?', '+', '-', '~',
'*', '/', '{', '\n',
',',
};
/// <summary>
/// Check if a byte is a delimiter
/// </summary>
/// <param name="c">byte to check</param>
/// <returns>retval - 1 if yes. else 0</returns>
private static int IsDelimiter(int c)
{
var retval = 0;
if (Delimiter.Contains((char)c))
{
retval = 1;
}
return retval;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment