Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers resource_manager.c Source File

resource_manager.c

Go to the documentation of this file.
00001 /**
00002  * @file resource_manager.c
00003  * @brief Embedded resource management
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00022  *
00023  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00024  * @version 1.7.6
00025  **/
00026 
00027 //Dependencies
00028 #include <string.h>
00029 #include "os_port.h"
00030 #include "resource_manager.h"
00031 #include "debug.h"
00032 
00033 //Resource data
00034 extern uint8_t res[];
00035 
00036 
00037 error_t resGetData(const char_t *path, uint8_t **data, size_t *length)
00038 {
00039    bool_t found;
00040    bool_t match;
00041    uint_t n;
00042    uint_t dirLength;
00043    ResEntry *resEntry;
00044 
00045    //Point to the resource header
00046    ResHeader *resHeader = (ResHeader *) res;
00047 
00048    //Make sure the resource data is valid
00049    if(resHeader->totalSize < sizeof(ResHeader))
00050       return ERROR_INVALID_RESOURCE;
00051 
00052    //Retrieve the length of the root directory
00053    dirLength = resHeader->rootEntry.dataLength;
00054    //Point to the contents of the root directory
00055    resEntry = (ResEntry *) (res + resHeader->rootEntry.dataStart);
00056 
00057    //Parse the entire path
00058    for(found = FALSE; !found && path[0] != '\0'; path += n + 1)
00059    {
00060       //Search for the separator that terminates the current token
00061       for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++);
00062 
00063       if(n == 0 && path[n] != '\0')
00064       {
00065          path++;
00066          for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++);
00067       }
00068 
00069       //Loop through the directory
00070       for(match = FALSE; !match && dirLength > 0; )
00071       {
00072          //Check the number of remaining bytes
00073          if(dirLength < sizeof(ResEntry))
00074             return ERROR_INVALID_RESOURCE;
00075          //Make sure the entry is valid
00076          if(dirLength < (sizeof(ResEntry) + resEntry->nameLength))
00077             return ERROR_INVALID_RESOURCE;
00078 
00079          //Compare current entry name against the expected one
00080          if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n))
00081          {
00082             //Check the type of the entry
00083             if(resEntry->type == RES_TYPE_DIR)
00084             {
00085                //Save the length of the directory
00086                dirLength = resEntry->dataLength;
00087                //Point to the contents of the directory
00088                resEntry = (ResEntry *) (res + resEntry->dataStart);
00089             }
00090             else
00091             {
00092                //A file may only appear at the end of the path
00093                if(path[n] != '\0')
00094                   return ERROR_NOT_FOUND;
00095 
00096                //The search process is complete
00097                found = TRUE;
00098             }
00099             //The current entry matches the specified path
00100             match = TRUE;
00101          }
00102          else
00103          {
00104             //Remaining bytes to process
00105             dirLength -= sizeof(ResEntry) + resEntry->nameLength;
00106             //Point to the next entry
00107             resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) + resEntry->nameLength);
00108          }
00109       }
00110 
00111       //Unable to find the specified file?
00112       if(!match)
00113          return ERROR_NOT_FOUND;
00114    }
00115 
00116    //Unable to find the specified file?
00117    if(!found)
00118       return ERROR_NOT_FOUND;
00119    //Enforce the entry type
00120    if(resEntry->type != RES_TYPE_FILE)
00121       return ERROR_NOT_FOUND;
00122 
00123    //Return the location of the specified resource
00124    *data = res + resEntry->dataStart;
00125    //Return the length of the resource
00126    *length = resEntry->dataLength;
00127 
00128    //Successful processing
00129    return NO_ERROR;
00130 }
00131 
00132 
00133 error_t resSearchFile(const char_t *path, DirEntry *dirEntry)
00134 {
00135    bool_t found;
00136    bool_t match;
00137    uint_t n;
00138    uint_t length;
00139    ResEntry *resEntry;
00140 
00141    //Point to the resource header
00142    ResHeader *resHeader = (ResHeader *) res;
00143 
00144    //Make sure the resource data is valid
00145    if(resHeader->totalSize < sizeof(ResHeader))
00146       return ERROR_INVALID_RESOURCE;
00147 
00148    //Retrieve the length of the root directory
00149    length = resHeader->rootEntry.dataLength;
00150    //Point to the contents of the root directory
00151    resEntry = (ResEntry *) (res + resHeader->rootEntry.dataStart);
00152 
00153    //Parse the entire path
00154    for(found = FALSE; !found && path[0] != '\0'; path += n + 1)
00155    {
00156       //Search for the separator that terminates the current token
00157       for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++);
00158 
00159       if(n == 0 && path[n] != '\0')
00160       {
00161          path++;
00162          for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++);
00163       }
00164 
00165       //Loop through the directory
00166       for(match = FALSE; !match && length > 0; )
00167       {
00168          //Check the number of remaining bytes
00169          if(length < sizeof(ResEntry))
00170             return ERROR_INVALID_RESOURCE;
00171          //Make sure the entry is valid
00172          if(length < (sizeof(ResEntry) + resEntry->nameLength))
00173             return ERROR_INVALID_RESOURCE;
00174 
00175          //Compare current entry name against the expected one
00176          if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n))
00177          {
00178             //Check the type of the entry
00179             if(resEntry->type == RES_TYPE_DIR)
00180             {
00181                //Save the length of the directory
00182                length = resEntry->dataLength;
00183                //Point to the contents of the directory
00184                resEntry = (ResEntry *) (res + resEntry->dataStart);
00185             }
00186             else
00187             {
00188                //A file may only appear at the end of the path
00189                if(path[n] != '\0')
00190                   return ERROR_INVALID_PATH;
00191 
00192                //The search process is complete
00193                found = TRUE;
00194             }
00195             //The current entry matches the specified path
00196             match = TRUE;
00197          }
00198          else
00199          {
00200             //Remaining bytes to process
00201             length -= sizeof(ResEntry) + resEntry->nameLength;
00202             //Point to the next entry
00203             resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) + resEntry->nameLength);
00204          }
00205       }
00206 
00207       //Unable to find the specified file?
00208       if(!match)
00209          return ERROR_NOT_FOUND;
00210    }
00211 
00212    //Unable to find the specified file?
00213    if(!found)
00214       return ERROR_NOT_FOUND;
00215 
00216    //Return information about the file
00217    dirEntry->type = resEntry->type;
00218    dirEntry->volume = 0;
00219    dirEntry->dataStart = resEntry->dataStart;
00220    dirEntry->dataLength = resEntry->dataLength;
00221    dirEntry->nameLength = 0; //resEntry->nameLength;
00222    //Copy the filename
00223    //strncpy(dirEntry->name, resEntry->name, dirEntry->nameLength);
00224    //Properly terminate the filename
00225    //dirEntry->name[dirEntry->nameLength] = '\0';
00226 
00227    //Successful processing
00228    return NO_ERROR;
00229 }
00230 
00231 #if 0
00232 
00233 error_t resOpenFile(FsFile *file, const DirEntry *dirEntry, uint_t mode)
00234 {
00235    file->mode = mode;
00236    file->offset = 0;
00237    file->start = dirEntry->dataStart;
00238    file->size = dirEntry->dataLength;
00239 
00240    return NO_ERROR;
00241 }
00242 
00243 
00244 error_t resSeekFile(FsFile *file, uint32_t *position)
00245 {
00246    return ERROR_NOT_IMPLEMENTED;
00247 }
00248 
00249 
00250 uint_t resReadFile(FsFile *file, void *data, size_t length)
00251 {
00252    length = MIN(length, file->size - file->offset);
00253    memcpy(data, res + file->start + file->offset, length);
00254    file->offset += length;
00255    return length;
00256 }
00257 
00258 FILE *fopen(const char_t *filename, const char_t *mode)
00259 {
00260    error_t error;
00261    DirEntry dirEntry;
00262    FsFile *file;
00263 
00264    error = resSearchFile(filename, &dirEntry);
00265    if(error)
00266       return NULL;
00267 
00268    file = osAllocMem(sizeof(FsFile));
00269    if(!file)
00270       return NULL;
00271 
00272    error = resOpenFile(file, &dirEntry, MODE_BINARY);
00273    if(error)
00274    {
00275       osFreeMem(file);
00276       return NULL;
00277    }
00278 
00279    return (FILE *) file;
00280 }
00281 
00282 
00283 size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
00284 {
00285    uint_t n;
00286 
00287    n = resReadFile((FsFile *) stream, ptr, size * count);
00288 
00289    return n / size;
00290 }
00291 
00292 
00293 int_t fclose(FILE * stream)
00294 {
00295    osFreeMem(stream);
00296    //The stream is successfully closed
00297    return 0;
00298 }
00299 
00300 
00301 uint_t fileGetSize(FILE *stream)
00302 {
00303    uint_t n;
00304    n = ((FsFile *) stream)->size;
00305    return n;
00306 }
00307 
00308 #endif
00309