blob: 5af64002deeabde1e1c005cd0f31f1be8d810b6d [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import re
def quote(input_str, specials, escape='\\'):
"""Returns a quoted version of |str|, where every character in the
iterable |specials| (usually a set or a string) and the escape
character |escape| is replaced by the original character preceded by
the escape character."""
assert len(escape) == 1
# Since escape is used in replacement pattern context, so we need to
# ensure that it stays a simple literal and cannot affect the \1
# that will follow it.
if escape == '\\':
escape = '\\\\'
if len(specials) > 0:
return re.sub(r'(' + r'|'.join(specials)+r'|'+escape + r')',
escape + r'\1', input_str)
return re.sub(r'(' + escape + r')', escape + r'\1', input_str)
def unquote(input_str, specials, escape='\\'):
"""Splits the input string |input_str| where special characters in
the input |specials| are, if not quoted by |escape|, used as
delimiters to split the string. The returned value is a list of
strings of alternating non-specials and specials used to break the
string. The list will always begin with a possibly empty string of
non-specials, but may end with either specials or non-specials."""
assert len(escape) == 1
out = []
cur_out = []
cur_special = False
lit_next = False
for c in input_str:
if cur_special:
lit_next = (c == escape)
if c not in specials or lit_next:
cur_special = False
out.append(''.join(cur_out))
if not lit_next:
cur_out = [c]
else:
cur_out = []
else:
cur_out.append(c)
else:
if lit_next:
cur_out.append(c)
lit_next = False
else:
lit_next = c == escape
if c not in specials:
if not lit_next:
cur_out.append(c)
else:
out.append(''.join(cur_out))
cur_out = [c]
cur_special = True
out.append(''.join(cur_out))
return out