Home | History | Annotate | Download | only in lib
      1 #!/usr/bin/env python
      2 # Copyright 2014 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import re
      7 
      8 def quote(input_str, specials, escape='\\'):
      9   """Returns a quoted version of |str|, where every character in the
     10   iterable |specials| (usually a set or a string) and the escape
     11   character |escape| is replaced by the original character preceded by
     12   the escape character."""
     13 
     14   assert len(escape) == 1
     15 
     16   # Since escape is used in replacement pattern context, so we need to
     17   # ensure that it stays a simple literal and cannot affect the \1
     18   # that will follow it.
     19   if escape == '\\':
     20     escape = '\\\\'
     21   if len(specials) > 0:
     22     return re.sub(r'(' + r'|'.join(specials)+r'|'+escape + r')',
     23                   escape + r'\1', input_str)
     24   return re.sub(r'(' + escape + r')', escape + r'\1', input_str)
     25 
     26 
     27 def unquote(input_str, specials, escape='\\'):
     28   """Splits the input string |input_str| where special characters in
     29   the input |specials| are, if not quoted by |escape|, used as
     30   delimiters to split the string.  The returned value is a list of
     31   strings of alternating non-specials and specials used to break the
     32   string. The list will always begin with a possibly empty string of
     33   non-specials, but may end with either specials or non-specials."""
     34 
     35   assert len(escape) == 1
     36 
     37   out = []
     38   cur_out = []
     39   cur_special = False
     40   lit_next = False
     41   for c in input_str:
     42     if cur_special:
     43       lit_next = (c == escape)
     44       if c not in specials or lit_next:
     45         cur_special = False
     46         out.append(''.join(cur_out))
     47         if not lit_next:
     48           cur_out = [c]
     49         else:
     50           cur_out = []
     51       else:
     52         cur_out.append(c)
     53     else:
     54       if lit_next:
     55         cur_out.append(c)
     56         lit_next = False
     57       else:
     58         lit_next = c == escape
     59         if c not in specials:
     60           if not lit_next:
     61             cur_out.append(c)
     62         else:
     63           out.append(''.join(cur_out))
     64           cur_out = [c]
     65           cur_special = True
     66   out.append(''.join(cur_out))
     67   return out
     68