| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE.md file. | |
| 4 | |
| 5 #include <stdio.h> | |
| 6 #include <pthread.h> | |
| 7 #include <stdlib.h> | |
| 8 | |
| 9 #include "include/dartino_api.h" | |
| 10 #include "include/service_api.h" | |
| 11 #include "generated/cc/simple_todo.h" | |
| 12 | |
| 13 static const int kDone = 1; | |
| 14 static pthread_mutex_t mutex; | |
| 15 static pthread_cond_t cond; | |
| 16 static int status = 0; | |
| 17 | |
| 18 typedef enum { | |
| 19 EC_OK = 0, | |
| 20 EC_THREAD, | |
| 21 EC_INPUT_ERR, | |
| 22 } ErrorCode; | |
| 23 | |
| 24 static void ChangeStatusAndNotify(int new_status) { | |
| 25 pthread_mutex_lock(&mutex); | |
| 26 status = new_status; | |
| 27 pthread_cond_signal(&cond); | |
| 28 pthread_mutex_unlock(&mutex); | |
| 29 } | |
| 30 | |
| 31 static void WaitForVmThread(int expected) { | |
| 32 pthread_mutex_lock(&mutex); | |
| 33 while (expected != status) pthread_cond_wait(&cond, &mutex); | |
| 34 pthread_mutex_unlock(&mutex); | |
| 35 } | |
| 36 | |
| 37 static void* StartDartino(void* arg) { | |
| 38 char* snapshot_filepath_with_name = reinterpret_cast<char*>(arg); | |
| 39 DartinoSetup(); | |
| 40 DartinoProgram program = | |
| 41 DartinoLoadSnapshotFromFile(snapshot_filepath_with_name); | |
| 42 if (DartinoRunMain(program, 0, NULL) != 0) { | |
| 43 printf("Failed to run snapshot: %s\n", snapshot_filepath_with_name); | |
| 44 exit(1); | |
| 45 } | |
| 46 DartinoDeleteProgram(program); | |
| 47 DartinoTearDown(); | |
| 48 ChangeStatusAndNotify(kDone); | |
| 49 return NULL; | |
| 50 } | |
| 51 | |
| 52 static void StartVmThread(char* snapshot_filename) { | |
| 53 pthread_mutex_init(&mutex, NULL); | |
| 54 pthread_cond_init(&cond, NULL); | |
| 55 pthread_t tid = 0; | |
| 56 int result = pthread_create(&tid, 0, StartDartino, | |
| 57 reinterpret_cast<void*>(snapshot_filename)); | |
| 58 if (result != 0) { | |
| 59 printf("Error creating thread\n"); | |
| 60 exit(EC_THREAD); | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 class TodoListView { | |
| 65 public: | |
| 66 void showMenu() { | |
| 67 printf("\n #### Todo Menu ####\n" | |
| 68 "m\t-show this menu\n" | |
| 69 "l\t-list todo items\n" | |
| 70 "a\t-add todo item\n" | |
| 71 "t\t-toggle todo item done/undone\n" | |
| 72 "c\t-clear done items\n" | |
| 73 "d\t-delete item\n" | |
| 74 "q\t-quit application\n"); | |
| 75 } | |
| 76 | |
| 77 int readln(char* buffer, int buffer_length) { | |
| 78 int i = 0; | |
| 79 int ch = 0; | |
| 80 | |
| 81 if ((buffer == NULL) || (buffer_length == 0)) return 0; | |
| 82 | |
| 83 do { | |
| 84 ch = getchar(); | |
| 85 if (ch != EOF && ch != '\n') { | |
| 86 buffer[i] = ch; | |
| 87 } | |
| 88 | |
| 89 if (ch == EOF) return -1; | |
| 90 | |
| 91 ++i; | |
| 92 } while (ch != '\n' && i < buffer_length); | |
| 93 buffer[i] = 0; | |
| 94 return i; | |
| 95 } | |
| 96 | |
| 97 // TODO(zarah): In a multithreaded setting this should be atomic or extend | |
| 98 // the service with a List<Item> getItems to use here instead. | |
| 99 void listTodoItems() { | |
| 100 int32_t count = TodoService::getNoItems(); | |
| 101 int32_t i = 0; | |
| 102 | |
| 103 printf("-------------------- ToDo's --------------------\n"); | |
| 104 printf("Listing %2u items\n", count); | |
| 105 for (i = 0; i < count; ++i) { | |
| 106 TodoItem item = TodoService::getItem(i); | |
| 107 const char* done = (item.getDone() ? "+" : " "); | |
| 108 printf("%2u: %s [%1s] \n", item.getId(), item.getTitle(), done); | |
| 109 } | |
| 110 printf("------------------------------------------------\n"); | |
| 111 } | |
| 112 | |
| 113 void addTodoItem() { | |
| 114 char title[60] = {0}; | |
| 115 int title_length = sizeof(title); | |
| 116 printf("Add Todo Item:\n"); | |
| 117 printf("Title: "); | |
| 118 title_length = readln(title, title_length); | |
| 119 printf("\n"); | |
| 120 | |
| 121 int size = 56 + BoxString::kSize + title_length; | |
| 122 MessageBuilder builder(size); | |
| 123 BoxStringBuilder box = builder.initRoot<BoxStringBuilder>(); | |
| 124 box.setS(title); | |
| 125 TodoService::createItem(box); | |
| 126 } | |
| 127 | |
| 128 void toggleTodoItem() { | |
| 129 char idstr[5] = {0}; | |
| 130 printf("[t] Enter id: "); | |
| 131 readln(idstr, sizeof(idstr)); | |
| 132 printf("%s\n", idstr); | |
| 133 TodoService::toggle(atoi(idstr)); | |
| 134 } | |
| 135 | |
| 136 void clear_done_items() { | |
| 137 TodoService::clearItems(); | |
| 138 } | |
| 139 | |
| 140 void deleteItem() { | |
| 141 char idstr[5] = {0}; | |
| 142 printf("[d] Enter id: "); | |
| 143 readln(idstr, sizeof(idstr)); | |
| 144 printf("%s\n", idstr); | |
| 145 TodoService::deleteItem(atoi(idstr)); | |
| 146 } | |
| 147 }; | |
| 148 | |
| 149 static int InteractWithService() { | |
| 150 TodoService::setup(); | |
| 151 ErrorCode ec = EC_OK; | |
| 152 TodoListView view; | |
| 153 view.showMenu(); | |
| 154 bool should_terminate = false; | |
| 155 do { | |
| 156 char in[2] = {0}; | |
| 157 if (view.readln(in, 2) < 0) { | |
| 158 ec = EC_OK; | |
| 159 should_terminate = true; | |
| 160 } else { | |
| 161 printf("\n"); | |
| 162 switch (in[0]) { | |
| 163 case 'q': | |
| 164 should_terminate = true; | |
| 165 break; | |
| 166 case 'm': | |
| 167 view.showMenu(); | |
| 168 break; | |
| 169 case 'l': | |
| 170 view.listTodoItems(); | |
| 171 break; | |
| 172 case 'a': | |
| 173 view.addTodoItem(); | |
| 174 view.listTodoItems(); | |
| 175 break; | |
| 176 case 't': | |
| 177 view.toggleTodoItem(); | |
| 178 view.listTodoItems(); | |
| 179 break; | |
| 180 case 'c': | |
| 181 view.clear_done_items(); | |
| 182 view.listTodoItems(); | |
| 183 break; | |
| 184 case 'd': | |
| 185 view.deleteItem(); | |
| 186 view.listTodoItems(); | |
| 187 break; | |
| 188 default: | |
| 189 break; | |
| 190 } | |
| 191 } | |
| 192 } while (!should_terminate); | |
| 193 TodoService::tearDown(); | |
| 194 return ec; | |
| 195 } | |
| 196 | |
| 197 int main(int argc, char** argv) { | |
| 198 if (argc < 2) { | |
| 199 printf("Usage: %s <snapshot file>\n", argv[0]); | |
| 200 return EC_OK; | |
| 201 } | |
| 202 | |
| 203 ServiceApiSetup(); | |
| 204 StartVmThread(argv[1]); | |
| 205 int ec = InteractWithService(); | |
| 206 WaitForVmThread(kDone); | |
| 207 return ec; | |
| 208 } | |
| OLD | NEW |