1/*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2015 Paul Sokolovsky
7 * Copyright (c) 2016 Damien P. George
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28#include <string.h>
29#include <stdint.h>
30
31#include "py/lexer.h"
32#include "py/frozenmod.h"
33
34#if MICROPY_MODULE_FROZEN_STR
35
36#ifndef MICROPY_MODULE_FROZEN_LEXER
37#define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str_len
38#else
39mp_lexer_t *MICROPY_MODULE_FROZEN_LEXER(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len);
40#endif
41
42extern const char mp_frozen_str_names[];
43extern const uint32_t mp_frozen_str_sizes[];
44extern const char mp_frozen_str_content[];
45
46// On input, *len contains size of name, on output - size of content
47const char *mp_find_frozen_str(const char *str, size_t *len) {
48 const char *name = mp_frozen_str_names;
49
50 size_t offset = 0;
51 for (int i = 0; *name != 0; i++) {
52 size_t l = strlen(name);
53 if (l == *len && !memcmp(str, name, l)) {
54 *len = mp_frozen_str_sizes[i];
55 return mp_frozen_str_content + offset;
56 }
57 name += l + 1;
58 offset += mp_frozen_str_sizes[i] + 1;
59 }
60 return NULL;
61}
62
63STATIC mp_lexer_t *mp_lexer_frozen_str(const char *str, size_t len) {
64 size_t name_len = len;
65 const char *content = mp_find_frozen_str(str, &len);
66
67 if (content == NULL) {
68 return NULL;
69 }
70
71 qstr source = qstr_from_strn(str, name_len);
72 mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, len, 0);
73 return lex;
74}
75
76#endif
77
78#if MICROPY_MODULE_FROZEN_MPY
79
80#include "py/emitglue.h"
81
82extern const char mp_frozen_mpy_names[];
83extern const mp_raw_code_t *const mp_frozen_mpy_content[];
84
85STATIC const mp_raw_code_t *mp_find_frozen_mpy(const char *str, size_t len) {
86 const char *name = mp_frozen_mpy_names;
87 for (size_t i = 0; *name != 0; i++) {
88 size_t l = strlen(name);
89 if (l == len && !memcmp(str, name, l)) {
90 return mp_frozen_mpy_content[i];
91 }
92 name += l + 1;
93 }
94 return NULL;
95}
96
97#endif
98
99#if MICROPY_MODULE_FROZEN
100
101STATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) {
102 size_t len = strlen(str);
103
104 for (int i = 0; *name != 0; i++) {
105 size_t l = strlen(name);
106 if (l >= len && !memcmp(str, name, len)) {
107 if (name[len] == 0) {
108 return MP_IMPORT_STAT_FILE;
109 } else if (name[len] == '/') {
110 return MP_IMPORT_STAT_DIR;
111 }
112 }
113 name += l + 1;
114 }
115 return MP_IMPORT_STAT_NO_EXIST;
116}
117
118mp_import_stat_t mp_frozen_stat(const char *str) {
119 mp_import_stat_t stat;
120
121 #if MICROPY_MODULE_FROZEN_STR
122 stat = mp_frozen_stat_helper(mp_frozen_str_names, str);
123 if (stat != MP_IMPORT_STAT_NO_EXIST) {
124 return stat;
125 }
126 #endif
127
128 #if MICROPY_MODULE_FROZEN_MPY
129 stat = mp_frozen_stat_helper(mp_frozen_mpy_names, str);
130 if (stat != MP_IMPORT_STAT_NO_EXIST) {
131 return stat;
132 }
133 #endif
134
135 return MP_IMPORT_STAT_NO_EXIST;
136}
137
138int mp_find_frozen_module(const char *str, size_t len, void **data) {
139 #if MICROPY_MODULE_FROZEN_STR
140 mp_lexer_t *lex = mp_lexer_frozen_str(str, len);
141 if (lex != NULL) {
142 *data = lex;
143 return MP_FROZEN_STR;
144 }
145 #endif
146 #if MICROPY_MODULE_FROZEN_MPY
147 const mp_raw_code_t *rc = mp_find_frozen_mpy(str, len);
148 if (rc != NULL) {
149 *data = (void *)rc;
150 return MP_FROZEN_MPY;
151 }
152 #endif
153 return MP_FROZEN_NONE;
154}
155
156#endif
157