LogcatTextWriter.cs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #if MONODROID
  2. using System;
  3. using System.IO;
  4. using System.Text;
  5. using System.Runtime.CompilerServices;
  6. using System.Runtime.InteropServices;
  7. using Mono;
  8. namespace System.IO {
  9. class LogcatTextWriter : TextWriter {
  10. const string LibLog = "/system/lib/liblog.so";
  11. const string LibLog64 = "/system/lib64/liblog.so";
  12. readonly byte[] appname;
  13. TextWriter stdout;
  14. StringBuilder line = new StringBuilder ();
  15. public LogcatTextWriter (string appname, TextWriter stdout)
  16. {
  17. this.appname = Encoding.UTF8.GetBytes (appname + '\0');
  18. this.stdout = stdout;
  19. }
  20. public override Encoding Encoding {
  21. get {return Encoding.UTF8;}
  22. }
  23. public override void Write (string s)
  24. {
  25. if (s != null)
  26. foreach (char c in s)
  27. Write (c);
  28. }
  29. public override void Write (char value)
  30. {
  31. if (value == '\n')
  32. WriteLine ();
  33. else
  34. line.Append (value);
  35. }
  36. public override void WriteLine ()
  37. {
  38. var o = line.ToString ();
  39. line.Clear ();
  40. Log (o);
  41. stdout.WriteLine (o);
  42. }
  43. void Log (string message)
  44. {
  45. const int buffer_size = 512;
  46. unsafe {
  47. if (Encoding.UTF8.GetByteCount (message) < buffer_size) {
  48. try {
  49. fixed (char *b_message = message) {
  50. byte* buffer = stackalloc byte[buffer_size];
  51. int written = Encoding.UTF8.GetBytes (b_message, message.Length, buffer, buffer_size - 1);
  52. buffer [written] = (byte)'\0';
  53. Log (buffer);
  54. }
  55. return;
  56. } catch (ArgumentException) {
  57. /* It might be due to a failure to encode a character, or due to a smaller than necessary buffer. In the
  58. * secode case, we want to fallback to simply allocating on the heap. */
  59. }
  60. }
  61. using (SafeStringMarshal str = new SafeStringMarshal(message)) {
  62. Log ((byte*) str.Value);
  63. }
  64. }
  65. }
  66. unsafe void Log (byte* b_message)
  67. {
  68. fixed (byte *b_appname = appname) {
  69. Log (b_appname, 1 << 5 /* G_LOG_LEVEL_MESSAGE */, b_message);
  70. }
  71. }
  72. public static bool IsRunningOnAndroid ()
  73. {
  74. return File.Exists (LibLog) || File.Exists (LibLog64);
  75. }
  76. [MethodImpl(MethodImplOptions.InternalCall)]
  77. static unsafe extern void Log (byte *appname, int level, byte *message);
  78. }
  79. }
  80. #endif // MONODROID