Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.61 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include "textbuffer.h"
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6.  
  7. typedef struct textbufferNode {
  8. char *data;
  9. struct textbufferNode *next;
  10. struct textbufferNode *prev;
  11. } TBNode;
  12.  
  13. struct textbuffer {
  14. int textbufferLength; //Number of lines in the textbuffer
  15. TBNode *first; //a pointer to the first node
  16. TBNode *last; //a pointer to the last node
  17. };
  18.  
  19.  
  20. static TBNode *newTBNode(char *text);
  21. static void freeTBNode(TBNode *node);
  22. static char* mystrsep(char **input, const char *delim);
  23. static char * mystrdup (const char *s);
  24. int numDigits (int n);
  25. static int sizeInBytes(TB tb);
  26. //static void printTB(TB tb);
  27. static Match createMatchNode(int line, int columnNumber);
  28.  
  29. /* Allocate a new textbuffer whose contents is initialised with the text given
  30. * in the array.
  31. */
  32. static char * mystrdup (const char *s) {
  33. size_t len = strlen (s) + 1;
  34. void *new = malloc (len);
  35. if (new == NULL){
  36. return NULL;
  37. }
  38. return (char *) memcpy (new, s, len);
  39. }
  40. /*static void printTB(TB tb){
  41. TBNode *transverse = tb->first;
  42. while(transverse != NULL){
  43. fprintf(stderr,"%s\n", transverse->data);
  44. transverse = transverse->next;
  45. }
  46. }
  47. */
  48.  
  49. static Match createMatchNode(int line, int columnNumber){
  50. Match new = malloc(sizeof(*new));
  51. if(new == NULL){
  52. fprintf(stderr,"couldn't allocate memory for match node\n");
  53. abort();
  54. }
  55. (*new) = (struct _matchNode){
  56. .lineNumber = line, .columnNumber = columnNumber, .next = NULL
  57. };
  58. return new;
  59. }
  60. static TBNode *newTBNode (char *text)
  61. {
  62. //Allocate memory to the node.
  63. TBNode *new = malloc (sizeof(*new));
  64. if (new == NULL){
  65. printf("couldn't allocate newTB node");
  66. abort();
  67. }
  68. (*new) = (struct textbufferNode){
  69. .data = mystrdup(text), .next = NULL, .prev = NULL
  70. };
  71. return new;
  72. }
  73.  
  74. static int sizeInBytes(TB tb) {
  75. size_t size = 0;
  76. TBNode *search = tb->first;
  77. while(search != NULL){
  78. size += strlen(search->data) +1;
  79. search = search->next;
  80. }
  81. return size;
  82. }
  83.  
  84. static char * mystrsep(char **input, const char *delim){
  85. char *begin, *end;
  86. begin = *input;
  87. if (begin == NULL || strcmp(*input, "") == 0){
  88. return NULL;
  89. }
  90. //Find the end of the token
  91. //get the string until character delim
  92. end = begin + strcspn (begin, delim);
  93.  
  94. if (*end) {
  95. //Terminate the token and set *input past NULL character
  96. *end++ = '\0';
  97. *input = end;
  98. }
  99. else {
  100. //No more delimiters; this is the last token.
  101. *input = NULL;
  102. }
  103. //printf("returned is %s\n", begin);
  104. return begin;
  105. }
  106.  
  107.  
  108. int numDigits (int n){
  109. int count = 0;
  110. while(n != 0) {
  111. // n = n/10
  112. n /= 10;
  113. ++count;
  114. }
  115. return count;
  116. }
  117.  
  118. TB newTB (char text[]) {
  119. //Allocate memory for a new textbuffer
  120. TB newTB = malloc(sizeof(struct textbuffer));
  121. if (newTB == NULL){
  122. printf("unable to allocate memory to new textbuffer\n");
  123. exit(1);
  124. }
  125. //Set the fields to null:
  126. (*newTB) = (struct textbuffer){
  127. .first = NULL, .last = NULL, .textbufferLength = 0
  128. };
  129.  
  130. //break the string up and for every line of text allocate a node
  131. char *line;
  132.  
  133. char *newText = mystrdup(text);
  134. char **splitString = &newText;
  135. while((line = mystrsep(splitString,"\n"))!= NULL){
  136. //create a new node.
  137. TBNode *newNode = newTBNode (line);
  138. //if we're the first node in the list
  139. if(newTB->first == NULL){
  140. newTB->first = newNode;
  141. newTB->last = newNode;
  142. //otherwise append to the end
  143. } else {
  144. newTB->last->next = newNode;
  145. newNode->prev = newTB->last;
  146. newTB->last = newNode;
  147. }
  148. newTB->textbufferLength++;
  149. }
  150. return newTB;
  151. }
  152.  
  153. //A function to free a node
  154. static void freeTBNode (TBNode *node)
  155. {
  156. //printf("here with data %s\n", node->data);
  157. if (node == NULL) {
  158. return;
  159. }
  160. free(node->data);
  161. //printf("my node is at location %p\n", node);
  162. free(node);
  163. }
  164.  
  165. /* Free the memory occupied by the given textbuffer. It is an error to access
  166. * the buffer afterwards.
  167. */
  168. void releaseTB (TB tb) {
  169. if (tb == NULL){
  170. printf("invalid text buffer!\n");
  171. abort();
  172. }
  173. if(tb->textbufferLength == 0){
  174. //free just the memory of the tb
  175. free(tb);
  176. return;
  177. }
  178. TBNode *current = tb->first;
  179. while(current != NULL){
  180. //printf("i am freeing %s, with current->next->data: %s\n", current->data, current->next->data);
  181. TBNode *temp = current->next;
  182. //printf("temp is at %p with data %s\n", temp, temp->data);
  183. //printf("current is at %p with data %s\n", current, current->data);
  184. freeTBNode(current);
  185. //somehow my data is getting corrupted.
  186. current = temp;
  187. }
  188. free(tb);
  189. }
  190.  
  191. /* Allocate and return an array containing the text in the given textbuffer.
  192. * add a prefix corrosponding to line number iff showLineNumbers == TRUE
  193. */
  194. char *dumpTB (TB tb, bool showLineNumbers){
  195. size_t size = sizeInBytes(tb);
  196. if(size == 0){
  197. char *string = malloc(1);
  198. *string = '\0';
  199. return string;
  200. }
  201. if(showLineNumbers){
  202. int count = 1;
  203. //add to the size of the string
  204. TBNode *current = tb->first;
  205. while(current != NULL){
  206. size += 2 + numDigits(count);
  207. current = current->next;
  208. count++;
  209. }
  210. //printf("size is %zu\n", size);
  211. char *totalText = malloc(size +1);
  212. if(totalText == NULL){
  213. printf("malloc failed\n");
  214. abort();
  215. }
  216. char *addingPoint = totalText;
  217. TBNode *search = tb->first;
  218. int lineNumber = 1;
  219. while(search != NULL){
  220. sprintf(addingPoint, "%d. %s\n", lineNumber, search->data);
  221. addingPoint += strlen(search->data) + numDigits(lineNumber) + 3;
  222. search = search->next;
  223. lineNumber++;
  224. }
  225. //printf("text is : %s", totalText);
  226. return totalText;
  227. } else {
  228. char *totalText = malloc(size +1);
  229. if(totalText == NULL){
  230. printf("malloc failed\n");
  231. abort();
  232. }
  233.  
  234. TBNode *current = tb->first;
  235. char *addingPoint = totalText;
  236. while(current != NULL){
  237. sprintf(addingPoint, "%s\n",current->data);
  238. addingPoint += strlen(current->data) +1;
  239. current = current->next;
  240. }
  241. //printf("text is : %s", totalText);
  242. return totalText;
  243. }
  244. }
  245.  
  246. /* Return the number of lines of the given textbuffer.
  247. */
  248. int linesTB (TB tb){
  249. return(tb->textbufferLength);
  250. }
  251.  
  252. /* Add a given prefix to all lines between pos1 and pos2
  253. *
  254. * - The program is to abort() with an error message if line 'pos1' or line
  255. * 'pos2' is out of range. The first line of a textbuffer is at position 0.
  256. */
  257. //You need to realloc
  258. void addPrefixTB (TB tb, int pos1, int pos2, char* prefix){
  259. if(prefix == NULL || strcmp(prefix, "") == 0){
  260. return;
  261. }
  262. if(pos1 > pos2){
  263. fprintf(stderr,"Invalid input\n");
  264. abort();
  265. }
  266. //printf("textbufferLength is %d\n", tb->textbufferLength);
  267. if(pos2 > tb->textbufferLength|| pos1 < 1){
  268. fprintf(stderr, "invalid input\n");
  269. abort();
  270. }
  271. TBNode *searchNode = tb->first;
  272. //This will count our index along the linked list.
  273. int count = 1;
  274. //find pos1's node
  275. while(count < pos1){
  276. searchNode = searchNode->next;
  277. count++;
  278. }
  279. //Now, for every node from there, add the prefix:
  280. while(count <= pos2){
  281. int size = strlen(searchNode->data) + strlen(prefix) +1;
  282. char *tmp = malloc(size);
  283. //printf("data is %s\n", tmp);
  284.  
  285. sprintf(tmp, "%s%s",prefix, searchNode->data);
  286. //printf("value is now %s\n", tmp);
  287. free(searchNode->data);
  288. searchNode->data = tmp;
  289. searchNode = searchNode->next;
  290. count++;
  291. }
  292. }
  293.  
  294. /* Merge 'tb2' into 'tb1' at line 'pos'.
  295. *
  296. * - Afterwards line 0 of 'tb2' will be line 'pos' of 'tb1'.
  297. * - The old line 'pos' of 'tb1' will follow after the last line of 'tb2'.
  298. * - After this operation 'tb2' can not be used anymore (as if we had used
  299. * releaseTB() on it).
  300. * - The program is to abort() with an error message if 'pos' is out of range.
  301. */
  302. void mergeTB (TB tb1, int pos, TB tb2){
  303. if(tb1 == NULL || tb2 == NULL){
  304. return;
  305. }
  306. if(tb1 == tb2){
  307. printf("can't merge textbuffers that are the same!\n");
  308. return;
  309. }
  310.  
  311. if(pos < 1 || pos > (linesTB(tb1)+1)){
  312. printf("Invalid input\n");
  313. abort();
  314. }
  315. //Three cases:
  316. //printf("num lines of tb1 is %d\n", linesTB(tb1));
  317. //at the start of the textbuffer:
  318. if(pos == 1){
  319. //insert here.
  320. tb2->last->next = tb1->first;
  321. tb1->first->prev = tb2->last;
  322. tb1->first = tb2->first;
  323.  
  324. }
  325. //at the end of the textbuffer:
  326. else if(pos == linesTB(tb1)+1){
  327. tb1->last->next = tb2->first;
  328. tb2->first->prev = tb1->last;
  329. tb1->last = tb2->last;
  330. }
  331. //in the middle of the textbuffer
  332. else {
  333.  
  334. if(pos > 1 && pos < linesTB(tb1)){
  335. //find where to insert it.
  336. int insertionPoint = 1;
  337. TBNode *insertionNode = NULL;
  338. TBNode *current = tb1->first;
  339. TBNode *prevNode = NULL;
  340. while(current != NULL && insertionPoint < pos){
  341. prevNode = current;
  342. insertionPoint++;
  343. current = current->next;
  344.  
  345. }
  346. if(prevNode == NULL){
  347. abort();
  348. }
  349.  
  350. insertionNode = prevNode->next;
  351. prevNode->next = tb2->first;
  352. tb2->first->prev = prevNode;
  353. tb2->last->next = insertionNode;
  354. insertionNode->prev = tb2->last;
  355. }
  356.  
  357. }
  358.  
  359. tb1->textbufferLength += linesTB(tb2);
  360. free(tb2);
  361. //printTB(tb1);
  362. }
  363.  
  364. /* Copy 'tb2' into 'tb1' at line 'pos'.
  365. *
  366. * - Afterwards line 0 of 'tb2' will be line 'pos' of 'tb1'.
  367. * - The old line 'pos' of 'tb1' will follow after the last line of 'tb2'.
  368. * - After this operation 'tb2' is unmodified and remains usable independent
  369. * of 'tb1'.
  370. * - The program is to abort() with an error message if 'pos' is out of range.
  371. */
  372. void pasteTB (TB tb1, int pos, TB tb2) {
  373. if(tb1 == NULL || tb2 == NULL){
  374. return;
  375. }
  376. if(pos <1 || pos > (linesTB(tb1)+2)){
  377. printf("Invalid input\n");
  378. abort();
  379. }
  380. //create a new TB that is a copy of tb2. I'm going to call dump TB then
  381. //call newTB.
  382. char *text = dumpTB(tb2, false);
  383. TB dupTb2 = newTB(text);
  384. //now call merge with these two.
  385. mergeTB(tb1, pos, dupTb2);
  386. //fprintf(stderr, "tb2 is \n");
  387. //printTB(tb2);
  388. return;
  389. }
  390.  
  391. /* Cut the lines between and including 'from' and 'to' out of the textbuffer
  392. * 'tb'.
  393. *
  394. * - The result is a new textbuffer (much as one created with newTB()).
  395. * - The cut lines will be deleted from 'tb'.
  396. * - The program is to abort() with an error message if 'from' or 'to' is out
  397. * of range.
  398. */
  399. TB cutTB (TB tb, int from, int to){
  400. //grab the lines from the tb between from and to.
  401. if(tb == NULL) {
  402. printf("invalid TB\n");
  403. abort();
  404. }
  405. if(from > to){
  406. printf("Invalid input\n");
  407. abort();
  408. }
  409. int length = linesTB(tb);
  410. //printf("length is %d\n", length);
  411. if(from < 1 || to > length){
  412. printf("Invalid input\n");
  413. abort();
  414. }
  415. TBNode *searchNode = tb->first;
  416. //find the node at from
  417. int count = 0;
  418. while(count < from -1){
  419. searchNode = searchNode->next;
  420. count++;
  421. }
  422. //go up until to.
  423. size_t size = sizeInBytes(tb);
  424. char *totalText = malloc(size +1);
  425. if(totalText == NULL){
  426. printf("malloc failed\n");
  427. abort();
  428. }
  429. char *addingPoint = totalText;
  430. while(count < to){
  431. sprintf(addingPoint, "%s\n",searchNode->data);
  432. addingPoint += strlen(searchNode->data) +1;
  433. searchNode = searchNode->next;
  434. count++;
  435. }
  436. //now we have text, create a newTB with it.
  437. TB cutTB = newTB(totalText);
  438. deleteTB(tb, from, to);
  439. /*fprintf(stderr, "cutTB looks like: \n");
  440. printTB(cutTB);
  441. fprintf(stderr, "tb looks like: \n");
  442. printTB(tb);
  443. */
  444. return cutTB;
  445. }
  446.  
  447. /* Return a linked list of Match nodes of all the matches of string search
  448. * in tb
  449. *
  450. * - The textbuffer 'tb' will remain unmodified.
  451. * - The user is responsible of freeing the returned list
  452. */
  453. Match searchTB (TB tb, char* search){
  454. //To keep track of the previous match node added to the list.
  455. Match prev = NULL;
  456. Match head = NULL;
  457. TBNode *curr = tb->first;
  458. int line = 1;
  459. //I'm going to assume the only matches are empty nodes.
  460. if(strncmp(search,"",1) == 0){
  461. while(curr != NULL){
  462. if(strncmp(curr->data,"", 1) == 0){
  463. Match newNode = createMatchNode(line, 0);
  464. if(prev == NULL){
  465. head = newNode;
  466. }
  467. if(prev != NULL){
  468. prev->next = newNode;
  469. }
  470. prev = newNode;
  471. }
  472. line++;
  473. curr = curr->next;
  474. }
  475. }
  476. while(curr != NULL){
  477. char *currentPointer = curr->data;
  478. char *pos;
  479. while((pos = strstr(currentPointer, search)) != NULL){
  480. int column = (pos - curr->data);
  481. //fprintf(stderr,"found a match at line %d and column %d\n", line, column);
  482. Match new = createMatchNode(line,column+1);
  483. if(prev == NULL){
  484. head = new;
  485. }
  486. if(prev != NULL){
  487. prev->next = new;
  488. }
  489. prev = new;
  490. currentPointer = pos + strlen(search);
  491. }
  492. line++;
  493. curr = curr->next;
  494.  
  495. }
  496. /*
  497. if(head != NULL){
  498. Match current = head;
  499. while(current!= NULL){
  500. fprintf(stderr,"we are at %p, line %d, column %d, next is %p\n",current, current->lineNumber, current->columnNumber, current->next);
  501. current = current->next;
  502. }
  503. }
  504. if (head == NULL){
  505. fprintf(stderr,"no matches!\n");
  506. }
  507. */
  508.  
  509. return head;
  510. }
  511.  
  512.  
  513. /* Remove the lines between and including 'from' and 'to' from the textbuffer
  514. * 'tb'.
  515. *
  516. * - The program is to abort() with an error message if 'from' or 'to' is out
  517. * of range.
  518. */
  519. void deleteTB (TB tb, int from, int to){
  520. if(from > to){
  521. printf("Invalid input\n");
  522. abort();
  523. }
  524. int length = linesTB(tb);
  525. //printf("length is %d\n", length);
  526. if(from < 1 || to > length){
  527. printf("Invalid input\n");
  528. abort();
  529. }
  530. TBNode *searchNode = tb->first;
  531. //find the node at from
  532. int count = 0;
  533. while(count < from -1){
  534. searchNode = searchNode->next;
  535. count++;
  536. }
  537.  
  538. while(count < to){
  539. TBNode *newCurrent = searchNode->next;
  540. //Set the node to delete:
  541. TBNode *nodeToDelete = searchNode;
  542. //Cases:
  543. //if we're the last node but there are some before me
  544. if(searchNode == tb->last && tb->textbufferLength >1){
  545. //New Current is now the one before the current node
  546. newCurrent = searchNode->prev;
  547. //Set it to the last:
  548. tb->last = newCurrent;
  549. //it's next is now NULL
  550. newCurrent->next = NULL;
  551.  
  552. //if we're the last node and the only one in the list
  553. } else if (searchNode == tb->last && tb->textbufferLength == 1){
  554. tb->first = NULL;
  555. tb->last = NULL;
  556. //if we're the first node
  557. } else if (searchNode == tb->first) {
  558. newCurrent->prev = NULL;
  559. searchNode->next = NULL;
  560. tb->first = newCurrent;
  561.  
  562. //if we're somewhere in the middle
  563. } else {
  564. searchNode->prev->next = newCurrent;
  565. searchNode->next->prev = searchNode->prev;
  566. }
  567. //we've removed an item
  568. tb->textbufferLength--;
  569. //free the node to delete
  570. freeTBNode(nodeToDelete);
  571. searchNode = newCurrent;
  572. count++;
  573. }
  574. return;
  575. }
  576.  
  577.  
  578. /* Search every line of tb for each occurrence of a set of specified subsitituions
  579. * and alter them accordingly
  580. *
  581. * refer to spec for table.
  582. */
  583.  
  584. void formRichText (TB tb){
  585. TBNode *current = tb->first;
  586. while(current != NULL){
  587. //go through for *
  588. char *pos1 = strchr(current->data, '*');
  589. while(pos1){
  590. //find an equivalent thing that is more than 2 away.
  591. char *search = pos1 +1;
  592. char *pos2 = NULL;
  593. while(*search != '\0'){
  594. if(*search == '*'){
  595. pos2 = search;
  596. break;
  597. }
  598. search++;
  599. }
  600. if(pos2 && pos2-pos1 >= 2){
  601. printf("pos1 is %p and %c\n", pos1, *pos1);
  602. printf("pos2 is %p and %c\n", pos2, *pos2);
  603.  
  604. }
  605. pos1 = 0;
  606. //strchr(current->data, '*');
  607. }
  608. current = current->next;
  609. }
  610.  
  611. }
  612.  
  613. /* Your whitebox tests
  614. */
  615. void whiteBoxTests() {
  616.  
  617. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement