package br.uff.ic.oceano.core.tools.metrics.extractors.cpp.easycount; import br.uff.ic.oceano.util.file.FileUtils; /** * Converted to Java from http://www.monperrus.net/martin/easysloc.c.txt original c version * @author Daniel */ public class EasyCountService { //TODO Fix class to extract this metrics //TLOC: Total lines of code that will count non-blank and non-comment lines in a compilation unit. //MLOC: Method lines of code will counts and sum non-blank and non-comment lines inside method bodies. //LOC: Total lines of code that will counts non-blank lines in a compilation unit. /** * Total of logical lines of code plus comments * @param path Path to a file * @return * @throws EasyCountServiceException */ public long loc(String path) throws EasyCountServiceException{ final int PREPROCESSING = 8; final int CHAR = 9; final int COMMENT_LINE = 3; final int COMMENT_STAR_OUT = 5; final int STRING_SPECIAL = 7; final int COMMENT_STAR = 4; final int CHAR_SPECIAL = 10; final int COMMENT = 1; final int NORMAL = 0; final int STRING = 6; final int COMMENT_IN = 2; int state = NORMAL; long semicolon = 0; long brace = 0; long comment_logical = 0; long comment_physical = 0; long parenthesis_opened = 0; long preprocessing = 0; final String fileText; try { fileText = FileUtils.readFile(path); } catch (Exception ex) { throw new EasyCountServiceException(ex); } //Empty file if(fileText== null || fileText.isEmpty()){ return 0; } int position = 0; do { final char message = fileText.charAt(position); if ((state != STRING) && (state != CHAR) && (state != STRING_SPECIAL) && (state != CHAR_SPECIAL) && (state != PREPROCESSING) && (state != COMMENT_LINE) && (state != COMMENT_STAR)) { if (message == ';') { semicolon++; } if (message == '{') { brace++; } if (message == '(') { parenthesis_opened++; } } switch (state) { case NORMAL: switch (message) { case '/': state = COMMENT_IN; break; case '"': state = STRING; break; case '#': preprocessing++; state = PREPROCESSING; break; case '\'': state = CHAR; break; default: state = NORMAL; } break; case PREPROCESSING: switch (message) { case '\n': state = NORMAL; break; default: state = PREPROCESSING; } break; case COMMENT_IN: switch (message) { case '/': state = COMMENT_LINE; break; case '*': state = COMMENT_STAR; break; default: state = NORMAL; } break; case COMMENT_LINE: switch (message) { case '\n': comment_logical++; comment_physical++; state = NORMAL; break; default: state = COMMENT_LINE; } break; case COMMENT_STAR: switch (message) { case '*': state = COMMENT_STAR_OUT; break; case '\n': comment_physical++; break; default: state = COMMENT_STAR; } break; case COMMENT_STAR_OUT: switch (message) { case '/': comment_logical++; comment_physical++; state = NORMAL; break; case '\n': comment_physical++; break; case '*': state = COMMENT_STAR_OUT; break; default: state = COMMENT_STAR; } break; case STRING: switch (message) { case '\\': state = STRING_SPECIAL; break; case '"': state = NORMAL; break; default: state = STRING; } break; case STRING_SPECIAL: switch (message) { default: state = STRING; } break; case CHAR: switch (message) { case '\\': state = CHAR_SPECIAL; break; case '\'': state = NORMAL; break; default: state = CHAR; } break; case CHAR_SPECIAL: switch (message) { default: state = CHAR; } break; default: break; } //next char position position++; } while (position != fileText.length()); return semicolon + comment_physical; } }