FileUserDataBase.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using MoonSharp.Interpreter.Execution;
  6. namespace MoonSharp.Interpreter.CoreLib.IO
  7. {
  8. /// <summary>
  9. /// Abstract class implementing a file Lua userdata. Methods are meant to be called by Lua code.
  10. /// </summary>
  11. public abstract class FileUserDataBase : RefIdObject
  12. {
  13. public DynValue lines(ScriptExecutionContext executionContext, CallbackArguments args)
  14. {
  15. List<DynValue> readLines = new List<DynValue>();
  16. DynValue readValue = null;
  17. do
  18. {
  19. readValue = read(executionContext, args);
  20. readLines.Add(readValue);
  21. } while (readValue.IsNotNil());
  22. return DynValue.FromObject(executionContext.GetScript(), readLines.Select(s => s));
  23. }
  24. public DynValue read(ScriptExecutionContext executionContext, CallbackArguments args)
  25. {
  26. if (args.Count == 0)
  27. {
  28. string str = ReadLine();
  29. if (str == null)
  30. return DynValue.Nil;
  31. str = str.TrimEnd('\n', '\r');
  32. return DynValue.NewString(str);
  33. }
  34. else
  35. {
  36. List<DynValue> rets = new List<DynValue>();
  37. for (int i = 0; i < args.Count; i++)
  38. {
  39. DynValue v;
  40. if (args[i].Type == DataType.Number)
  41. {
  42. if (Eof())
  43. return DynValue.Nil;
  44. int howmany = (int)args[i].Number;
  45. string str = ReadBuffer(howmany);
  46. v = DynValue.NewString(str);
  47. }
  48. else
  49. {
  50. string opt = args.AsType(i, "read", DataType.String, false).String;
  51. if (Eof())
  52. {
  53. v = opt.StartsWith("*a") ? DynValue.NewString("") : DynValue.Nil;
  54. }
  55. else if (opt.StartsWith("*n"))
  56. {
  57. double? d = ReadNumber();
  58. if (d.HasValue)
  59. v = DynValue.NewNumber(d.Value);
  60. else
  61. v = DynValue.Nil;
  62. }
  63. else if (opt.StartsWith("*a"))
  64. {
  65. string str = ReadToEnd();
  66. v = DynValue.NewString(str);
  67. }
  68. else if (opt.StartsWith("*l"))
  69. {
  70. string str = ReadLine();
  71. str = str.TrimEnd('\n', '\r');
  72. v = DynValue.NewString(str);
  73. }
  74. else if (opt.StartsWith("*L"))
  75. {
  76. string str = ReadLine();
  77. str = str.TrimEnd('\n', '\r');
  78. str += "\n";
  79. v = DynValue.NewString(str);
  80. }
  81. else
  82. {
  83. throw ScriptRuntimeException.BadArgument(i, "read", "invalid option");
  84. }
  85. }
  86. rets.Add(v);
  87. }
  88. return DynValue.NewTuple(rets.ToArray());
  89. }
  90. }
  91. public DynValue write(ScriptExecutionContext executionContext, CallbackArguments args)
  92. {
  93. try
  94. {
  95. for (int i = 0; i < args.Count; i++)
  96. {
  97. //string str = args.AsStringUsingMeta(executionContext, i, "file:write");
  98. string str = args.AsType(i, "write", DataType.String, false).String;
  99. Write(str);
  100. }
  101. return UserData.Create(this);
  102. }
  103. catch (ScriptRuntimeException)
  104. {
  105. throw;
  106. }
  107. catch (Exception ex)
  108. {
  109. return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.Message));
  110. }
  111. }
  112. public DynValue close(ScriptExecutionContext executionContext, CallbackArguments args)
  113. {
  114. try
  115. {
  116. string msg = Close();
  117. if (msg == null)
  118. return DynValue.True;
  119. else
  120. return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(msg));
  121. }
  122. catch (ScriptRuntimeException)
  123. {
  124. throw;
  125. }
  126. catch (Exception ex)
  127. {
  128. return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.Message));
  129. }
  130. }
  131. double? ReadNumber()
  132. {
  133. string chr = "";
  134. while (!Eof())
  135. {
  136. char c = Peek();
  137. if (char.IsWhiteSpace(c))
  138. {
  139. ReadBuffer(1);
  140. }
  141. else if (IsNumericChar(c, chr))
  142. {
  143. ReadBuffer(1);
  144. chr += c;
  145. }
  146. else break;
  147. }
  148. double d;
  149. if (double.TryParse(chr, out d))
  150. {
  151. return d;
  152. }
  153. else
  154. {
  155. return null;
  156. }
  157. }
  158. private bool IsNumericChar(char c, string numAsFar)
  159. {
  160. if (char.IsDigit(c))
  161. return true;
  162. if (c == '-')
  163. return numAsFar.Length == 0;
  164. if (c == '.')
  165. return !numAsFar.Contains('.');
  166. if (c == 'E' || c == 'e')
  167. return !(numAsFar.Contains('E') || numAsFar.Contains('e'));
  168. return false;
  169. }
  170. protected abstract bool Eof();
  171. protected abstract string ReadLine();
  172. protected abstract string ReadBuffer(int p);
  173. protected abstract string ReadToEnd();
  174. protected abstract char Peek();
  175. protected abstract void Write(string value);
  176. protected internal abstract bool isopen();
  177. protected abstract string Close();
  178. public abstract bool flush();
  179. public abstract long seek(string whence, long offset);
  180. public abstract bool setvbuf(string mode);
  181. public override string ToString()
  182. {
  183. if (isopen())
  184. return string.Format("file ({0:X8})", base.ReferenceID);
  185. else
  186. return "file (closed)";
  187. }
  188. }
  189. }