2
0

Kernel-Collections.st 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880
  1. Smalltalk current createPackage: 'Kernel-Collections'!
  2. Object subclass: #Association
  3. instanceVariableNames: 'key value'
  4. package: 'Kernel-Collections'!
  5. !Association commentStamp!
  6. I represent a pair of associated objects, a key and a value. My instances can serve as entries in a dictionary.
  7. Instances can be created with the class-side method `#key:value:`!
  8. !Association methodsFor: 'accessing'!
  9. key
  10. ^key
  11. !
  12. key: aKey
  13. key := aKey
  14. !
  15. value
  16. ^value
  17. !
  18. value: aValue
  19. value := aValue
  20. ! !
  21. !Association methodsFor: 'comparing'!
  22. = anAssociation
  23. ^self class = anAssociation class and: [
  24. self key = anAssociation key and: [
  25. self value = anAssociation value]]
  26. ! !
  27. !Association methodsFor: 'printing'!
  28. printString
  29. "print the contents of the Association into a string and return the string"
  30. ^String streamContents: [:aStream |
  31. self storeOn: aStream]
  32. !
  33. storeOn: aStream
  34. "Store in the format: key->value"
  35. key storeOn: aStream.
  36. aStream nextPutAll: '->'.
  37. value storeOn: aStream.
  38. ! !
  39. !Association class methodsFor: 'instance creation'!
  40. key: aKey value: aValue
  41. ^self new
  42. key: aKey;
  43. value: aValue;
  44. yourself
  45. ! !
  46. Object subclass: #Collection
  47. instanceVariableNames: ''
  48. package: 'Kernel-Collections'!
  49. !Collection commentStamp!
  50. I am the abstract superclass of all classes that represent a group of elements.
  51. I provide a set of useful methods to the Collectiohn hierarchy such as enumerating and converting methods.!
  52. !Collection methodsFor: 'accessing'!
  53. occurrencesOf: anObject
  54. "Answer how many of the receiver's elements are equal to anObject."
  55. | tally |
  56. tally := 0.
  57. self do: [:each | anObject = each ifTrue: [tally := tally + 1]].
  58. ^tally
  59. !
  60. readStream
  61. ^self stream
  62. !
  63. size
  64. self subclassResponsibility
  65. !
  66. stream
  67. ^self streamClass on: self
  68. !
  69. streamClass
  70. ^self class streamClass
  71. !
  72. writeStream
  73. ^self stream
  74. ! !
  75. !Collection methodsFor: 'adding/removing'!
  76. add: anObject
  77. self subclassResponsibility
  78. !
  79. addAll: aCollection
  80. aCollection do: [:each |
  81. self add: each].
  82. ^aCollection
  83. !
  84. remove: anObject
  85. ^self remove: anObject ifAbsent: [self errorNotFound]
  86. !
  87. remove: anObject ifAbsent: aBlock
  88. self subclassResponsibility
  89. ! !
  90. !Collection methodsFor: 'converting'!
  91. asArray
  92. ^Array withAll: self
  93. !
  94. asJSON
  95. ^self asArray collect: [:each | each asJSON]
  96. !
  97. asOrderedCollection
  98. ^self asArray
  99. !
  100. asSet
  101. ^Set withAll: self
  102. ! !
  103. !Collection methodsFor: 'copying'!
  104. , aCollection
  105. ^self copy
  106. addAll: aCollection;
  107. yourself
  108. !
  109. copyWith: anObject
  110. ^self copy add: anObject; yourself
  111. !
  112. copyWithAll: aCollection
  113. ^self copy addAll: aCollection; yourself
  114. !
  115. copyWithoutAll: aCollection
  116. "Answer a copy of the receiver that does not contain any elements
  117. equal to those in aCollection."
  118. ^ self reject: [:each | aCollection includes: each]
  119. ! !
  120. !Collection methodsFor: 'enumerating'!
  121. collect: aBlock
  122. | stream |
  123. stream := self class new writeStream.
  124. self do: [ :each |
  125. stream nextPut: (aBlock value: each) ].
  126. ^stream contents
  127. !
  128. detect: aBlock
  129. ^self detect: aBlock ifNone: [self errorNotFound]
  130. !
  131. detect: aBlock ifNone: anotherBlock
  132. self subclassResponsibility
  133. !
  134. do: aBlock
  135. self subclassResponsibility
  136. !
  137. do: aBlock separatedBy: anotherBlock
  138. | actionBeforeElement |
  139. actionBeforeElement := [actionBeforeElement := anotherBlock].
  140. self do: [:each |
  141. actionBeforeElement value.
  142. aBlock value: each]
  143. !
  144. inject: anObject into: aBlock
  145. | result |
  146. result := anObject.
  147. self do: [:each |
  148. result := aBlock value: result value: each].
  149. ^result
  150. !
  151. intersection: aCollection
  152. "Answer the set theoretic intersection of two collections."
  153. | set outputSet |
  154. set := self asSet.
  155. outputSet := Set new.
  156. aCollection do: [ :each |
  157. ((set includes: each) and: [(outputSet includes: each) not])
  158. ifTrue: [
  159. outputSet add: each]].
  160. ^ self class withAll: outputSet asArray
  161. !
  162. reject: aBlock
  163. ^self select: [:each | (aBlock value: each) = false]
  164. !
  165. select: aBlock
  166. | stream |
  167. stream := self class new writeStream.
  168. self do: [:each |
  169. (aBlock value: each) ifTrue: [
  170. stream nextPut: each]].
  171. ^stream contents
  172. ! !
  173. !Collection methodsFor: 'error handling'!
  174. errorNotFound
  175. self error: 'Object is not in the collection'
  176. ! !
  177. !Collection methodsFor: 'printing'!
  178. printString
  179. "print the contents of the Collection into a string and return it"
  180. ^String streamContents: [:aStream |
  181. aStream
  182. nextPutAll: super printString, ' ('.
  183. self do: [:each | aStream nextPutAll: each printString]
  184. separatedBy: [aStream nextPutAll: ' '].
  185. aStream nextPutAll: ')']
  186. ! !
  187. !Collection methodsFor: 'testing'!
  188. ifEmpty: aBlock
  189. "Evaluate the given block with the receiver as argument, answering its value if the receiver is empty, otherwise answer the receiver. Note that the fact that this method returns its argument in case the receiver is not empty allows one to write expressions like the following ones: self classifyMethodAs:
  190. (myProtocol ifEmpty: ['As yet unclassified'])"
  191. ^ self isEmpty
  192. ifTrue: [ aBlock value ]
  193. ifFalse: [ self ]
  194. !
  195. ifNotEmpty: aBlock
  196. self notEmpty ifTrue: aBlock.
  197. !
  198. includes: anObject
  199. | sentinel |
  200. sentinel := Object new.
  201. ^(self detect: [ :each | each = anObject] ifNone: [ sentinel ]) ~= sentinel
  202. !
  203. isEmpty
  204. ^self size = 0
  205. !
  206. notEmpty
  207. ^self isEmpty not
  208. ! !
  209. !Collection class methodsFor: 'accessing'!
  210. streamClass
  211. ^Stream
  212. ! !
  213. !Collection class methodsFor: 'instance creation'!
  214. new: anInteger
  215. ^self new
  216. !
  217. with: anObject
  218. ^self new
  219. add: anObject;
  220. yourself
  221. !
  222. with: anObject with: anotherObject
  223. ^self new
  224. add: anObject;
  225. add: anotherObject;
  226. yourself
  227. !
  228. with: firstObject with: secondObject with: thirdObject
  229. ^self new
  230. add: firstObject;
  231. add: secondObject;
  232. add: thirdObject;
  233. yourself
  234. !
  235. withAll: aCollection
  236. ^self new
  237. addAll: aCollection;
  238. yourself
  239. ! !
  240. Collection subclass: #IndexableCollection
  241. instanceVariableNames: ''
  242. package: 'Kernel-Collections'!
  243. !IndexableCollection commentStamp!
  244. I am a key-value store, that is,
  245. it stores values under indexes.
  246. As a rule of thumb, if a collection has at: and at:put:,
  247. it is an IndexableCollection.!
  248. !IndexableCollection methodsFor: 'accessing'!
  249. at: anIndex
  250. "Lookup the given index in the receiver.
  251. If it is present, answer the value stored at anIndex.
  252. Otherwise, raise an error."
  253. ^self at: anIndex ifAbsent: [ self errorNotFound ]
  254. !
  255. at: anIndex ifAbsent: aBlock
  256. "Lookup the given index in the receiver.
  257. If it is present, answer the value stored at anIndex.
  258. Otherwise, answer the value of aBlock."
  259. self subclassReponsibility
  260. !
  261. at: anIndex ifPresent: aBlock
  262. "Lookup the given index in the receiver.
  263. If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
  264. Otherwise, answer nil."
  265. ^self at: anIndex ifPresent: aBlock ifAbsent: [ nil ]
  266. !
  267. at: anIndex ifPresent: aBlock ifAbsent: anotherBlock
  268. "Lookup the given index in the receiver.
  269. If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
  270. Otherwise, answer the value of anotherBlock."
  271. self subclassReponsibility
  272. !
  273. at: anIndex put: anObject
  274. "Store anObject under the given index in the receiver."
  275. self subclassReponsibility
  276. !
  277. indexOf: anObject
  278. "Lookup index at which anObject is stored in the receiver.
  279. If not present, raise an error."
  280. ^self indexOf: anObject ifAbsent: [ self errorNotFound ]
  281. !
  282. indexOf: anObject ifAbsent: aBlock
  283. "Lookup index at which anObject is stored in the receiver.
  284. If not present, return value of executing aBlock."
  285. self subclassResponsibility
  286. ! !
  287. !IndexableCollection methodsFor: 'enumeration'!
  288. with: anotherCollection do: aBlock
  289. "Calls aBlock with every value from self
  290. and with indetically-indexed value from anotherCollection"
  291. self withIndexDo: [ :each :index |
  292. aBlock value: each value: (anotherCollection at: index) ]
  293. !
  294. withIndexDo: aBlock
  295. "Calls aBlock with every value from self
  296. and with its index as the second argument"
  297. self subclassReponsibility
  298. ! !
  299. IndexableCollection subclass: #HashedCollection
  300. instanceVariableNames: ''
  301. package: 'Kernel-Collections'!
  302. !HashedCollection commentStamp!
  303. I am a traditional JavaScript object, or a Smalltalk `Dictionary`.
  304. Unlike a `Dictionary`, it can only have strings as keys.!
  305. !HashedCollection methodsFor: 'accessing'!
  306. associations
  307. | associations |
  308. associations := #().
  309. self associationsDo: [:each | associations add: each].
  310. ^associations
  311. !
  312. at: aKey ifAbsent: aBlock
  313. ^(self includesKey: aKey)
  314. ifTrue: [self basicAt: aKey]
  315. ifFalse: aBlock
  316. !
  317. at: aKey ifAbsentPut: aBlock
  318. ^self at: aKey ifAbsent: [
  319. self at: aKey put: aBlock value]
  320. !
  321. at: aKey ifPresent: aBlock ifAbsent: anotherBlock
  322. "Lookup the given key in the receiver.
  323. If it is present, answer the value of evaluating the oneArgBlock with the value associated with the key,
  324. otherwise answer the value of absentBlock."
  325. ^(self includesKey: aKey)
  326. ifTrue: [ aBlock value: (self at: aKey) ]
  327. ifFalse: anotherBlock
  328. !
  329. at: aKey put: aValue
  330. ^self basicAt: aKey put: aValue
  331. !
  332. indexOf: anObject ifAbsent: aBlock
  333. ^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock
  334. !
  335. keys
  336. <
  337. if ('function'===typeof Object.keys) return Object.keys(self);
  338. var keys = [];
  339. for(var i in self) {
  340. if(self.hasOwnProperty(i)) {
  341. keys.push(i);
  342. }
  343. };
  344. return keys;
  345. >
  346. !
  347. size
  348. ^self keys size
  349. !
  350. values
  351. ^self keys collect: [:each | self at: each]
  352. ! !
  353. !HashedCollection methodsFor: 'adding/removing'!
  354. add: anAssociation
  355. self at: anAssociation key put: anAssociation value
  356. !
  357. addAll: aHashedCollection
  358. super addAll: aHashedCollection associations.
  359. ^aHashedCollection
  360. !
  361. remove: aKey ifAbsent: aBlock
  362. ^self removeKey: aKey ifAbsent: aBlock
  363. !
  364. removeKey: aKey
  365. ^self remove: aKey
  366. !
  367. removeKey: aKey ifAbsent: aBlock
  368. ^(self includesKey: aKey)
  369. ifFalse: [aBlock value]
  370. ifTrue: [self basicDelete: aKey]
  371. ! !
  372. !HashedCollection methodsFor: 'comparing'!
  373. = aHashedCollection
  374. self class = aHashedCollection class ifFalse: [^false].
  375. self size = aHashedCollection size ifFalse: [^false].
  376. ^self associations = aHashedCollection associations
  377. ! !
  378. !HashedCollection methodsFor: 'converting'!
  379. asDictionary
  380. ^Dictionary fromPairs: self associations
  381. !
  382. asJSON
  383. | c |
  384. c := self class new.
  385. self keysAndValuesDo: [:key :value |
  386. c at: key put: value asJSON].
  387. ^c
  388. ! !
  389. !HashedCollection methodsFor: 'copying'!
  390. , aCollection
  391. self shouldNotImplement
  392. !
  393. deepCopy
  394. | copy |
  395. copy := self class new.
  396. self keysAndValuesDo: [:key :value |
  397. copy at: key put: value deepCopy].
  398. ^copy
  399. !
  400. shallowCopy
  401. | copy |
  402. copy := self class new.
  403. self keysAndValuesDo: [:key :value |
  404. copy at: key put: value].
  405. ^copy
  406. ! !
  407. !HashedCollection methodsFor: 'enumerating'!
  408. associationsDo: aBlock
  409. self keysAndValuesDo: [:key :value |
  410. aBlock value: (Association key: key value: value)]
  411. !
  412. collect: aBlock
  413. | newDict |
  414. newDict := self class new.
  415. self keysAndValuesDo: [:key :value |
  416. newDict at: key put: (aBlock value: value)].
  417. ^newDict
  418. !
  419. detect: aBlock ifNone: anotherBlock
  420. ^self values detect: aBlock ifNone: anotherBlock
  421. !
  422. do: aBlock
  423. self valuesDo: aBlock
  424. !
  425. includes: anObject
  426. ^self values includes: anObject
  427. !
  428. keysAndValuesDo: aBlock
  429. self keysDo: [:each |
  430. aBlock value: each value: (self at: each)]
  431. !
  432. keysDo: aBlock
  433. self keys do: aBlock
  434. !
  435. select: aBlock
  436. | newDict |
  437. newDict := self class new.
  438. self keysAndValuesDo: [:key :value |
  439. (aBlock value: value) ifTrue: [newDict at: key put: value]].
  440. ^newDict
  441. !
  442. valuesDo: aBlock
  443. self keysAndValuesDo: [ :key :value | aBlock value: value ]
  444. !
  445. withIndexDo: aBlock
  446. self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]
  447. ! !
  448. !HashedCollection methodsFor: 'printing'!
  449. printString
  450. "print the contents of the HashedCollection into a string and return the string"
  451. ^String streamContents: [:aStream |
  452. aStream nextPutAll: 'a ', self class name, '('.
  453. self associations
  454. do: [:each | each storeOn: aStream]
  455. separatedBy: [ aStream nextPutAll: ' , '].
  456. aStream nextPutAll: ')']
  457. !
  458. storeOn: aStream
  459. aStream nextPutAll: '#{'.
  460. self associations
  461. do: [:each | each storeOn: aStream]
  462. separatedBy: [ aStream nextPutAll: '. '].
  463. aStream nextPutAll: '}'
  464. ! !
  465. !HashedCollection methodsFor: 'testing'!
  466. includesKey: aKey
  467. <return self.hasOwnProperty(aKey)>
  468. ! !
  469. !HashedCollection class methodsFor: 'instance creation'!
  470. fromPairs: aCollection
  471. | dict |
  472. dict := self new.
  473. aCollection do: [:each | dict add: each].
  474. ^dict
  475. ! !
  476. HashedCollection subclass: #Dictionary
  477. instanceVariableNames: 'keys values'
  478. package: 'Kernel-Collections'!
  479. !Dictionary commentStamp!
  480. I represent a set of elements that can be viewed from one of two perspectives: a set of associations,
  481. or a container of values that are externally named where the name can be any object that responds to `=`.
  482. The external name is referred to as the key.!
  483. !Dictionary methodsFor: 'accessing'!
  484. at: aKey ifAbsent: aBlock
  485. <
  486. var index = self._positionOfKey_(aKey);
  487. return index >>=0 ? self['@values'][index] : aBlock();
  488. >
  489. !
  490. at: aKey put: aValue
  491. <
  492. var index = self._positionOfKey_(aKey);
  493. if(index === -1) {
  494. var keys = self['@keys'];
  495. index = keys.length;
  496. keys.push(aKey);
  497. }
  498. return self['@values'][index] = aValue;
  499. >
  500. !
  501. indexOf: anObject ifAbsent: aBlock
  502. | index |
  503. index := values indexOf: anObject ifAbsent: [0].
  504. ^ index = 0 ifTrue: [ aBlock value ] ifFalse: [ keys at: index ]
  505. !
  506. keys
  507. ^keys copy
  508. !
  509. values
  510. ^values copy
  511. ! !
  512. !Dictionary methodsFor: 'adding/removing'!
  513. removeKey: aKey ifAbsent: aBlock
  514. <
  515. var index = self._positionOfKey_(aKey);
  516. if(index === -1) {
  517. return aBlock()
  518. } else {
  519. var keys = self['@keys'], values = self['@values'];
  520. var value = values[index], l = keys.length;
  521. keys[index] = keys[l-1];
  522. keys.pop();
  523. values[index] = values[l-1];
  524. values.pop();
  525. return value;
  526. }
  527. >
  528. ! !
  529. !Dictionary methodsFor: 'converting'!
  530. asHashedCollection
  531. ^HashedCollection fromPairs: self associations
  532. !
  533. asJSON
  534. ^self asHashedCollection asJSON
  535. ! !
  536. !Dictionary methodsFor: 'enumerating'!
  537. keysAndValuesDo: aBlock
  538. ^keys with: values do: aBlock
  539. !
  540. keysDo: aBlock
  541. ^keys do: aBlock
  542. !
  543. valuesDo: aBlock
  544. ^values do: aBlock
  545. ! !
  546. !Dictionary methodsFor: 'initialization'!
  547. initialize
  548. super initialize.
  549. keys := #().
  550. values := #()
  551. ! !
  552. !Dictionary methodsFor: 'private'!
  553. positionOfKey: anObject
  554. <
  555. var keys = self['@keys'];
  556. for(var i=0;i<keys.length;i++){
  557. if(keys[i].__eq(anObject)) { return i;}
  558. }
  559. return -1;
  560. >
  561. ! !
  562. !Dictionary methodsFor: 'testing'!
  563. includesKey: aKey
  564. < return self._positionOfKey_(aKey) >>= 0; >
  565. ! !
  566. IndexableCollection subclass: #SequenceableCollection
  567. instanceVariableNames: ''
  568. package: 'Kernel-Collections'!
  569. !SequenceableCollection commentStamp!
  570. I am an IndexableCollection
  571. with numeric indexes starting with 1.!
  572. !SequenceableCollection methodsFor: 'accessing'!
  573. allButFirst
  574. ^self copyFrom: 2 to: self size
  575. !
  576. allButLast
  577. ^self copyFrom: 1 to: self size - 1
  578. !
  579. atRandom
  580. ^ self at: self size atRandom
  581. !
  582. first
  583. ^self at: 1
  584. !
  585. first: n
  586. "Answer the first n elements of the receiver.
  587. Raise an error if there are not enough elements."
  588. ^ self copyFrom: 1 to: n
  589. !
  590. fourth
  591. ^self at: 4
  592. !
  593. indexOf: anObject ifAbsent: aBlock
  594. <
  595. for(var i=0;i<self.length;i++) {
  596. if(self[i].__eq(anObject)) {return i+1}
  597. };
  598. return aBlock();
  599. >
  600. !
  601. indexOf: anObject startingAt: start
  602. "Answer the index of the first occurence of anElement after start
  603. within the receiver. If the receiver does not contain anElement,
  604. answer 0."
  605. ^self indexOf: anObject startingAt: start ifAbsent: [0]
  606. !
  607. indexOf: anObject startingAt: start ifAbsent: aBlock
  608. <
  609. for(var i=start-1;i<self.length;i++){
  610. if(self[i].__eq(anObject)) {return i+1}
  611. }
  612. return aBlock();
  613. >
  614. !
  615. last
  616. ^self at: self size
  617. !
  618. second
  619. ^self at: 2
  620. !
  621. third
  622. ^self at: 3
  623. ! !
  624. !SequenceableCollection methodsFor: 'adding'!
  625. addLast: anObject
  626. self add: anObject
  627. !
  628. removeLast
  629. self remove: self last
  630. ! !
  631. !SequenceableCollection methodsFor: 'comparing'!
  632. = aCollection
  633. (self class = aCollection class and: [
  634. self size = aCollection size]) ifFalse: [^false].
  635. self withIndexDo: [:each :i |
  636. (aCollection at: i) = each ifFalse: [^false]].
  637. ^true
  638. ! !
  639. !SequenceableCollection methodsFor: 'converting'!
  640. reversed
  641. self subclassResponsibility
  642. ! !
  643. !SequenceableCollection methodsFor: 'copying'!
  644. copyFrom: anIndex to: anotherIndex
  645. | range newCollection |
  646. range := anIndex to: anotherIndex.
  647. newCollection := self class new: range size.
  648. range withIndexDo: [:each :i |
  649. newCollection at: i put: (self at: each)].
  650. ^newCollection
  651. !
  652. deepCopy
  653. | newCollection |
  654. newCollection := self class new: self size.
  655. self withIndexDo: [:each :index |
  656. newCollection at: index put: each deepCopy].
  657. ^newCollection
  658. !
  659. shallowCopy
  660. | newCollection |
  661. newCollection := self class new: self size.
  662. self withIndexDo: [ :each :index |
  663. newCollection at: index put: each].
  664. ^newCollection
  665. ! !
  666. !SequenceableCollection methodsFor: 'enumerating'!
  667. detect: aBlock ifNone: anotherBlock
  668. <
  669. for(var i = 0; i < self.length; i++)
  670. if(aBlock(self[i]))
  671. return self[i];
  672. return anotherBlock();
  673. >
  674. !
  675. do: aBlock
  676. <for(var i=0;i<self.length;i++){aBlock(self[i]);}>
  677. !
  678. with: anotherCollection do: aBlock
  679. <for(var i=0;i<self.length;i++){aBlock(self[i], anotherCollection[i]);}>
  680. !
  681. withIndexDo: aBlock
  682. <for(var i=0;i<self.length;i++){aBlock(self[i], i+1);}>
  683. ! !
  684. !SequenceableCollection methodsFor: 'testing'!
  685. includes: anObject
  686. ^(self indexOf: anObject ifAbsent: [nil]) notNil
  687. ! !
  688. SequenceableCollection subclass: #Array
  689. instanceVariableNames: ''
  690. package: 'Kernel-Collections'!
  691. !Array commentStamp!
  692. I represent a collection of objects ordered by the collector. The size of arrays is dynamic.
  693. In Amber, OrderedCollection is an alias for Array.!
  694. !Array methodsFor: 'accessing'!
  695. at: anIndex ifAbsent: aBlock
  696. <
  697. if((anIndex < 1) || (self.length < anIndex)) {return aBlock()};
  698. return self[anIndex - 1];
  699. >
  700. !
  701. at: anIndex put: anObject
  702. <return self[anIndex - 1] = anObject>
  703. !
  704. size
  705. <return self.length>
  706. ! !
  707. !Array methodsFor: 'adding/removing'!
  708. add: anObject
  709. <self.push(anObject); return anObject;>
  710. !
  711. remove: anObject ifAbsent: aBlock
  712. <
  713. for(var i=0;i<self.length;i++) {
  714. if(self[i] == anObject) {
  715. self.splice(i,1);
  716. return self;
  717. }
  718. };
  719. aBlock._value();
  720. >
  721. !
  722. removeFrom: aNumber to: anotherNumber
  723. <self.splice(aNumber - 1,anotherNumber - 1)>
  724. ! !
  725. !Array methodsFor: 'converting'!
  726. asJavascript
  727. ^'[', ((self collect: [:each | each asJavascript]) join: ', '), ']'
  728. !
  729. reversed
  730. <return self._copy().reverse()>
  731. ! !
  732. !Array methodsFor: 'enumerating'!
  733. join: aString
  734. <return self.join(aString)>
  735. !
  736. sort
  737. ^self basicPerform: 'sort'
  738. !
  739. sort: aBlock
  740. <
  741. return self.sort(function(a, b) {
  742. if(aBlock(a,b)) {return -1} else {return 1}
  743. })
  744. >
  745. !
  746. sorted
  747. ^self copy sort
  748. !
  749. sorted: aBlock
  750. ^self copy sort: aBlock
  751. ! !
  752. !Array class methodsFor: 'instance creation'!
  753. new: anInteger
  754. <return new Array(anInteger)>
  755. !
  756. with: anObject
  757. ^(self new: 1)
  758. at: 1 put: anObject;
  759. yourself
  760. !
  761. with: anObject with: anObject2
  762. ^(self new: 2)
  763. at: 1 put: anObject;
  764. at: 2 put: anObject2;
  765. yourself
  766. !
  767. with: anObject with: anObject2 with: anObject3
  768. ^(self new: 3)
  769. at: 1 put: anObject;
  770. at: 2 put: anObject2;
  771. at: 3 put: anObject3;
  772. yourself
  773. !
  774. withAll: aCollection
  775. | instance index |
  776. index := 1.
  777. instance := self new: aCollection size.
  778. aCollection do: [:each |
  779. instance at: index put: each.
  780. index := index + 1].
  781. ^instance
  782. ! !
  783. SequenceableCollection subclass: #CharacterArray
  784. instanceVariableNames: ''
  785. package: 'Kernel-Collections'!
  786. !CharacterArray commentStamp!
  787. I am the abstract superclass of string-like collections.!
  788. !CharacterArray methodsFor: 'accessing'!
  789. at: anIndex put: anObject
  790. self errorReadOnly
  791. ! !
  792. !CharacterArray methodsFor: 'adding'!
  793. add: anObject
  794. self errorReadOnly
  795. !
  796. remove: anObject
  797. self errorReadOnly
  798. ! !
  799. !CharacterArray methodsFor: 'converting'!
  800. asLowercase
  801. ^self class fromString: self asString asLowercase
  802. !
  803. asNumber
  804. ^self asString asNumber
  805. !
  806. asString
  807. ^self subclassResponsibility
  808. !
  809. asSymbol
  810. ^self subclassResponsibility
  811. !
  812. asUppercase
  813. ^self class fromString: self asString asUppercase
  814. ! !
  815. !CharacterArray methodsFor: 'copying'!
  816. , aString
  817. ^self asString, aString asString
  818. ! !
  819. !CharacterArray methodsFor: 'error handling'!
  820. errorReadOnly
  821. self error: 'Object is read-only'
  822. ! !
  823. !CharacterArray methodsFor: 'printing'!
  824. printString
  825. ^self asString printString
  826. ! !
  827. !CharacterArray class methodsFor: 'instance creation'!
  828. fromString: aString
  829. self subclassResponsibility
  830. ! !
  831. CharacterArray subclass: #String
  832. instanceVariableNames: ''
  833. package: 'Kernel-Collections'!
  834. !String commentStamp!
  835. I am an indexed collection of Characters. Unlike most Smalltalk dialects, Amber doesn't provide the Character class. Instead, elements of a String are single character strings.
  836. String inherits many useful methods from its hierarchy, such as
  837. `Collection >> #,`!
  838. !String methodsFor: 'accessing'!
  839. asciiValue
  840. <return self.charCodeAt(0);>
  841. !
  842. at: anIndex ifAbsent: aBlock
  843. <return String(self).charAt(anIndex - 1) || aBlock()>
  844. !
  845. escaped
  846. <return escape(self)>
  847. !
  848. size
  849. <return self.length>
  850. !
  851. unescaped
  852. <return unescape(self)>
  853. ! !
  854. !String methodsFor: 'comparing'!
  855. < aString
  856. <return String(self) < aString._asString()>
  857. !
  858. <= aString
  859. <return String(self) <= aString._asString()>
  860. !
  861. = aString
  862. <
  863. if(!! aString._isString || !! aString._isString()) {
  864. return false;
  865. }
  866. return String(self) === String(aString)
  867. >
  868. !
  869. == aString
  870. ^self = aString
  871. !
  872. > aString
  873. <return String(self) >> aString._asString()>
  874. !
  875. >= aString
  876. <return String(self) >>= aString._asString()>
  877. ! !
  878. !String methodsFor: 'converting'!
  879. asJSON
  880. ^self
  881. !
  882. asJavaScriptSelector
  883. ^(self asSelector replace: '^_' with: '') replace: '_.*' with: ''.
  884. !
  885. asJavascript
  886. <
  887. if(self.search(/^[a-zA-Z0-9_:.$ ]*$/) == -1)
  888. return "\"" + self.replace(/[\x00-\x1f"\\\x7f-\x9f]/g, function(ch){var c=ch.charCodeAt(0);return "\\x"+("0"+c.toString(16)).slice(-2)}) + "\"";
  889. else
  890. return "\"" + self + "\"";
  891. >
  892. !
  893. asLowercase
  894. <return self.toLowerCase()>
  895. !
  896. asNumber
  897. <return Number(self)>
  898. !
  899. asRegexp
  900. ^ RegularExpression fromString: self
  901. !
  902. asSelector
  903. <return smalltalk.selector(self)>
  904. !
  905. asString
  906. ^self
  907. !
  908. asSymbol
  909. ^Symbol lookup: self
  910. !
  911. asUppercase
  912. <return self.toUpperCase()>
  913. !
  914. reversed
  915. <return self.split("").reverse().join("")>
  916. !
  917. tokenize: aString
  918. <return self.split(aString)>
  919. ! !
  920. !String methodsFor: 'copying'!
  921. , aString
  922. <return self + aString>
  923. !
  924. copyFrom: anIndex to: anotherIndex
  925. <return self.substring(anIndex - 1, anotherIndex)>
  926. !
  927. deepCopy
  928. ^self shallowCopy
  929. !
  930. shallowCopy
  931. ^self class fromString: self
  932. ! !
  933. !String methodsFor: 'enumerating'!
  934. do: aBlock
  935. <for(var i=0;i<self.length;i++){aBlock(self.charAt(i));}>
  936. !
  937. withIndexDo: aBlock
  938. <for(var i=0;i<self.length;i++){aBlock(self.charAt(i), i+1);}>
  939. ! !
  940. !String methodsFor: 'printing'!
  941. printNl
  942. <console.log(self)>
  943. !
  944. printString
  945. ^'''', self, ''''
  946. ! !
  947. !String methodsFor: 'regular expressions'!
  948. match: aRegexp
  949. <return self.search(aRegexp) !!= -1>
  950. !
  951. matchesOf: aRegularExpression
  952. <return self.match(aRegularExpression)>
  953. !
  954. replace: aString with: anotherString
  955. ^self replaceRegexp: (RegularExpression fromString: aString flag: 'g') with: anotherString
  956. !
  957. replaceRegexp: aRegexp with: aString
  958. <return self.replace(aRegexp, aString)>
  959. !
  960. trimBoth
  961. ^self trimBoth: '\s'
  962. !
  963. trimBoth: separators
  964. ^(self trimLeft: separators) trimRight: separators
  965. !
  966. trimLeft
  967. ^self trimLeft: '\s'
  968. !
  969. trimLeft: separators
  970. ^self replaceRegexp: (RegularExpression fromString: '^[', separators, ']+' flag: 'g') with: ''
  971. !
  972. trimRight
  973. ^self trimRight: '\s'
  974. !
  975. trimRight: separators
  976. ^self replaceRegexp: (RegularExpression fromString: '[', separators, ']+$' flag: 'g') with: ''
  977. ! !
  978. !String methodsFor: 'split join'!
  979. join: aCollection
  980. ^ String
  981. streamContents: [:stream | aCollection
  982. do: [:each | stream nextPutAll: each asString]
  983. separatedBy: [stream nextPutAll: self]]
  984. !
  985. lineIndicesDo: aBlock
  986. "execute aBlock with 3 arguments for each line:
  987. - start index of line
  988. - end index of line without line delimiter
  989. - end index of line including line delimiter(s) CR, LF or CRLF"
  990. | cr lf start sz nextLF nextCR |
  991. start := 1.
  992. sz := self size.
  993. cr := String cr.
  994. nextCR := self indexOf: cr startingAt: 1.
  995. lf := String lf.
  996. nextLF := self indexOf: lf startingAt: 1.
  997. [ start <= sz ] whileTrue: [
  998. (nextLF = 0 and: [ nextCR = 0 ])
  999. ifTrue: [ "No more CR, nor LF, the string is over"
  1000. aBlock value: start value: sz value: sz.
  1001. ^self ].
  1002. (nextCR = 0 or: [ 0 < nextLF and: [ nextLF < nextCR ] ])
  1003. ifTrue: [ "Found a LF"
  1004. aBlock value: start value: nextLF - 1 value: nextLF.
  1005. start := 1 + nextLF.
  1006. nextLF := self indexOf: lf startingAt: start ]
  1007. ifFalse: [ 1 + nextCR = nextLF
  1008. ifTrue: [ "Found a CR-LF pair"
  1009. aBlock value: start value: nextCR - 1 value: nextLF.
  1010. start := 1 + nextLF.
  1011. nextCR := self indexOf: cr startingAt: start.
  1012. nextLF := self indexOf: lf startingAt: start ]
  1013. ifFalse: [ "Found a CR"
  1014. aBlock value: start value: nextCR - 1 value: nextCR.
  1015. start := 1 + nextCR.
  1016. nextCR := self indexOf: cr startingAt: start ]]]
  1017. !
  1018. lineNumber: anIndex
  1019. "Answer a string containing the characters in the given line number."
  1020. | lineCount |
  1021. lineCount := 0.
  1022. self lineIndicesDo: [:start :endWithoutDelimiters :end |
  1023. (lineCount := lineCount + 1) = anIndex ifTrue: [^self copyFrom: start to: endWithoutDelimiters]].
  1024. ^nil
  1025. !
  1026. lines
  1027. "Answer an array of lines composing this receiver without the line ending delimiters."
  1028. | lines |
  1029. lines := Array new.
  1030. self linesDo: [:aLine | lines add: aLine].
  1031. ^lines
  1032. !
  1033. linesDo: aBlock
  1034. "Execute aBlock with each line in this string. The terminating line
  1035. delimiters CR, LF or CRLF pairs are not included in what is passed to aBlock"
  1036. self lineIndicesDo: [:start :endWithoutDelimiters :end |
  1037. aBlock value: (self copyFrom: start to: endWithoutDelimiters)]
  1038. ! !
  1039. !String methodsFor: 'testing'!
  1040. includesSubString: subString
  1041. < return self.indexOf(subString) !!= -1 >
  1042. !
  1043. isString
  1044. ^true
  1045. ! !
  1046. !String class methodsFor: 'accessing'!
  1047. cr
  1048. <return '\r'>
  1049. !
  1050. crlf
  1051. <return '\r\n'>
  1052. !
  1053. lf
  1054. <return '\n'>
  1055. !
  1056. space
  1057. <return ' '>
  1058. !
  1059. streamClass
  1060. ^StringStream
  1061. !
  1062. tab
  1063. <return '\t'>
  1064. ! !
  1065. !String class methodsFor: 'instance creation'!
  1066. fromCharCode: anInteger
  1067. <return String.fromCharCode(anInteger)>
  1068. !
  1069. fromString: aString
  1070. <return new self.fn(aString)>
  1071. !
  1072. streamContents: blockWithArg
  1073. |stream|
  1074. stream := (self streamClass on: String new).
  1075. blockWithArg value: stream.
  1076. ^ stream contents
  1077. !
  1078. value: aUTFCharCode
  1079. <return String.fromCharCode(aUTFCharCode);>
  1080. ! !
  1081. CharacterArray subclass: #Symbol
  1082. instanceVariableNames: ''
  1083. package: 'Kernel-Collections'!
  1084. !Symbol commentStamp!
  1085. I represent Strings that are created uniquely.
  1086. Symbols are unique through the system.
  1087. Thus, someString asSymbol == someString asSymbol.!
  1088. !Symbol methodsFor: 'accessing'!
  1089. at: anIndex ifAbsent: aBlock
  1090. ^self asString at: anIndex ifAbsent: aBlock
  1091. !
  1092. size
  1093. ^self asString size
  1094. ! !
  1095. !Symbol methodsFor: 'comparing'!
  1096. < aSymbol
  1097. ^self asString < aSymbol asString
  1098. !
  1099. <= aSymbol
  1100. ^self asString <= aSymbol asString
  1101. !
  1102. = aSymbol
  1103. aSymbol class = self class ifFalse: [^false].
  1104. ^self asString = aSymbol asString
  1105. !
  1106. > aSymbol
  1107. ^self asString > aSymbol asString
  1108. !
  1109. >= aSymbol
  1110. ^self asString >= aSymbol asString
  1111. ! !
  1112. !Symbol methodsFor: 'converting'!
  1113. asJSON
  1114. ^self asString asJSON
  1115. !
  1116. asJavascript
  1117. ^'smalltalk.symbolFor(', self asString asJavascript, ')'
  1118. !
  1119. asSelector
  1120. ^self asString asSelector
  1121. !
  1122. asString
  1123. <return self.value>
  1124. !
  1125. asSuperSelector
  1126. ^self asString asSuperSelector
  1127. !
  1128. asSymbol
  1129. ^self
  1130. ! !
  1131. !Symbol methodsFor: 'copying'!
  1132. copyFrom: anIndex to: anotherIndex
  1133. ^self class fromString: (self asString copyFrom: anIndex to: anotherIndex)
  1134. !
  1135. deepCopy
  1136. ^self
  1137. !
  1138. shallowCopy
  1139. ^self
  1140. ! !
  1141. !Symbol methodsFor: 'enumerating'!
  1142. collect: aBlock
  1143. ^ (self asString collect: aBlock) asSymbol
  1144. !
  1145. detect: aBlock
  1146. ^ self asString detect: aBlock
  1147. !
  1148. do: aBlock
  1149. self asString do: aBlock
  1150. !
  1151. select: aBlock
  1152. ^ (self asString select: aBlock) asSymbol
  1153. !
  1154. withIndexDo: aBlock
  1155. self asString withIndexDo: aBlock
  1156. ! !
  1157. !Symbol methodsFor: 'evaluating'!
  1158. value: anObject
  1159. ^anObject perform: self
  1160. ! !
  1161. !Symbol methodsFor: 'printing'!
  1162. isSymbol
  1163. ^true
  1164. !
  1165. printString
  1166. ^'#', self asString
  1167. ! !
  1168. !Symbol class methodsFor: 'instance creation'!
  1169. basicNew
  1170. self shouldNotImplement
  1171. !
  1172. fromString: aString
  1173. ^self lookup: aString
  1174. !
  1175. lookup: aString
  1176. <return smalltalk.symbolFor(aString);>
  1177. ! !
  1178. Collection subclass: #Set
  1179. instanceVariableNames: 'elements'
  1180. package: 'Kernel-Collections'!
  1181. !Set commentStamp!
  1182. I represent an unordered set of objects without duplicates.!
  1183. !Set methodsFor: 'accessing'!
  1184. size
  1185. ^elements size
  1186. ! !
  1187. !Set methodsFor: 'adding/removing'!
  1188. add: anObject
  1189. <
  1190. var found;
  1191. for(var i=0; i < self['@elements'].length; i++) {
  1192. if(anObject == self['@elements'][i]) {
  1193. found = true;
  1194. break;
  1195. }
  1196. }
  1197. if(!!found) {self['@elements'].push(anObject)}
  1198. >
  1199. !
  1200. remove: anObject
  1201. elements remove: anObject
  1202. ! !
  1203. !Set methodsFor: 'comparing'!
  1204. = aCollection
  1205. self class = aCollection class ifFalse: [ ^ false ].
  1206. self size = aCollection size ifFalse: [ ^ false ].
  1207. self do: [:each | (aCollection includes: each) ifFalse: [ ^ false ] ].
  1208. ^ true
  1209. ! !
  1210. !Set methodsFor: 'converting'!
  1211. asArray
  1212. ^elements copy
  1213. ! !
  1214. !Set methodsFor: 'enumerating'!
  1215. collect: aBlock
  1216. ^self class withAll: (elements collect: aBlock)
  1217. !
  1218. detect: aBlock ifNone: anotherBlock
  1219. ^elements detect: aBlock ifNone: anotherBlock
  1220. !
  1221. do: aBlock
  1222. elements do: aBlock
  1223. !
  1224. select: aBlock
  1225. | collection |
  1226. collection := self class new.
  1227. self do: [:each |
  1228. (aBlock value: each) ifTrue: [
  1229. collection add: each]].
  1230. ^collection
  1231. ! !
  1232. !Set methodsFor: 'initialization'!
  1233. initialize
  1234. super initialize.
  1235. elements := #()
  1236. ! !
  1237. !Set methodsFor: 'testing'!
  1238. includes: anObject
  1239. ^elements includes: anObject
  1240. ! !
  1241. Object subclass: #Queue
  1242. instanceVariableNames: 'read readIndex write'
  1243. package: 'Kernel-Collections'!
  1244. !Queue commentStamp!
  1245. A Queue am a one-sided queue.
  1246. A Queue uses two OrderedCollections inside,
  1247. `read` is at the front, is not modified and only read using `readIndex`.
  1248. `write` is at the back and is appended new items.
  1249. When `read` is exhausted, `write` is promoted to `read` and new `write` is created.
  1250. As a consequence, no data moving is done by the Queue; write appending may do data moving
  1251. when growing `write`, but this is left to engine to implement as good as it chooses to.!
  1252. !Queue methodsFor: 'accessing'!
  1253. back: anObject
  1254. write add: anObject
  1255. !
  1256. front
  1257. ^self frontIfAbsent: [ self error: 'Cannot read from empty Queue.' ]
  1258. !
  1259. frontIfAbsent: aBlock
  1260. | result |
  1261. result := read at: readIndex ifAbsent: [
  1262. write isEmpty ifTrue: [
  1263. readIndex > 1 ifTrue: [ read := #(). readIndex := 1 ].
  1264. ^aBlock value ].
  1265. read := write.
  1266. readIndex := 1.
  1267. write := OrderedCollection new.
  1268. read first ].
  1269. read at: readIndex put: nil.
  1270. readIndex := readIndex + 1.
  1271. ^result
  1272. ! !
  1273. !Queue methodsFor: 'initialization'!
  1274. initialize
  1275. super initialize.
  1276. read := OrderedCollection new.
  1277. write := OrderedCollection new.
  1278. readIndex := 1
  1279. ! !
  1280. Object subclass: #RegularExpression
  1281. instanceVariableNames: ''
  1282. package: 'Kernel-Collections'!
  1283. !RegularExpression commentStamp!
  1284. I represent a regular expression object. My instances are JavaScript `RegExp` object.!
  1285. !RegularExpression methodsFor: 'evaluating'!
  1286. compile: aString
  1287. <return self.compile(aString)>
  1288. !
  1289. exec: aString
  1290. <return self.exec(aString) || nil>
  1291. !
  1292. test: aString
  1293. <return self.test(aString)>
  1294. ! !
  1295. !RegularExpression class methodsFor: 'instance creation'!
  1296. fromString: aString
  1297. ^self fromString: aString flag: ''
  1298. !
  1299. fromString: aString flag: anotherString
  1300. <return new RegExp(aString, anotherString)>
  1301. ! !
  1302. Object subclass: #Stream
  1303. instanceVariableNames: 'collection position streamSize'
  1304. package: 'Kernel-Collections'!
  1305. !Stream commentStamp!
  1306. I represent an accessor for a sequence of objects. This sequence is referred to as my "contents".
  1307. My instances are read/write streams to the contents sequence collection.!
  1308. !Stream methodsFor: 'accessing'!
  1309. collection
  1310. ^collection
  1311. !
  1312. contents
  1313. ^self collection
  1314. copyFrom: 1
  1315. to: self streamSize
  1316. !
  1317. position
  1318. ^position ifNil: [position := 0]
  1319. !
  1320. position: anInteger
  1321. position := anInteger
  1322. !
  1323. setCollection: aCollection
  1324. collection := aCollection
  1325. !
  1326. setStreamSize: anInteger
  1327. streamSize := anInteger
  1328. !
  1329. size
  1330. ^self streamSize
  1331. !
  1332. streamSize
  1333. ^streamSize
  1334. ! !
  1335. !Stream methodsFor: 'actions'!
  1336. close
  1337. !
  1338. flush
  1339. !
  1340. reset
  1341. self position: 0
  1342. !
  1343. resetContents
  1344. self reset.
  1345. self setStreamSize: 0
  1346. ! !
  1347. !Stream methodsFor: 'enumerating'!
  1348. do: aBlock
  1349. [self atEnd] whileFalse: [aBlock value: self next]
  1350. ! !
  1351. !Stream methodsFor: 'positioning'!
  1352. setToEnd
  1353. self position: self size
  1354. !
  1355. skip: anInteger
  1356. self position: ((self position + anInteger) min: self size max: 0)
  1357. ! !
  1358. !Stream methodsFor: 'reading'!
  1359. next
  1360. ^self atEnd
  1361. ifTrue: [nil]
  1362. ifFalse: [
  1363. self position: self position + 1.
  1364. collection at: self position]
  1365. !
  1366. next: anInteger
  1367. | tempCollection |
  1368. tempCollection := self collection class new.
  1369. anInteger timesRepeat: [
  1370. self atEnd ifFalse: [
  1371. tempCollection add: self next]].
  1372. ^tempCollection
  1373. !
  1374. peek
  1375. ^self atEnd ifFalse: [
  1376. self collection at: self position + 1]
  1377. ! !
  1378. !Stream methodsFor: 'testing'!
  1379. atEnd
  1380. ^self position = self size
  1381. !
  1382. atStart
  1383. ^self position = 0
  1384. !
  1385. isEmpty
  1386. ^self size = 0
  1387. ! !
  1388. !Stream methodsFor: 'writing'!
  1389. nextPut: anObject
  1390. self position: self position + 1.
  1391. self collection at: self position put: anObject.
  1392. self setStreamSize: (self streamSize max: self position)
  1393. !
  1394. nextPutAll: aCollection
  1395. aCollection do: [:each |
  1396. self nextPut: each]
  1397. ! !
  1398. !Stream class methodsFor: 'instance creation'!
  1399. on: aCollection
  1400. ^self new
  1401. setCollection: aCollection;
  1402. setStreamSize: aCollection size;
  1403. yourself
  1404. ! !
  1405. Stream subclass: #StringStream
  1406. instanceVariableNames: ''
  1407. package: 'Kernel-Collections'!
  1408. !StringStream commentStamp!
  1409. I am a Stream specific to `String` objects.!
  1410. !StringStream methodsFor: 'reading'!
  1411. next: anInteger
  1412. | tempCollection |
  1413. tempCollection := self collection class new.
  1414. anInteger timesRepeat: [
  1415. self atEnd ifFalse: [
  1416. tempCollection := tempCollection, self next]].
  1417. ^tempCollection
  1418. ! !
  1419. !StringStream methodsFor: 'writing'!
  1420. cr
  1421. ^self nextPutAll: String cr
  1422. !
  1423. crlf
  1424. ^self nextPutAll: String crlf
  1425. !
  1426. lf
  1427. ^self nextPutAll: String lf
  1428. !
  1429. nextPut: aString
  1430. self nextPutAll: aString
  1431. !
  1432. nextPutAll: aString
  1433. self setCollection:
  1434. (self collection copyFrom: 1 to: self position),
  1435. aString,
  1436. (self collection copyFrom: (self position + 1 + aString size) to: self collection size).
  1437. self position: self position + aString size.
  1438. self setStreamSize: (self streamSize max: self position)
  1439. !
  1440. space
  1441. self nextPut: ' '
  1442. ! !