Advertisement
Vearie

Steam VDF/ACF File Parser (libraryfolders.vdf, libraryfolder.vdf, appmanifest.acf, appworkshop.acf)

Feb 19th, 2022
1,874
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.64 KB | None | 0 0
  1. # libraryfolders.vdf
  2. # libraryfolder.vdf
  3. # appmanifest_%d.acf
  4. # appworkshop_%d.acf
  5.  
  6. class VDF_ParseError(Exception):
  7.     def __init__(self, msg, line, col):
  8.         self.msg = msg
  9.         self.line = line
  10.         self.col = col
  11.    
  12.     def __str__(self):
  13.         return self.msg + " (line %d column %d)" % (self.line + 1, self.col + 1) # +1 for 0-based to 1-based
  14.  
  15. def read(path):
  16.     """Returns dictionary of {key: value or sub}, case sensitive."""
  17.     with open(path, "r") as f:
  18.         escape = False
  19.         in_quote = False
  20.         words = []
  21.        
  22.         root = {}
  23.         section = root
  24.         section_history = []
  25.        
  26.         for line, row_content in enumerate(f):
  27.             for col, c in enumerate(row_content):
  28.                 if in_quote:
  29.                     if c in "\r\n":
  30.                         raise VDF_ParseError("unterminated string %r" % word, line, col)
  31.                     elif escape:
  32.                         escape = False
  33.                         # c is an escaped character (not handled for now)
  34.                         words[-1] += "\\" + c
  35.                     elif c == in_quote:
  36.                         in_quote = False
  37.                         if len(words) == 2:
  38.                             key, value = tuple(words)
  39.                             section[key] = value
  40.                             words = []
  41.                         elif len(words) > 2:
  42.                             raise VDF_ParseError("expected 2 items for key and value but got %d items" % len(words), line, col)
  43.                     elif c == "\\":
  44.                         escape = True
  45.                     else:
  46.                         words[-1] += c
  47.                 elif c in "'\"":
  48.                     in_quote = c
  49.                     words += [""]
  50.                 elif c == "{":
  51.                     if len(words) != 1:
  52.                         raise VDF_ParseError("expected exactly 1 item before opening brace but got %d items" % len(words), line, col)
  53.                    
  54.                     new_section = {}
  55.                     section_history.append(section)
  56.                     section[words[0]] = new_section
  57.                     section = new_section
  58.                     words = []
  59.                 elif c == "}":
  60.                     if len(section_history) <= 0:
  61.                         raise VDF_ParseError("closing brace not expected", line, col)
  62.                     section = section_history.pop()
  63.                 elif not c.isspace():
  64.                     raise VDF_ParseError("unexpected symbol %r" % c, line, col)
  65.        
  66.         if len(section_history) > 0:
  67.             raise VDF_ParseError("%d braces left unclosed" % len(section_at)-1, line, col)
  68.        
  69.         return root
  70.  
  71. def write(f, vdf, lvl=0):
  72.     for key, value in vdf.items():
  73.         if type(value) is dict:
  74.             f.write("\t"*lvl + "\"%s\"\n" % str(key))
  75.             f.write("\t"*lvl + "{\n")
  76.             write(f, value, lvl+1)
  77.             f.write("\t"*lvl + "}\n")
  78.         elif type(value) is str:
  79.             f.write("\t"*lvl + "\"%s\"\t\t\"%s\"\n" % (str(key), str(value)))
  80.         else:
  81.             raise TypeError("expected dict or str not %r" % type(value))
  82.  
  83. if __name__ == "__main__":
  84.     vdf = read(r"C:\Program Files (x86)\Steam\steamapps\libraryfolders.vdf")
  85.    
  86.     # How to use (KeyError is raised if you enter invalid key)
  87.     print(vdf["libraryfolders"]["0"])
  88.    
  89.     # Display all
  90.     #~ with open(1, "w") as f:
  91.         #~ write(f, vdf)
  92.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement