1111import com .laytonsmith .annotations .api ;
1212import com .laytonsmith .annotations .core ;
1313import com .laytonsmith .annotations .noboilerplate ;
14+ import com .laytonsmith .core .ArgumentValidation ;
1415import com .laytonsmith .core .MSLog ;
1516import com .laytonsmith .core .MSVersion ;
1617import com .laytonsmith .core .LogLevel ;
@@ -64,8 +65,8 @@ public static String docs() {
6465 @ DocumentLink (0 )
6566 public static class read extends AbstractFunction implements DocumentLinkProvider {
6667
67- public static String file_get_contents (String fileLocation ) throws Exception {
68- return new ZipReader (new File (fileLocation )).getFileContents ();
68+ public static String file_get_contents (String fileLocation , String charset ) throws Exception {
69+ return new ZipReader (new File (fileLocation )).getFileContents (charset );
6970 }
7071
7172 @ Override
@@ -75,19 +76,23 @@ public String getName() {
7576
7677 @ Override
7778 public Integer [] numArgs () {
78- return new Integer []{1 };
79+ return new Integer []{1 , 2 };
7980 }
8081
8182 @ Override
8283 public Mixed exec (Target t , Environment env , Mixed ... args ) throws CancelCommandException , ConfigRuntimeException {
8384 File location = Static .GetFileFromArgument (args [0 ].val (), env , t , null );
85+ String charset = "UTF-8" ;
86+ if (args .length > 1 ) {
87+ charset = ArgumentValidation .getString (args [1 ], t );
88+ }
8489 try {
8590 // Verify this file is not above the craftbukkit directory (or whatever directory the user specified).
8691 // Cmdline mode doesn't currently have this restriction.
8792 if (!Static .InCmdLine (env , true ) && !Security .CheckSecurity (location )) {
8893 throw new CRESecurityException ("You do not have permission to access the file '" + location + "'" , t );
8994 }
90- String s = file_get_contents (location .getAbsolutePath ());
95+ String s = file_get_contents (location .getAbsolutePath (), charset );
9196 s = s .replace ("\r \n " , "\n " );
9297 return new CString (s , t );
9398 } catch (Exception ex ) {
@@ -100,10 +105,11 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws CancelCommand
100105
101106 @ Override
102107 public String docs () {
103- return "string {file} Reads in a file from the file system at location var1 and returns it as a string. The path is relative to"
108+ return "string {file, [encoding] } Reads in a file from the file system at location var1 and returns it as a string. The path is relative to"
104109 + " the file that is being run, not CommandHelper. If the file is not found, or otherwise can't be read in, an IOException is thrown."
105110 + " If the file specified is not within base-dir (as specified in the preferences file), a SecurityException is thrown."
106- + " The line endings for the string returned will always be \\ n, even if they originally were \\ r\\ n." ;
111+ + " The line endings for the string returned will always be \\ n, even if they originally were \\ r\\ n. Encoding defaults"
112+ + " to UTF-8 if not specified." ;
107113 }
108114
109115 @ Override
@@ -165,15 +171,16 @@ public String getName() {
165171
166172 @ Override
167173 public Integer [] numArgs () {
168- return new Integer []{1 };
174+ return new Integer []{1 , 2 };
169175 }
170176
171177 @ Override
172178 public String docs () {
173- return "string {path} Returns the value of a file at compile time only. Unlike read, this runs and is fully resolved"
179+ return "string {path, [encoding] } Returns the value of a file at compile time only. Unlike read, this runs and is fully resolved"
174180 + " at compile time. This is useful for optimization reasons, if you have a file that is unchanging, this can be"
175181 + " used instead of read(), to prevent a runtime hit each time the code is executed. Otherwise, this method is"
176- + " equivalent to read(). The path must be fully resolved at compile time." ;
182+ + " equivalent to read(). The path must be fully resolved at compile time. Encoding is optional, and"
183+ + " defaults to UTF-8." ;
177184 }
178185
179186 @ Override
@@ -195,7 +202,13 @@ public ParseTree optimizeDynamic(Target t, Environment env,
195202 throw new ConfigCompileException (getName () + " can only accept hardcoded paths." , t );
196203 }
197204
198- String ret = new read ().exec (t , env , children .get (0 ).getData ()).val ();
205+ String ret ;
206+ if (children .size () == 1 ) {
207+ ret = new read ().exec (t , env , children .get (0 ).getData ()).val ();
208+ } else {
209+ ret = new read ().exec (t , env , children .get (0 ).getData (),
210+ children .get (1 ).getData ()).val ();
211+ }
199212 ParseTree tree = new ParseTree (new CString (ret , t ), fileOptions );
200213 return tree ;
201214 }
@@ -253,8 +266,16 @@ public Mixed exec(final Target t, final Environment environment, Mixed... args)
253266 startup ();
254267 final String file = args [0 ].val ();
255268 final CClosure callback ;
256- if (!(args [1 ].isInstanceOf (CClosure .TYPE ))) {
257- throw new CRECastException ("Expected parameter 2 of " + getName () + " to be a closure!" , t );
269+ int callbackIndex = 0 ;
270+ String _encoding = "UTF-8" ;
271+ if (args .length == 3 ) {
272+ _encoding = ArgumentValidation .getString (args [1 ], t );
273+ callbackIndex = 1 ;
274+ }
275+ final String encoding = _encoding ;
276+
277+ if (!(args [1 + callbackIndex ].isInstanceOf (CClosure .TYPE ))) {
278+ throw new CRECastException ("Expected parameter " + (2 + callbackIndex ) + " of " + getName () + " to be a closure!" , t );
258279 } else {
259280 callback = ((CClosure ) args [1 ]);
260281 }
@@ -285,7 +306,7 @@ public void run() {
285306 try {
286307 //It's a local file read
287308 File _file = Static .GetFileFromArgument (file , environment , t , null );
288- returnString = FileUtil .read (_file );
309+ returnString = FileUtil .read (_file , encoding );
289310 } catch (IOException ex ) {
290311 exception = new CREIOException (ex .getMessage (), t , ex );
291312 }
@@ -322,12 +343,12 @@ public String getName() {
322343
323344 @ Override
324345 public Integer [] numArgs () {
325- return new Integer []{2 };
346+ return new Integer []{2 , 3 };
326347 }
327348
328349 @ Override
329350 public String docs () {
330- return "void {file, callback} Asyncronously reads in a file. ---- "
351+ return "void {file, [encoding], callback} Asyncronously reads in a file. ---- "
331352 + " This may be a remote file accessed with an SCP style path. (See the [[SCP|wiki article]]"
332353 + " about SCP credentials for more information.) If the file is not found, or otherwise can't be read in, an IOException is thrown."
333354 + " If the file specified is not within base-dir (as specified in the preferences file), a SecurityException is thrown."
0 commit comments