
  # -------------------------------------------------------------------------------------------------------------------------  #
  #  -----------------------------------------------------------------------------------------------------------------------   #
  #                                                                                                                            #
  #           File Name              :  findQuotedChars.r                                                                      #
  #           Last Updated Funclist  :  15 Feb 2014,  1:13 AM (Saturday)                                                       #
  #                                                                                                                            #
  #           Author Name            :  Rick Saporta                                                                           #
  #           Author Email           :  RickSaporta@gmail.com                                                                  #
  #           Author URL             :  www.github.com/rsaporta                                                                #
  #                                                                                                                            #
  #           Packages Called        :  NA                                                                                     #
  #           Packages Used via NS   :  NA                                                                                     #
  #                                                                                                                            #
  #  -----------------------------------------------------------------------------------------------------------------------   #
  #                                                                                                                            #
  #   findQuotedChars    ( x, quotes=c("both", "single", "double") )                                                           #
  #   is.odd             ( n, use.length=(length(n) != 1) )                                                                    #
  #                                                                                                                            #
  #                                                                                                                            #
  #                                                     <END FUNCS>                                                            #
  #  -----------------------------------------------------------------------------------------------------------------------   #
  # -------------------------------------------------------------------------------------------------------------------------  #

# Test1 <- "1hello \"There\" world 'This is quoted' This is not \"This is also quoted\" "
# Test2 <- "2hello 'This is quoted' This is NOT. 'This \\'STILL is quoted'   "
# Test3 <- '3hello "This is quoted" This is NOT. "This \'STOPS is not quoted'
# Test4 <- "2hello 'This is quoted' This is NOT. 'This \\\'STILL is quoted'   " ## same as Test2
# Test5 <- "2hello 'This is quoted' This is NOT. 'This \\\\'NO LONGER is quoted'   "

               
Test0 <- "XX 'Is This Quo'ted' XX"        #            ..  count: 0   ..  x
Test1 <- "XX 'Is This Quo\'ted' XX"       # same as 0  ..  count: 0   ..  x
Test2 <- "XX 'Is This Quo\\'ted' XX"      #            ..  count: 1   ..  YES, quoted (mid quote is ignored)
Test3 <- "XX 'Is This Quo\\\'ted' XX"     # same as 2  ..  count: 1   ..  YES, quoted (mid quote is ignored)
Test4 <- "XX 'Is This Quo\\\\'ted' XX"    #            ..  count: 2   ..  x
Test5 <- "XX 'Is This Quo\\\\\'ted' XX"   # same as 4  ..  count: 2   ..  x
Test6 <- "XX 'Is This Quo\\\\\\'ted' XX"  #            ..  count: 3   ..  YES, quoted (mid quote is ignored)
Test7 <- "XX 'Is This Quo\\\\\\\'ted' XX" # same as 6  ..  count: 3   ..  YES, quoted (mid quote is ignored)

identical(Test0, Test1)
identical(Test1, Test2)
identical(Test2, Test3)
identical(Test3, Test4)
identical(Test4, Test5)
identical(Test5, Test6)
identical(Test6, Test7)

TESTALL <- ls(pattern="Test\\d+")
TESTALL <- setNames(nm=TESTALL)
TESTALL <- lapply(TESTALL, function(x) get(x))

# note on the regex: we want to count how many single backslashes.
# To give the grep engine a backslash, we need to escape it, in regex. 
#   to that's  \\
# However, that requires, in R, for each one of those slashes to be escaped
#   so we get four  \\\\
backslash <- "(\\\\)+"
escapes <- sapply(TESTALL, function(x) attr(gregexpr(backslash, x)[[1L]], "match.length"))

escapes <- gregexpr("(\\\\)+", x)

identical(substr(Test4, 2, 1e4), substr(Test2, 2, 1e4))
identical(substr(Test3, 2, 1e4), substr(Test2, 2, 1e4))
identical(substr(Test5, 2, 1e4), substr(Test2, 2, 1e4))

x <- Test7
showCharIndex(x)

findQuotedChars <- function(x, quotes=c("both", "single", "double")) {
  rege
  qchars <- c("'", '"')

  qchar <- "'"
  matches <- gregexpr(qchar, x)
  matches 

  ## If a match is preceeded by an escape "\", then it should not be counted
  ##   HOWEVER, the escape might be preceeded by one as well. 
  ##            thus we have to count up the preceeding slashes, and 
  ##                if that number is odd, then we disregard the quote char, 
  ##                if that number is even, then the quote char is considered normal



  # note on the regex: we want to count how many single backslashes.
  # To give the grep engine a backslash, we need to escape it, in regex. 
  #   to that's  \\
  # However, that requires, in R, for each one of those slashes to be escaped
  #   so we get four  \\\\
  # We add a "+" because we want any ammmount of at least one
  backslash <- "(\\\\)+"

  is.odd <- function(n, use.length=(length(n) != 1)) {
    if (use.length)
      n = length(n)

    return(identical(as.numeric(n) %% 2, 1))
  }

  escapes <- gregexpr(backslash, x) # note on the regex: we want to find 
  # check if the match.length is odd. If so, include that match as one we should drop.
  #    Notice that the nchar value of the quote to be ignored is equal to the nchar value of the backslash match plus its match length
  escapes <- lapply(escapes, function(es) if (is.odd(ml <- attr(es, "match.length"))) es + ml )

  matches.clean <- mapply(setdiff, matches, escapes, SIMPLIFY=FALSE)
  
  ## The number of matches in each x should be even (ie open & close). If not, there is an issue
  errs <- sapply(matches.clean, is.odd, use.length=TRUE)
  if (any(errs))  {

    ~~~ LEFT OFF HERE...    THIS IS NOT COMPLETELY CORRECT.   WHAT IF THEY ARE WITHIN THE OTHER QUOTE. 

  }


  lens <- sapply(matches.clean, length)

  if (any)
  print(x)
  gregexpr("\\'", x)
  print(Test2)

}

> gregexpr(qchar, x)
[[1]]
[1]  7 22 37 43 59
attr(,"match.length")
[1] 1 1 1 1 1
attr(,"useBytes")
[1] TRUE



 1 2 3 4 5 6 7 8 9  11 2 3 4 5 6 7 8 9 0  22 3 4 5 6 7 8 9 0 1  33 4 5 6 7 8 9 0 1 2  44 5 6 7 8 9 0 1 2 3  55 6 7 8 9 0 1 2                                      
 h e l l o ~ ' T h i s ~ i s ~ q u o t e d ' ~ T h i s ~ i s ~ N O T . ~ ' T h i s ~ ' S T I L L ~ i s ~ q u o t e d ' ~ ~ ~                                      
