String.ob 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. MODULE String;
  2. CONST
  3. offs8 = 8;
  4. offs16 = 8 + 16;
  5. offs32 = offs16 + 32;
  6. offs64 = offs32 + 64;
  7. offs128 = offs64 + 128;
  8. offs256 = offs128 + 256;
  9. offs512 = offs256 + 512;
  10. offs1024 = offs512 + 1024;
  11. chunkSize = 4096;
  12. TYPE
  13. Type* = POINTER TO RECORD
  14. size: INTEGER;
  15. data: ARRAY 8 OF CHAR;
  16. next: POINTER TO Data16
  17. END;
  18. Data16 = RECORD
  19. data: ARRAY 16 OF CHAR;
  20. next: POINTER TO Data32
  21. END;
  22. Data32 = RECORD
  23. data: ARRAY 32 OF CHAR;
  24. next: POINTER TO Data64
  25. END;
  26. Data64 = RECORD
  27. data: ARRAY 64 OF CHAR;
  28. next: POINTER TO Data128
  29. END;
  30. Data128 = RECORD
  31. data: ARRAY 128 OF CHAR;
  32. next: POINTER TO Data256
  33. END;
  34. Data256 = RECORD
  35. data: ARRAY 256 OF CHAR;
  36. next: POINTER TO Data512
  37. END;
  38. Data512 = RECORD
  39. data: ARRAY 512 OF CHAR;
  40. next: POINTER TO Data1024
  41. END;
  42. Data1024 = RECORD
  43. data: ARRAY 1024 OF CHAR;
  44. next: POINTER TO Chunk
  45. END;
  46. Chunk = RECORD
  47. data: ARRAY chunkSize OF CHAR;
  48. next: POINTER TO Chunk
  49. END;
  50. PROCEDURE fromArray*(a: ARRAY OF CHAR): Type;
  51. VAR
  52. result: Type;
  53. PROCEDURE copy(from: INTEGER; VAR dst: ARRAY OF CHAR): BOOLEAN;
  54. VAR
  55. i: INTEGER;
  56. BEGIN
  57. WHILE (i < LEN(dst)) & (i + from < LEN(a)) DO
  58. dst[i] := a[i + from];
  59. INC(i);
  60. END;
  61. RETURN i + from < LEN(a)
  62. END copy;
  63. PROCEDURE copyToChunks();
  64. VAR
  65. i: INTEGER;
  66. from: INTEGER;
  67. chunk: POINTER TO Chunk;
  68. BEGIN
  69. from := offs1024;
  70. NEW(chunk);
  71. result.next.next.next.next.next.next.next.next := chunk;
  72. WHILE from < LEN(a) DO
  73. IF i = LEN(chunk.data) THEN
  74. NEW(chunk.next);
  75. chunk := chunk.next;
  76. i := 0;
  77. END;
  78. chunk.data[i] := a[from];
  79. INC(i);
  80. INC(from);
  81. END;
  82. END copyToChunks;
  83. BEGIN
  84. NEW(result);
  85. IF copy(0, result.data) THEN
  86. NEW(result.next);
  87. IF copy(offs8, result.next.data) THEN
  88. NEW(result.next.next);
  89. IF copy(offs16, result.next.next.data) THEN
  90. NEW(result.next.next.next);
  91. IF copy(offs32, result.next.next.next.data) THEN
  92. NEW(result.next.next.next.next);
  93. IF copy(offs64, result.next.next.next.next.data) THEN
  94. NEW(result.next.next.next.next.next);
  95. IF copy(offs128, result.next.next.next.next.next.data) THEN
  96. NEW(result.next.next.next.next.next.next);
  97. IF copy(offs256, result.next.next.next.next.next.next.data) THEN
  98. NEW(result.next.next.next.next.next.next.next);
  99. IF copy(offs512, result.next.next.next.next.next.next.next.data) THEN
  100. copyToChunks();
  101. END;
  102. END;
  103. END;
  104. END;
  105. END;
  106. END;
  107. END;
  108. END;
  109. result.size := LEN(a);
  110. RETURN result
  111. END fromArray;
  112. PROCEDURE size*(s: Type): INTEGER;
  113. RETURN s.size
  114. END size;
  115. PROCEDURE at*(s: Type; index: INTEGER): CHAR;
  116. VAR
  117. result: CHAR;
  118. PROCEDURE chunkAt(): CHAR;
  119. VAR
  120. i: INTEGER;
  121. chunk: POINTER TO Chunk;
  122. BEGIN
  123. chunk := s.next.next.next.next.next.next.next.next;
  124. FOR i := 0 TO ((index - offs1024) DIV chunkSize) - 1 DO
  125. chunk := chunk.next;
  126. END;
  127. RETURN chunk.data[(index - offs1024) MOD chunkSize]
  128. END chunkAt;
  129. BEGIN
  130. IF index < offs8 THEN
  131. result := s.data[index];
  132. ELSIF index < offs16 THEN
  133. result := s.next.data[index - offs8];
  134. ELSIF index < offs32 THEN
  135. result := s.next.next.data[index - offs16];
  136. ELSIF index < offs64 THEN
  137. result := s.next.next.next.data[index - offs32];
  138. ELSIF index < offs128 THEN
  139. result := s.next.next.next.next.data[index - offs64];
  140. ELSIF index < offs256 THEN
  141. result := s.next.next.next.next.next.data[index - offs128];
  142. ELSIF index < offs512 THEN
  143. result := s.next.next.next.next.next.next.data[index - offs256];
  144. ELSIF index < offs1024 THEN
  145. result := s.next.next.next.next.next.next.next.data[index - offs512];
  146. ELSE
  147. result := chunkAt();
  148. END
  149. RETURN result
  150. END at;
  151. END String.