Changed general file descriptors to specific for CDU

Dependents:   CDUFinal CDU_Mbed_36

Fork of ConfigFile by Shinichiro Nakamura

Committer:
shintamainjp
Date:
Wed Sep 15 12:23:15 2010 +0000
Revision:
5:56d544b8e5c6
Parent:
4:940510a29b44
Child:
6:f6ceafabe9f8

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shintamainjp 3:7250e339328c 1 /**
shintamainjp 3:7250e339328c 2 * Configuration file interface class (Version 0.0.1)
shintamainjp 3:7250e339328c 3 *
shintamainjp 3:7250e339328c 4 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
shintamainjp 3:7250e339328c 5 * http://shinta.main.jp/
shintamainjp 3:7250e339328c 6 */
shintamainjp 0:6b4ba48753b9 7 #include "ConfigFile.h"
shintamainjp 0:6b4ba48753b9 8
shintamainjp 2:d8febae84a45 9 #define NEWLINE_UNIX "\n"
shintamainjp 2:d8febae84a45 10 #define NEWLINE_DOS "\r\n"
shintamainjp 2:d8febae84a45 11 #define NEWLINE_MAC "\r"
shintamainjp 2:d8febae84a45 12
shintamainjp 0:6b4ba48753b9 13 ConfigFile::ConfigFile() {
shintamainjp 0:6b4ba48753b9 14 /*
shintamainjp 0:6b4ba48753b9 15 * Allocation for a config_t list.
shintamainjp 0:6b4ba48753b9 16 */
shintamainjp 0:6b4ba48753b9 17 configlist = (config_t **)malloc(sizeof(config_t *) * MAXCONFIG);
shintamainjp 0:6b4ba48753b9 18 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 19 configlist[i] = NULL;
shintamainjp 0:6b4ba48753b9 20 }
shintamainjp 0:6b4ba48753b9 21 }
shintamainjp 0:6b4ba48753b9 22
shintamainjp 0:6b4ba48753b9 23 ConfigFile::~ConfigFile() {
shintamainjp 0:6b4ba48753b9 24 /*
shintamainjp 0:6b4ba48753b9 25 * Remove all storage and the contents.
shintamainjp 0:6b4ba48753b9 26 */
shintamainjp 0:6b4ba48753b9 27 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 28 config_t *cfg = configlist[i];
shintamainjp 0:6b4ba48753b9 29 if (cfg != NULL) {
shintamainjp 0:6b4ba48753b9 30 free(cfg->key);
shintamainjp 0:6b4ba48753b9 31 free(cfg->value);
shintamainjp 0:6b4ba48753b9 32 free(cfg);
shintamainjp 0:6b4ba48753b9 33 }
shintamainjp 0:6b4ba48753b9 34 configlist[i] = NULL;
shintamainjp 0:6b4ba48753b9 35 }
shintamainjp 0:6b4ba48753b9 36
shintamainjp 0:6b4ba48753b9 37 /*
shintamainjp 0:6b4ba48753b9 38 * Remove cnofig_t list.
shintamainjp 0:6b4ba48753b9 39 */
shintamainjp 0:6b4ba48753b9 40 free(configlist);
shintamainjp 0:6b4ba48753b9 41 configlist = NULL;
shintamainjp 0:6b4ba48753b9 42 }
shintamainjp 0:6b4ba48753b9 43
shintamainjp 1:f02e081afe42 44 bool ConfigFile::getValue(char *key, char *value, size_t siz) {
shintamainjp 0:6b4ba48753b9 45 /*
shintamainjp 0:6b4ba48753b9 46 * Null check.
shintamainjp 0:6b4ba48753b9 47 */
shintamainjp 0:6b4ba48753b9 48 if (key == NULL) {
shintamainjp 1:f02e081afe42 49 return false;
shintamainjp 0:6b4ba48753b9 50 }
shintamainjp 0:6b4ba48753b9 51
shintamainjp 0:6b4ba48753b9 52 /*
shintamainjp 0:6b4ba48753b9 53 * Search a config_t object from the key.
shintamainjp 0:6b4ba48753b9 54 */
shintamainjp 0:6b4ba48753b9 55 config_t *p = search(key);
shintamainjp 0:6b4ba48753b9 56 if (p == NULL) {
shintamainjp 1:f02e081afe42 57 return false;
shintamainjp 1:f02e081afe42 58 }
shintamainjp 2:d8febae84a45 59
shintamainjp 1:f02e081afe42 60 /*
shintamainjp 1:f02e081afe42 61 * Check the storage size.
shintamainjp 1:f02e081afe42 62 */
shintamainjp 1:f02e081afe42 63 if (siz <= strlen(p->value)) {
shintamainjp 1:f02e081afe42 64 return false;
shintamainjp 0:6b4ba48753b9 65 }
shintamainjp 0:6b4ba48753b9 66
shintamainjp 0:6b4ba48753b9 67 /*
shintamainjp 1:f02e081afe42 68 * Copy the value to the storage.
shintamainjp 0:6b4ba48753b9 69 */
shintamainjp 1:f02e081afe42 70 strcpy(value, p->value);
shintamainjp 1:f02e081afe42 71 return true;
shintamainjp 0:6b4ba48753b9 72 }
shintamainjp 0:6b4ba48753b9 73
shintamainjp 0:6b4ba48753b9 74 bool ConfigFile::setValue(char *key, char *value) {
shintamainjp 0:6b4ba48753b9 75 /*
shintamainjp 0:6b4ba48753b9 76 * Null check.
shintamainjp 0:6b4ba48753b9 77 */
shintamainjp 0:6b4ba48753b9 78 if ((key == NULL) || (value == NULL)) {
shintamainjp 0:6b4ba48753b9 79 return false;
shintamainjp 0:6b4ba48753b9 80 }
shintamainjp 0:6b4ba48753b9 81
shintamainjp 0:6b4ba48753b9 82 /*
shintamainjp 0:6b4ba48753b9 83 * Size check.
shintamainjp 0:6b4ba48753b9 84 */
shintamainjp 0:6b4ba48753b9 85 if ((MAXLEN_KEY < strlen(key)) || (MAXLEN_VALUE < strlen(value))) {
shintamainjp 0:6b4ba48753b9 86 return false;
shintamainjp 0:6b4ba48753b9 87 }
shintamainjp 0:6b4ba48753b9 88
shintamainjp 0:6b4ba48753b9 89 /*
shintamainjp 0:6b4ba48753b9 90 * Search a config_t object from the key.
shintamainjp 0:6b4ba48753b9 91 */
shintamainjp 0:6b4ba48753b9 92 config_t *p = search(key);
shintamainjp 0:6b4ba48753b9 93 if (p == NULL) {
shintamainjp 0:6b4ba48753b9 94 /*
shintamainjp 0:6b4ba48753b9 95 * Allocation a memory for a new key.
shintamainjp 0:6b4ba48753b9 96 */
shintamainjp 0:6b4ba48753b9 97 char *k = (char *)malloc(sizeof(char) * (strlen(key) + 1));
shintamainjp 0:6b4ba48753b9 98 if (k == NULL) {
shintamainjp 0:6b4ba48753b9 99 return false;
shintamainjp 0:6b4ba48753b9 100 }
shintamainjp 0:6b4ba48753b9 101 strcpy(k, key);
shintamainjp 0:6b4ba48753b9 102
shintamainjp 0:6b4ba48753b9 103 /*
shintamainjp 0:6b4ba48753b9 104 * Allocation a memory for a new value.
shintamainjp 0:6b4ba48753b9 105 */
shintamainjp 0:6b4ba48753b9 106 char *v = (char *)malloc(sizeof(char) * (strlen(value) + 1));
shintamainjp 0:6b4ba48753b9 107 if (v == NULL) {
shintamainjp 0:6b4ba48753b9 108 free(k);
shintamainjp 0:6b4ba48753b9 109 return false;
shintamainjp 0:6b4ba48753b9 110 }
shintamainjp 0:6b4ba48753b9 111 strcpy(v, value);
shintamainjp 0:6b4ba48753b9 112
shintamainjp 0:6b4ba48753b9 113 /*
shintamainjp 0:6b4ba48753b9 114 * Allocation a memory for a new configuration.
shintamainjp 0:6b4ba48753b9 115 */
shintamainjp 0:6b4ba48753b9 116 config_t *cfg = (config_t *)malloc(sizeof(config_t) * 1);
shintamainjp 0:6b4ba48753b9 117 if (cfg == NULL) {
shintamainjp 0:6b4ba48753b9 118 free(k);
shintamainjp 0:6b4ba48753b9 119 free(v);
shintamainjp 0:6b4ba48753b9 120 return false;
shintamainjp 0:6b4ba48753b9 121 }
shintamainjp 0:6b4ba48753b9 122 cfg->key = k;
shintamainjp 0:6b4ba48753b9 123 cfg->value = v;
shintamainjp 0:6b4ba48753b9 124
shintamainjp 0:6b4ba48753b9 125 /*
shintamainjp 0:6b4ba48753b9 126 * Add the new configuration.
shintamainjp 0:6b4ba48753b9 127 */
shintamainjp 0:6b4ba48753b9 128 if (!add(cfg)) {
shintamainjp 0:6b4ba48753b9 129 free(k);
shintamainjp 0:6b4ba48753b9 130 free(v);
shintamainjp 0:6b4ba48753b9 131 free(cfg);
shintamainjp 0:6b4ba48753b9 132 return false;
shintamainjp 0:6b4ba48753b9 133 }
shintamainjp 0:6b4ba48753b9 134
shintamainjp 0:6b4ba48753b9 135 return true;
shintamainjp 0:6b4ba48753b9 136 } else {
shintamainjp 0:6b4ba48753b9 137 /*
shintamainjp 0:6b4ba48753b9 138 * The value is same.
shintamainjp 0:6b4ba48753b9 139 */
shintamainjp 0:6b4ba48753b9 140 if (strcmp(value, p->value) == 0) {
shintamainjp 0:6b4ba48753b9 141 return true;
shintamainjp 0:6b4ba48753b9 142 }
shintamainjp 0:6b4ba48753b9 143
shintamainjp 0:6b4ba48753b9 144 /*
shintamainjp 0:6b4ba48753b9 145 * Free a memory for the value.
shintamainjp 0:6b4ba48753b9 146 */
shintamainjp 0:6b4ba48753b9 147 free(p->value);
shintamainjp 0:6b4ba48753b9 148 p->value = NULL;
shintamainjp 0:6b4ba48753b9 149
shintamainjp 0:6b4ba48753b9 150 /*
shintamainjp 0:6b4ba48753b9 151 * Allocation memory for the new value.
shintamainjp 0:6b4ba48753b9 152 */
shintamainjp 0:6b4ba48753b9 153 char *v = (char *)malloc(sizeof(char) * (strlen(value) + 1));
shintamainjp 0:6b4ba48753b9 154 if (v == NULL) {
shintamainjp 0:6b4ba48753b9 155 return false;
shintamainjp 0:6b4ba48753b9 156 }
shintamainjp 0:6b4ba48753b9 157
shintamainjp 0:6b4ba48753b9 158 /*
shintamainjp 0:6b4ba48753b9 159 * Store it.
shintamainjp 0:6b4ba48753b9 160 */
shintamainjp 0:6b4ba48753b9 161 strcpy(v, value);
shintamainjp 0:6b4ba48753b9 162 p->value = v;
shintamainjp 0:6b4ba48753b9 163
shintamainjp 0:6b4ba48753b9 164 return true;
shintamainjp 0:6b4ba48753b9 165 }
shintamainjp 0:6b4ba48753b9 166 }
shintamainjp 0:6b4ba48753b9 167
shintamainjp 0:6b4ba48753b9 168 bool ConfigFile::remove(char *key) {
shintamainjp 0:6b4ba48753b9 169 if (key == NULL) {
shintamainjp 0:6b4ba48753b9 170 return false;
shintamainjp 0:6b4ba48753b9 171 }
shintamainjp 0:6b4ba48753b9 172 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 173 config_t *cfg = configlist[i];
shintamainjp 0:6b4ba48753b9 174 if (cfg != NULL) {
shintamainjp 0:6b4ba48753b9 175 if (strcmp(cfg->key, key) == 0) {
shintamainjp 0:6b4ba48753b9 176 free(cfg->key);
shintamainjp 0:6b4ba48753b9 177 free(cfg->value);
shintamainjp 0:6b4ba48753b9 178 free(cfg);
shintamainjp 0:6b4ba48753b9 179 configlist[i] = NULL;
shintamainjp 0:6b4ba48753b9 180 return true;
shintamainjp 0:6b4ba48753b9 181 }
shintamainjp 0:6b4ba48753b9 182 }
shintamainjp 0:6b4ba48753b9 183 }
shintamainjp 0:6b4ba48753b9 184 return false;
shintamainjp 0:6b4ba48753b9 185 }
shintamainjp 0:6b4ba48753b9 186
shintamainjp 0:6b4ba48753b9 187 bool ConfigFile::removeAll(void) {
shintamainjp 0:6b4ba48753b9 188 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 189 config_t *p = configlist[i];
shintamainjp 0:6b4ba48753b9 190 if (p != NULL) {
shintamainjp 0:6b4ba48753b9 191 free(p->key);
shintamainjp 0:6b4ba48753b9 192 free(p->value);
shintamainjp 0:6b4ba48753b9 193 }
shintamainjp 0:6b4ba48753b9 194 free(p);
shintamainjp 0:6b4ba48753b9 195 configlist[i] = NULL;
shintamainjp 0:6b4ba48753b9 196 }
shintamainjp 0:6b4ba48753b9 197 return true;
shintamainjp 0:6b4ba48753b9 198 }
shintamainjp 0:6b4ba48753b9 199
shintamainjp 5:56d544b8e5c6 200 int ConfigFile::getCount() {
shintamainjp 5:56d544b8e5c6 201 int cnt = 0;
shintamainjp 5:56d544b8e5c6 202 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 5:56d544b8e5c6 203 config_t *p = configlist[i];
shintamainjp 5:56d544b8e5c6 204 if (p != NULL) {
shintamainjp 5:56d544b8e5c6 205 cnt++;
shintamainjp 5:56d544b8e5c6 206 }
shintamainjp 5:56d544b8e5c6 207 }
shintamainjp 5:56d544b8e5c6 208 return cnt;
shintamainjp 5:56d544b8e5c6 209 }
shintamainjp 5:56d544b8e5c6 210
shintamainjp 5:56d544b8e5c6 211 bool ConfigFile::getKeyAndValue(int index, char *key, size_t keybufsiz, char *value, size_t valuebufsiz) {
shintamainjp 5:56d544b8e5c6 212 int cnt = 0;
shintamainjp 5:56d544b8e5c6 213 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 5:56d544b8e5c6 214 config_t *p = configlist[i];
shintamainjp 5:56d544b8e5c6 215 if (p != NULL) {
shintamainjp 5:56d544b8e5c6 216 if (cnt == index) {
shintamainjp 5:56d544b8e5c6 217 if ((strlen(p->key) < keybufsiz) && (strlen(p->value) < valuebufsiz)) {
shintamainjp 5:56d544b8e5c6 218 strcpy(key, p->key);
shintamainjp 5:56d544b8e5c6 219 strcpy(value, p->value);
shintamainjp 5:56d544b8e5c6 220 return true;
shintamainjp 5:56d544b8e5c6 221 }
shintamainjp 5:56d544b8e5c6 222 return false;
shintamainjp 5:56d544b8e5c6 223 }
shintamainjp 5:56d544b8e5c6 224 cnt++;
shintamainjp 5:56d544b8e5c6 225 }
shintamainjp 5:56d544b8e5c6 226 }
shintamainjp 5:56d544b8e5c6 227 return false;
shintamainjp 5:56d544b8e5c6 228 }
shintamainjp 5:56d544b8e5c6 229
shintamainjp 0:6b4ba48753b9 230 bool ConfigFile::read(char *file) {
shintamainjp 0:6b4ba48753b9 231 /*
shintamainjp 0:6b4ba48753b9 232 * Open the target file.
shintamainjp 0:6b4ba48753b9 233 */
shintamainjp 0:6b4ba48753b9 234 FILE *fp = fopen(file, "r");
shintamainjp 0:6b4ba48753b9 235 if (fp == NULL) {
shintamainjp 0:6b4ba48753b9 236 return false;
shintamainjp 0:6b4ba48753b9 237 }
shintamainjp 0:6b4ba48753b9 238
shintamainjp 0:6b4ba48753b9 239 /*
shintamainjp 0:6b4ba48753b9 240 * Remove all configuration.
shintamainjp 0:6b4ba48753b9 241 */
shintamainjp 0:6b4ba48753b9 242 removeAll();
shintamainjp 0:6b4ba48753b9 243
shintamainjp 0:6b4ba48753b9 244 /*
shintamainjp 0:6b4ba48753b9 245 * Read from a file.
shintamainjp 0:6b4ba48753b9 246 */
shintamainjp 0:6b4ba48753b9 247 char buf[MAXLEN_KEY + 8 + MAXLEN_VALUE];
shintamainjp 0:6b4ba48753b9 248 while (fgets(buf, sizeof(buf), fp) != NULL) {
shintamainjp 0:6b4ba48753b9 249 /*
shintamainjp 0:6b4ba48753b9 250 * Ignore a comment.
shintamainjp 0:6b4ba48753b9 251 */
shintamainjp 0:6b4ba48753b9 252 if (buf[0] == '#') {
shintamainjp 0:6b4ba48753b9 253 continue;
shintamainjp 0:6b4ba48753b9 254 }
shintamainjp 2:d8febae84a45 255
shintamainjp 0:6b4ba48753b9 256 /*
shintamainjp 0:6b4ba48753b9 257 * Trim a return.
shintamainjp 0:6b4ba48753b9 258 */
shintamainjp 0:6b4ba48753b9 259 const size_t len = strlen(buf);
shintamainjp 0:6b4ba48753b9 260 for (int i = 0; i < len; i++) {
shintamainjp 0:6b4ba48753b9 261 if ((buf[i] == '\r') || (buf[i] == '\n')) {
shintamainjp 0:6b4ba48753b9 262 buf[i] = '\0';
shintamainjp 0:6b4ba48753b9 263 }
shintamainjp 0:6b4ba48753b9 264 }
shintamainjp 0:6b4ba48753b9 265
shintamainjp 0:6b4ba48753b9 266 /*
shintamainjp 0:6b4ba48753b9 267 * Separate key and value.
shintamainjp 2:d8febae84a45 268 */
shintamainjp 0:6b4ba48753b9 269 char k[MAXLEN_KEY];
shintamainjp 0:6b4ba48753b9 270 char v[MAXLEN_VALUE];
shintamainjp 0:6b4ba48753b9 271 char *sp = strchr(buf, SEPARATOR);
shintamainjp 0:6b4ba48753b9 272 if (sp != NULL) {
shintamainjp 0:6b4ba48753b9 273 strcpy(v, sp + 1);
shintamainjp 0:6b4ba48753b9 274 *sp = '\0';
shintamainjp 0:6b4ba48753b9 275 strcpy(k, buf);
shintamainjp 0:6b4ba48753b9 276 setValue(k, v);
shintamainjp 0:6b4ba48753b9 277 }
shintamainjp 0:6b4ba48753b9 278 }
shintamainjp 0:6b4ba48753b9 279 fclose(fp);
shintamainjp 0:6b4ba48753b9 280 return true;
shintamainjp 0:6b4ba48753b9 281 }
shintamainjp 0:6b4ba48753b9 282
shintamainjp 4:940510a29b44 283 bool ConfigFile::write(char *file, char *header, FileFormat ff) {
shintamainjp 2:d8febae84a45 284 /*
shintamainjp 2:d8febae84a45 285 * Open the target file.
shintamainjp 2:d8febae84a45 286 */
shintamainjp 0:6b4ba48753b9 287 FILE *fp = fopen(file, "w");
shintamainjp 0:6b4ba48753b9 288 if (fp == NULL) {
shintamainjp 0:6b4ba48753b9 289 return false;
shintamainjp 0:6b4ba48753b9 290 }
shintamainjp 0:6b4ba48753b9 291
shintamainjp 2:d8febae84a45 292 /*
shintamainjp 2:d8febae84a45 293 * Set a type of new line.
shintamainjp 2:d8febae84a45 294 */
shintamainjp 2:d8febae84a45 295 char *newline = NEWLINE_UNIX;
shintamainjp 2:d8febae84a45 296 switch (ff) {
shintamainjp 2:d8febae84a45 297 case UNIX:
shintamainjp 2:d8febae84a45 298 newline = NEWLINE_UNIX;
shintamainjp 2:d8febae84a45 299 break;
shintamainjp 2:d8febae84a45 300 case MAC:
shintamainjp 2:d8febae84a45 301 newline = NEWLINE_MAC;
shintamainjp 2:d8febae84a45 302 break;
shintamainjp 2:d8febae84a45 303 case DOS:
shintamainjp 2:d8febae84a45 304 newline = NEWLINE_DOS;
shintamainjp 2:d8febae84a45 305 break;
shintamainjp 2:d8febae84a45 306 default:
shintamainjp 2:d8febae84a45 307 newline = NEWLINE_UNIX;
shintamainjp 2:d8febae84a45 308 break;
shintamainjp 2:d8febae84a45 309 }
shintamainjp 2:d8febae84a45 310
shintamainjp 2:d8febae84a45 311 /*
shintamainjp 4:940510a29b44 312 * Write the header.
shintamainjp 4:940510a29b44 313 */
shintamainjp 4:940510a29b44 314 if (header != NULL) {
shintamainjp 4:940510a29b44 315 fprintf(fp, "%s%s", header, newline);
shintamainjp 4:940510a29b44 316 }
shintamainjp 4:940510a29b44 317
shintamainjp 4:940510a29b44 318 /*
shintamainjp 2:d8febae84a45 319 * Write the data.
shintamainjp 2:d8febae84a45 320 */
shintamainjp 0:6b4ba48753b9 321 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 322 config_t *cfg = configlist[i];
shintamainjp 0:6b4ba48753b9 323 if (cfg != NULL) {
shintamainjp 2:d8febae84a45 324 fprintf(fp, "%s=%s%s", cfg->key, cfg->value, newline);
shintamainjp 0:6b4ba48753b9 325 }
shintamainjp 0:6b4ba48753b9 326 }
shintamainjp 0:6b4ba48753b9 327 fclose(fp);
shintamainjp 0:6b4ba48753b9 328 return true;
shintamainjp 0:6b4ba48753b9 329 }
shintamainjp 0:6b4ba48753b9 330
shintamainjp 0:6b4ba48753b9 331 ConfigFile::config_t *ConfigFile::search(char *key) {
shintamainjp 0:6b4ba48753b9 332 if (key == NULL) {
shintamainjp 0:6b4ba48753b9 333 return NULL;
shintamainjp 0:6b4ba48753b9 334 }
shintamainjp 0:6b4ba48753b9 335 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 336 if (configlist[i] != NULL) {
shintamainjp 0:6b4ba48753b9 337 if (strcmp(configlist[i]->key, key) == 0) {
shintamainjp 0:6b4ba48753b9 338 return configlist[i];
shintamainjp 0:6b4ba48753b9 339 }
shintamainjp 0:6b4ba48753b9 340 }
shintamainjp 0:6b4ba48753b9 341 }
shintamainjp 0:6b4ba48753b9 342 return NULL;
shintamainjp 0:6b4ba48753b9 343 }
shintamainjp 0:6b4ba48753b9 344
shintamainjp 0:6b4ba48753b9 345 bool ConfigFile::add(config_t *cfg) {
shintamainjp 0:6b4ba48753b9 346 for (int i = 0; i < MAXCONFIG; i++) {
shintamainjp 0:6b4ba48753b9 347 if (configlist[i] == NULL) {
shintamainjp 0:6b4ba48753b9 348 configlist[i] = cfg;
shintamainjp 0:6b4ba48753b9 349 return true;
shintamainjp 0:6b4ba48753b9 350 }
shintamainjp 0:6b4ba48753b9 351 }
shintamainjp 0:6b4ba48753b9 352 return false;
shintamainjp 0:6b4ba48753b9 353 }