diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..2546c70 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,73 @@ +name: Deploy Game + +on: + push: + branches: + - main + tags: + - v* + pull_request: + branches: + - main + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + deploy: + name: Deploy + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup cache + uses: actions/cache@v4 + with: + path: "_deps" + key: deps-${{ runner.os }} + + - uses: mymindstorm/setup-emsdk@v14 + with: + version: 4.0.6 + actions-cache-folder: "emsdk-cache" + + - name: Download ports + run: | + embuilder build harfbuzz + + - name: Run CMake + run: emcmake cmake -G "Unix Makefiles" . + + - name: Make + run: emmake make -j4 + + - uses: actions/upload-pages-artifact@v3 + if: github.ref == 'refs/heads/main' + with: + path: ./build + + - name: Deploy to GitHub Pages + if: github.ref == 'refs/heads/main' + id: deployment + uses: actions/deploy-pages@v4 + + - name: Deploy to A.D.S. Games + if: startsWith(github.ref, 'refs/tags/v') + uses: adsgames/deploy-to-adsgames@v1.1.2 + with: + project-id: mazes + build-dir: ./build/ + platform: WEB + bucket-access-key: ${{ secrets.LINODE_BUCKET_ACCESS_KEY }} + bucket-secret-key: ${{ secrets.LINODE_BUCKET_SECRET_KEY }} + api-key: ${{ secrets.ADSGAMES_API_KEY }} diff --git a/.gitignore b/.gitignore index b29cb11..86cf8dd 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ $RECYCLE.BIN/ # Icon must ends with two \r. Icon - # Thumbnails ._* @@ -49,4 +48,6 @@ install_manifest.txt bin docs lib -build/Mazes* \ No newline at end of file +build/ +_deps/ +compile_commands.json diff --git a/.vscode/settings.json b/.vscode/settings.json index d1fe325..abe124e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,52 @@ { "files.associations": { - "fstream": "cpp" + "fstream": "cpp", + "array": "cpp", + "__bit_reference": "cpp", + "__config": "cpp", + "__locale": "cpp", + "__threading_support": "cpp", + "__verbose_abort": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "execution": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "locale": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "tuple": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "algorithm": "cpp", + "bit": "cpp", + "compare": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "*.tcc": "cpp", + "cinttypes": "cpp", + "random": "cpp" } -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt index dc2aa1d..7e84acb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,27 +1,58 @@ -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.24) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -project (Mazes) +include(FetchContent) + +project(Mazes) # Source code file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp) file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) -add_executable (${PROJECT_NAME} ${SOURCES} ${HEADERS}) +add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic) -# Find libs -find_library(ALLEGRO_LIBRARY NAMES alleg44 alleg REQUIRED) -find_library(ALLEGRO_PNG_LIBRARY NAMES loadpng REQUIRED) -find_library(ALLEGRO_OGG_LIBRARY NAMES logg REQUIRED) - +FetchContent_Declare( + asw + GIT_REPOSITORY https://github.com/adsgames/asw.git + GIT_TAG v0.5.4 +) +FetchContent_MakeAvailable(asw) # Link Libs -target_link_libraries(${PROJECT_NAME} ${ALLEGRO_LIBRARY}) -target_link_libraries(${PROJECT_NAME} ${ALLEGRO_PNG_LIBRARY}) -target_link_libraries(${PROJECT_NAME} ${ALLEGRO_OGG_LIBRARY}) - +if(MINGW) + target_link_libraries(${PROJECT_NAME} -lmingw32) +endif(MINGW) + +target_link_libraries( + ${PROJECT_NAME} + asw +) + +# Emscripten support +if(EMSCRIPTEN) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set(CMAKE_EXECUTABLE_SUFFIX ".html") + + target_link_libraries( + ${PROJECT_NAME} + -sWASM=1 + -sALLOW_MEMORY_GROWTH=1 + -sMAXIMUM_MEMORY=1gb + ) + + set_target_properties( + ${PROJECT_NAME} + PROPERTIES + LINK_FLAGS + "--preload-file ${CMAKE_CURRENT_LIST_DIR}/assets@/assets --use-preload-plugins --shell-file ${CMAKE_CURRENT_LIST_DIR}/index.html" + ) +endif(EMSCRIPTEN) + +file(COPY ${CMAKE_CURRENT_LIST_DIR}/assets DESTINATION ${CMAKE_BINARY_DIR}/build) \ No newline at end of file diff --git a/README.md b/README.md index cfdf098..d376abb 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,27 @@ # Mazes -A simple maze Sokoban type game based developed while learning c++ game development with allegro. - -## Getting started - -### Windows (MSYS2) - -#### Install Libraries - -```bash -https://www.allegro.cc/files/?v=4.4 -``` - -#### Build - -```bash -cmake -G "MSYS Makefiles" . -``` - -```bash -make -``` +[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=AdsGames_mazes&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=AdsGames_mazes) +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=AdsGames_mazes&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=AdsGames_mazes) +[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=AdsGames_mazes&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=AdsGames_mazes) -### Mac OS +A simple maze Sokoban type game based developed while learning c++ game development with allegro. -#### Install Libraries +## Demo -```bash -https://github.com/msikma/liballeg.4.4.2-osx -``` +[Web Demo](https://adsgames.github.io/mazes/) -#### Build +## Setup -```bash -cmake -G "Unix Makefiles" . -``` +### Build ```bash +cmake . make ``` -### Linux - -#### Install Libraries - -```bash -sudo apt-get install liballegro4-dev libloadpng4-dev liblogg4-dev -``` - -#### Build - -```bash -cmake -G "Unix Makefiles" . -``` +### Build Emscripten ```bash +emcmake cmake . make ``` diff --git a/assets/fonts/dosis.ttf b/assets/fonts/dosis.ttf new file mode 100644 index 0000000..49fe002 Binary files /dev/null and b/assets/fonts/dosis.ttf differ diff --git a/assets/images/background.png b/assets/images/background.png new file mode 100644 index 0000000..c86528d Binary files /dev/null and b/assets/images/background.png differ diff --git a/assets/images/blocks/2d/box.png b/assets/images/blocks/2d/box.png new file mode 100644 index 0000000..7e226fb Binary files /dev/null and b/assets/images/blocks/2d/box.png differ diff --git a/assets/images/blocks/2d/broom.png b/assets/images/blocks/2d/broom.png new file mode 100644 index 0000000..047ed97 Binary files /dev/null and b/assets/images/blocks/2d/broom.png differ diff --git a/assets/images/blocks/2d/character.png b/assets/images/blocks/2d/character.png new file mode 100644 index 0000000..7fe3f0b Binary files /dev/null and b/assets/images/blocks/2d/character.png differ diff --git a/assets/images/blocks/2d/garbagecan.png b/assets/images/blocks/2d/garbagecan.png new file mode 100644 index 0000000..6e4a158 Binary files /dev/null and b/assets/images/blocks/2d/garbagecan.png differ diff --git a/assets/images/blocks/2d/ground.png b/assets/images/blocks/2d/ground.png new file mode 100644 index 0000000..8e99c63 Binary files /dev/null and b/assets/images/blocks/2d/ground.png differ diff --git a/assets/images/blocks/2d/janitor_room.png b/assets/images/blocks/2d/janitor_room.png new file mode 100644 index 0000000..4f90a10 Binary files /dev/null and b/assets/images/blocks/2d/janitor_room.png differ diff --git a/assets/images/blocks/2d/janitor_room_open.png b/assets/images/blocks/2d/janitor_room_open.png new file mode 100644 index 0000000..cde5e94 Binary files /dev/null and b/assets/images/blocks/2d/janitor_room_open.png differ diff --git a/assets/images/blocks/2d/robot.png b/assets/images/blocks/2d/robot.png new file mode 100644 index 0000000..99a10f9 Binary files /dev/null and b/assets/images/blocks/2d/robot.png differ diff --git a/assets/images/blocks/2d/scrap.png b/assets/images/blocks/2d/scrap.png new file mode 100644 index 0000000..fbc46d3 Binary files /dev/null and b/assets/images/blocks/2d/scrap.png differ diff --git a/assets/images/blocks/2d/wall.png b/assets/images/blocks/2d/wall.png new file mode 100644 index 0000000..4b3b4d5 Binary files /dev/null and b/assets/images/blocks/2d/wall.png differ diff --git a/assets/images/blocks/2d/wall2.png b/assets/images/blocks/2d/wall2.png new file mode 100644 index 0000000..d6ddfaf Binary files /dev/null and b/assets/images/blocks/2d/wall2.png differ diff --git a/assets/images/blocks/2d/wood_floor.png b/assets/images/blocks/2d/wood_floor.png new file mode 100644 index 0000000..3d3fc08 Binary files /dev/null and b/assets/images/blocks/2d/wood_floor.png differ diff --git a/assets/images/blocks/3d/box.png b/assets/images/blocks/3d/box.png new file mode 100644 index 0000000..c4b606e Binary files /dev/null and b/assets/images/blocks/3d/box.png differ diff --git a/assets/images/blocks/3d/broom.png b/assets/images/blocks/3d/broom.png new file mode 100644 index 0000000..a05907a Binary files /dev/null and b/assets/images/blocks/3d/broom.png differ diff --git a/assets/images/blocks/3d/character_down.png b/assets/images/blocks/3d/character_down.png new file mode 100644 index 0000000..d8cc22b Binary files /dev/null and b/assets/images/blocks/3d/character_down.png differ diff --git a/assets/images/blocks/3d/character_left.png b/assets/images/blocks/3d/character_left.png new file mode 100644 index 0000000..88253f4 Binary files /dev/null and b/assets/images/blocks/3d/character_left.png differ diff --git a/assets/images/blocks/3d/character_old.png b/assets/images/blocks/3d/character_old.png new file mode 100644 index 0000000..8059cfc Binary files /dev/null and b/assets/images/blocks/3d/character_old.png differ diff --git a/assets/images/blocks/3d/character_right.png b/assets/images/blocks/3d/character_right.png new file mode 100644 index 0000000..5d6163a Binary files /dev/null and b/assets/images/blocks/3d/character_right.png differ diff --git a/assets/images/blocks/3d/character_up.png b/assets/images/blocks/3d/character_up.png new file mode 100644 index 0000000..4b000c8 Binary files /dev/null and b/assets/images/blocks/3d/character_up.png differ diff --git a/assets/images/blocks/3d/garbagecan.png b/assets/images/blocks/3d/garbagecan.png new file mode 100644 index 0000000..b969172 Binary files /dev/null and b/assets/images/blocks/3d/garbagecan.png differ diff --git a/assets/images/blocks/3d/janitor_room.png b/assets/images/blocks/3d/janitor_room.png new file mode 100644 index 0000000..997fe9c Binary files /dev/null and b/assets/images/blocks/3d/janitor_room.png differ diff --git a/assets/images/blocks/3d/janitor_room_open.png b/assets/images/blocks/3d/janitor_room_open.png new file mode 100644 index 0000000..cac6930 Binary files /dev/null and b/assets/images/blocks/3d/janitor_room_open.png differ diff --git a/assets/images/blocks/3d/robot.png b/assets/images/blocks/3d/robot.png new file mode 100644 index 0000000..0be83c6 Binary files /dev/null and b/assets/images/blocks/3d/robot.png differ diff --git a/assets/images/blocks/3d/scrap.png b/assets/images/blocks/3d/scrap.png new file mode 100644 index 0000000..4d11ca3 Binary files /dev/null and b/assets/images/blocks/3d/scrap.png differ diff --git a/assets/images/blocks/3d/wall.png b/assets/images/blocks/3d/wall.png new file mode 100644 index 0000000..09ce25e Binary files /dev/null and b/assets/images/blocks/3d/wall.png differ diff --git a/assets/images/blocks/3d/wall2.png b/assets/images/blocks/3d/wall2.png new file mode 100644 index 0000000..ac38dc1 Binary files /dev/null and b/assets/images/blocks/3d/wall2.png differ diff --git a/assets/images/blocks/3d/wood_floor.png b/assets/images/blocks/3d/wood_floor.png new file mode 100644 index 0000000..3d3fc08 Binary files /dev/null and b/assets/images/blocks/3d/wood_floor.png differ diff --git a/assets/images/buttons/back.png b/assets/images/buttons/back.png new file mode 100644 index 0000000..36fccda Binary files /dev/null and b/assets/images/buttons/back.png differ diff --git a/assets/images/buttons/back_hover.png b/assets/images/buttons/back_hover.png new file mode 100644 index 0000000..a6b56ab Binary files /dev/null and b/assets/images/buttons/back_hover.png differ diff --git a/assets/images/buttons/help.png b/assets/images/buttons/help.png new file mode 100644 index 0000000..de70eb8 Binary files /dev/null and b/assets/images/buttons/help.png differ diff --git a/assets/images/buttons/help_hover.png b/assets/images/buttons/help_hover.png new file mode 100644 index 0000000..c8624d1 Binary files /dev/null and b/assets/images/buttons/help_hover.png differ diff --git a/assets/images/buttons/mode_2d.png b/assets/images/buttons/mode_2d.png new file mode 100644 index 0000000..7d45388 Binary files /dev/null and b/assets/images/buttons/mode_2d.png differ diff --git a/assets/images/buttons/mode_2d_hover.png b/assets/images/buttons/mode_2d_hover.png new file mode 100644 index 0000000..f2ed7dc Binary files /dev/null and b/assets/images/buttons/mode_2d_hover.png differ diff --git a/assets/images/buttons/mode_3d.png b/assets/images/buttons/mode_3d.png new file mode 100644 index 0000000..10904e6 Binary files /dev/null and b/assets/images/buttons/mode_3d.png differ diff --git a/assets/images/buttons/mode_3d_hover.png b/assets/images/buttons/mode_3d_hover.png new file mode 100644 index 0000000..dbfa4b3 Binary files /dev/null and b/assets/images/buttons/mode_3d_hover.png differ diff --git a/assets/images/buttons/quit.png b/assets/images/buttons/quit.png new file mode 100644 index 0000000..c6e3084 Binary files /dev/null and b/assets/images/buttons/quit.png differ diff --git a/assets/images/buttons/quit_hover.png b/assets/images/buttons/quit_hover.png new file mode 100644 index 0000000..42d1ee8 Binary files /dev/null and b/assets/images/buttons/quit_hover.png differ diff --git a/assets/images/buttons/start.png b/assets/images/buttons/start.png new file mode 100644 index 0000000..a2d7145 Binary files /dev/null and b/assets/images/buttons/start.png differ diff --git a/assets/images/buttons/start_hover.png b/assets/images/buttons/start_hover.png new file mode 100644 index 0000000..8909f21 Binary files /dev/null and b/assets/images/buttons/start_hover.png differ diff --git a/assets/images/cursor1.png b/assets/images/cursor1.png new file mode 100644 index 0000000..4533716 Binary files /dev/null and b/assets/images/cursor1.png differ diff --git a/assets/images/cursor2.png b/assets/images/cursor2.png new file mode 100644 index 0000000..ff387ea Binary files /dev/null and b/assets/images/cursor2.png differ diff --git a/assets/images/help.png b/assets/images/help.png new file mode 100644 index 0000000..465cff0 Binary files /dev/null and b/assets/images/help.png differ diff --git a/assets/images/intro.png b/assets/images/intro.png new file mode 100644 index 0000000..6c79cf7 Binary files /dev/null and b/assets/images/intro.png differ diff --git a/assets/images/levelSelect.png b/assets/images/levelSelect.png new file mode 100644 index 0000000..5b7128c Binary files /dev/null and b/assets/images/levelSelect.png differ diff --git a/assets/images/levelSelectLeft.png b/assets/images/levelSelectLeft.png new file mode 100644 index 0000000..4f36a84 Binary files /dev/null and b/assets/images/levelSelectLeft.png differ diff --git a/assets/images/levelSelectRight.png b/assets/images/levelSelectRight.png new file mode 100644 index 0000000..b870a6f Binary files /dev/null and b/assets/images/levelSelectRight.png differ diff --git a/assets/images/menu.png b/assets/images/menu.png new file mode 100644 index 0000000..e448949 Binary files /dev/null and b/assets/images/menu.png differ diff --git a/assets/images/splash.png b/assets/images/splash.png new file mode 100644 index 0000000..837c978 Binary files /dev/null and b/assets/images/splash.png differ diff --git a/assets/images/winscreen.png b/assets/images/winscreen.png new file mode 100644 index 0000000..c00dbcc Binary files /dev/null and b/assets/images/winscreen.png differ diff --git a/build/levels/level1.map b/assets/levels/level1.map similarity index 100% rename from build/levels/level1.map rename to assets/levels/level1.map diff --git a/build/levels/level2.map b/assets/levels/level2.map similarity index 100% rename from build/levels/level2.map rename to assets/levels/level2.map diff --git a/build/levels/level3.map b/assets/levels/level3.map similarity index 100% rename from build/levels/level3.map rename to assets/levels/level3.map diff --git a/build/levels/level4.map b/assets/levels/level4.map similarity index 100% rename from build/levels/level4.map rename to assets/levels/level4.map diff --git a/build/levels/level5.map b/assets/levels/level5.map similarity index 100% rename from build/levels/level5.map rename to assets/levels/level5.map diff --git a/build/levels/level6.map b/assets/levels/level6.map similarity index 100% rename from build/levels/level6.map rename to assets/levels/level6.map diff --git a/build/levels/level7.map b/assets/levels/level7.map similarity index 100% rename from build/levels/level7.map rename to assets/levels/level7.map diff --git a/build/levels/level8.map b/assets/levels/level8.map similarity index 100% rename from build/levels/level8.map rename to assets/levels/level8.map diff --git a/build/levels/level9.map b/assets/levels/level9.map similarity index 100% rename from build/levels/level9.map rename to assets/levels/level9.map diff --git a/build/sfx/boxhitwall.wav b/assets/sfx/boxhitwall.wav similarity index 100% rename from build/sfx/boxhitwall.wav rename to assets/sfx/boxhitwall.wav diff --git a/build/sfx/boxslide.wav b/assets/sfx/boxslide.wav similarity index 100% rename from build/sfx/boxslide.wav rename to assets/sfx/boxslide.wav diff --git a/build/sfx/click.wav b/assets/sfx/click.wav similarity index 100% rename from build/sfx/click.wav rename to assets/sfx/click.wav diff --git a/build/sfx/door.wav b/assets/sfx/door.wav similarity index 100% rename from build/sfx/door.wav rename to assets/sfx/door.wav diff --git a/build/sfx/explode.wav b/assets/sfx/explode.wav similarity index 100% rename from build/sfx/explode.wav rename to assets/sfx/explode.wav diff --git a/build/sfx/hitwall.wav b/assets/sfx/hitwall.wav similarity index 100% rename from build/sfx/hitwall.wav rename to assets/sfx/hitwall.wav diff --git a/build/sfx/music.ogg b/assets/sfx/music.ogg similarity index 100% rename from build/sfx/music.ogg rename to assets/sfx/music.ogg diff --git a/build/sfx/oof.wav b/assets/sfx/oof.wav similarity index 100% rename from build/sfx/oof.wav rename to assets/sfx/oof.wav diff --git a/build/sfx/sweep.wav b/assets/sfx/sweep.wav similarity index 100% rename from build/sfx/sweep.wav rename to assets/sfx/sweep.wav diff --git a/build/sfx/trash.wav b/assets/sfx/trash.wav similarity index 100% rename from build/sfx/trash.wav rename to assets/sfx/trash.wav diff --git a/build/sfx/winsound.wav b/assets/sfx/winsound.wav similarity index 100% rename from build/sfx/winsound.wav rename to assets/sfx/winsound.wav diff --git a/build/fonts/arial_black.pcx b/build/fonts/arial_black.pcx deleted file mode 100644 index ec27824..0000000 Binary files a/build/fonts/arial_black.pcx and /dev/null differ diff --git a/build/images/background.png b/build/images/background.png deleted file mode 100644 index 7028591..0000000 Binary files a/build/images/background.png and /dev/null differ diff --git a/build/images/blocks/2d/box.png b/build/images/blocks/2d/box.png deleted file mode 100644 index cceecdf..0000000 Binary files a/build/images/blocks/2d/box.png and /dev/null differ diff --git a/build/images/blocks/2d/broom.png b/build/images/blocks/2d/broom.png deleted file mode 100644 index e2a1bcb..0000000 Binary files a/build/images/blocks/2d/broom.png and /dev/null differ diff --git a/build/images/blocks/2d/character.png b/build/images/blocks/2d/character.png deleted file mode 100644 index 52bd7e7..0000000 Binary files a/build/images/blocks/2d/character.png and /dev/null differ diff --git a/build/images/blocks/2d/garbagecan.png b/build/images/blocks/2d/garbagecan.png deleted file mode 100644 index 1d3333c..0000000 Binary files a/build/images/blocks/2d/garbagecan.png and /dev/null differ diff --git a/build/images/blocks/2d/ground.png b/build/images/blocks/2d/ground.png deleted file mode 100644 index ac169c6..0000000 Binary files a/build/images/blocks/2d/ground.png and /dev/null differ diff --git a/build/images/blocks/2d/janitor_room.png b/build/images/blocks/2d/janitor_room.png deleted file mode 100644 index 7c15ae3..0000000 Binary files a/build/images/blocks/2d/janitor_room.png and /dev/null differ diff --git a/build/images/blocks/2d/janitor_room_open.png b/build/images/blocks/2d/janitor_room_open.png deleted file mode 100644 index f3e2eb8..0000000 Binary files a/build/images/blocks/2d/janitor_room_open.png and /dev/null differ diff --git a/build/images/blocks/2d/robot.png b/build/images/blocks/2d/robot.png deleted file mode 100644 index 98aa2eb..0000000 Binary files a/build/images/blocks/2d/robot.png and /dev/null differ diff --git a/build/images/blocks/2d/scrap.png b/build/images/blocks/2d/scrap.png deleted file mode 100644 index 26545a9..0000000 Binary files a/build/images/blocks/2d/scrap.png and /dev/null differ diff --git a/build/images/blocks/2d/wall.png b/build/images/blocks/2d/wall.png deleted file mode 100644 index 53378d2..0000000 Binary files a/build/images/blocks/2d/wall.png and /dev/null differ diff --git a/build/images/blocks/2d/wall2.png b/build/images/blocks/2d/wall2.png deleted file mode 100644 index 7a7cdb9..0000000 Binary files a/build/images/blocks/2d/wall2.png and /dev/null differ diff --git a/build/images/blocks/2d/wood_floor.png b/build/images/blocks/2d/wood_floor.png deleted file mode 100644 index f29dd85..0000000 Binary files a/build/images/blocks/2d/wood_floor.png and /dev/null differ diff --git a/build/images/blocks/3d/box.png b/build/images/blocks/3d/box.png deleted file mode 100644 index 89a68f3..0000000 Binary files a/build/images/blocks/3d/box.png and /dev/null differ diff --git a/build/images/blocks/3d/broom.png b/build/images/blocks/3d/broom.png deleted file mode 100644 index 6eb1ea3..0000000 Binary files a/build/images/blocks/3d/broom.png and /dev/null differ diff --git a/build/images/blocks/3d/character_down.png b/build/images/blocks/3d/character_down.png deleted file mode 100644 index 4eeadeb..0000000 Binary files a/build/images/blocks/3d/character_down.png and /dev/null differ diff --git a/build/images/blocks/3d/character_left.png b/build/images/blocks/3d/character_left.png deleted file mode 100644 index b068f14..0000000 Binary files a/build/images/blocks/3d/character_left.png and /dev/null differ diff --git a/build/images/blocks/3d/character_old.png b/build/images/blocks/3d/character_old.png deleted file mode 100644 index a56c6fd..0000000 Binary files a/build/images/blocks/3d/character_old.png and /dev/null differ diff --git a/build/images/blocks/3d/character_right.png b/build/images/blocks/3d/character_right.png deleted file mode 100644 index 55ed911..0000000 Binary files a/build/images/blocks/3d/character_right.png and /dev/null differ diff --git a/build/images/blocks/3d/character_up.png b/build/images/blocks/3d/character_up.png deleted file mode 100644 index e0a8a89..0000000 Binary files a/build/images/blocks/3d/character_up.png and /dev/null differ diff --git a/build/images/blocks/3d/garbagecan.png b/build/images/blocks/3d/garbagecan.png deleted file mode 100644 index e768ff3..0000000 Binary files a/build/images/blocks/3d/garbagecan.png and /dev/null differ diff --git a/build/images/blocks/3d/janitor_room.png b/build/images/blocks/3d/janitor_room.png deleted file mode 100644 index fb211ac..0000000 Binary files a/build/images/blocks/3d/janitor_room.png and /dev/null differ diff --git a/build/images/blocks/3d/janitor_room_open.png b/build/images/blocks/3d/janitor_room_open.png deleted file mode 100644 index 680acf3..0000000 Binary files a/build/images/blocks/3d/janitor_room_open.png and /dev/null differ diff --git a/build/images/blocks/3d/robot.png b/build/images/blocks/3d/robot.png deleted file mode 100644 index a80618d..0000000 Binary files a/build/images/blocks/3d/robot.png and /dev/null differ diff --git a/build/images/blocks/3d/scrap.png b/build/images/blocks/3d/scrap.png deleted file mode 100644 index c07cb01..0000000 Binary files a/build/images/blocks/3d/scrap.png and /dev/null differ diff --git a/build/images/blocks/3d/wall.png b/build/images/blocks/3d/wall.png deleted file mode 100644 index ce56960..0000000 Binary files a/build/images/blocks/3d/wall.png and /dev/null differ diff --git a/build/images/blocks/3d/wall2.png b/build/images/blocks/3d/wall2.png deleted file mode 100644 index 121075a..0000000 Binary files a/build/images/blocks/3d/wall2.png and /dev/null differ diff --git a/build/images/blocks/3d/wood_floor.png b/build/images/blocks/3d/wood_floor.png deleted file mode 100644 index f29dd85..0000000 Binary files a/build/images/blocks/3d/wood_floor.png and /dev/null differ diff --git a/build/images/buttons/back.png b/build/images/buttons/back.png deleted file mode 100644 index 17abc5e..0000000 Binary files a/build/images/buttons/back.png and /dev/null differ diff --git a/build/images/buttons/back_hover.png b/build/images/buttons/back_hover.png deleted file mode 100644 index 734dad7..0000000 Binary files a/build/images/buttons/back_hover.png and /dev/null differ diff --git a/build/images/buttons/help.png b/build/images/buttons/help.png deleted file mode 100644 index e4740f9..0000000 Binary files a/build/images/buttons/help.png and /dev/null differ diff --git a/build/images/buttons/help_hover.png b/build/images/buttons/help_hover.png deleted file mode 100644 index f9134f9..0000000 Binary files a/build/images/buttons/help_hover.png and /dev/null differ diff --git a/build/images/buttons/mode_2d.png b/build/images/buttons/mode_2d.png deleted file mode 100644 index 2a69481..0000000 Binary files a/build/images/buttons/mode_2d.png and /dev/null differ diff --git a/build/images/buttons/mode_2d_hover.png b/build/images/buttons/mode_2d_hover.png deleted file mode 100644 index ae356e8..0000000 Binary files a/build/images/buttons/mode_2d_hover.png and /dev/null differ diff --git a/build/images/buttons/mode_3d.png b/build/images/buttons/mode_3d.png deleted file mode 100644 index 0648d99..0000000 Binary files a/build/images/buttons/mode_3d.png and /dev/null differ diff --git a/build/images/buttons/mode_3d_hover.png b/build/images/buttons/mode_3d_hover.png deleted file mode 100644 index abf58e4..0000000 Binary files a/build/images/buttons/mode_3d_hover.png and /dev/null differ diff --git a/build/images/buttons/quit.png b/build/images/buttons/quit.png deleted file mode 100644 index f48ecd4..0000000 Binary files a/build/images/buttons/quit.png and /dev/null differ diff --git a/build/images/buttons/quit_hover.png b/build/images/buttons/quit_hover.png deleted file mode 100644 index 07ad784..0000000 Binary files a/build/images/buttons/quit_hover.png and /dev/null differ diff --git a/build/images/buttons/start.png b/build/images/buttons/start.png deleted file mode 100644 index 8bb295b..0000000 Binary files a/build/images/buttons/start.png and /dev/null differ diff --git a/build/images/buttons/start_hover.png b/build/images/buttons/start_hover.png deleted file mode 100644 index ef3bd1d..0000000 Binary files a/build/images/buttons/start_hover.png and /dev/null differ diff --git a/build/images/cursor1.png b/build/images/cursor1.png deleted file mode 100644 index e9a0443..0000000 Binary files a/build/images/cursor1.png and /dev/null differ diff --git a/build/images/cursor2.png b/build/images/cursor2.png deleted file mode 100644 index b6ec4c3..0000000 Binary files a/build/images/cursor2.png and /dev/null differ diff --git a/build/images/help.png b/build/images/help.png deleted file mode 100644 index f9f735f..0000000 Binary files a/build/images/help.png and /dev/null differ diff --git a/build/images/intro.png b/build/images/intro.png deleted file mode 100644 index 567a0a1..0000000 Binary files a/build/images/intro.png and /dev/null differ diff --git a/build/images/levelSelect.png b/build/images/levelSelect.png deleted file mode 100644 index 2072e9a..0000000 Binary files a/build/images/levelSelect.png and /dev/null differ diff --git a/build/images/levelSelectLeft.png b/build/images/levelSelectLeft.png deleted file mode 100644 index d29fb6e..0000000 Binary files a/build/images/levelSelectLeft.png and /dev/null differ diff --git a/build/images/levelSelectRight.png b/build/images/levelSelectRight.png deleted file mode 100644 index db55ece..0000000 Binary files a/build/images/levelSelectRight.png and /dev/null differ diff --git a/build/images/menu.png b/build/images/menu.png deleted file mode 100644 index 8498e99..0000000 Binary files a/build/images/menu.png and /dev/null differ diff --git a/build/images/splash.png b/build/images/splash.png deleted file mode 100644 index a9b11eb..0000000 Binary files a/build/images/splash.png and /dev/null differ diff --git a/build/images/winscreen.png b/build/images/winscreen.png deleted file mode 100644 index 624f97f..0000000 Binary files a/build/images/winscreen.png and /dev/null differ diff --git a/build/changelog.txt b/changelog.txt similarity index 100% rename from build/changelog.txt rename to changelog.txt diff --git a/index.html b/index.html new file mode 100644 index 0000000..62b50a1 --- /dev/null +++ b/index.html @@ -0,0 +1,42 @@ + + + + Mazes + + + + + + + + + + + + {{{ SCRIPT }}} + + diff --git a/src/block.cpp b/src/block.cpp index 53fa1c9..bcbb9a7 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -1,22 +1,8 @@ #include "block.h" -#include - -Block::Block() - : x(0), y(0), type(0), frame(0), selected(false), sound(nullptr) { - images[0] = nullptr; - images[1] = nullptr; -} - -Block::~Block() { - destroy_bitmap(images[0]); - destroy_bitmap(images[1]); - destroy_sample(sound); -} - -void Block::SetImages(const char* image1, const char* image2) { - images[0] = load_png(image1, nullptr); - images[1] = load_png(image2, nullptr); +void Block::SetImages(const std::string& path1, const std::string& path2) { + images[0] = asw::assets::loadTexture(path1); + images[1] = asw::assets::loadTexture(path2); } int Block::GetX() const { @@ -35,18 +21,12 @@ void Block::SetY(int newValue) { y = newValue; } -void Block::draw(BITMAP* buffer) { - if (frame == 0 || frame == 1 || frame == 2 || frame == 3 || frame == 4) { - frame += 1; - draw_sprite(buffer, images[0], GetX(), GetY()); - } else if (frame == 5 || frame == 6 || frame == 7 || frame == 8 || - frame == 9 || frame == 10 || frame == 11 || frame == 12 || - frame == 13 || frame == 14 || frame == 15) { - frame += 1; - draw_sprite(buffer, images[1], GetX(), GetY()); - - if (frame == 16) { - frame = 0; - } +void Block::draw() { + if (frame <= 4) { + asw::draw::sprite(images[0], asw::Vec2(x, y)); + } else { + asw::draw::sprite(images[1], asw::Vec2(x, y)); } + + frame += (frame + 1) % 16; } diff --git a/src/block.h b/src/block.h index 67b4ce2..fd4c2c0 100644 --- a/src/block.h +++ b/src/block.h @@ -1,14 +1,14 @@ -#ifndef BLOCK_H -#define BLOCK_H +#pragma once -#include +#include +#include +#include class Block { public: - Block(); - ~Block(); + Block() = default; - void SetImages(const char* image1, const char* image2); + void SetImages(const std::string& path1, const std::string& path2); int GetY() const; int GetX() const; @@ -16,19 +16,14 @@ class Block { void SetX(int newValue); void SetY(int newValue); - void draw(BITMAP* buffer); + void draw(); private: - int x, y; + int x{0}; + int y{0}; - int type; + int frame{0}; - int frame; - - bool selected; - - BITMAP* images[2]; - SAMPLE* sound; + std::array images; + asw::Sample sound; }; - -#endif diff --git a/src/button.cpp b/src/button.cpp index dce82e3..8b58f20 100644 --- a/src/button.cpp +++ b/src/button.cpp @@ -1,22 +1,16 @@ #include "button.h" -#include +#include -Button::Button() : x(0), y(0), width(520), height(120) { - images[0] = nullptr; - images[1] = nullptr; -} - -Button::~Button() {} - -void Button::SetImages(const char* image1, const char* image2) { - images[0] = load_png(image1, nullptr); - images[1] = load_png(image2, nullptr); +void Button::SetImages(const std::string& image1, const std::string& image2) { + images[0] = asw::assets::loadTexture(image1); + images[1] = asw::assets::loadTexture(image2); } bool Button::Hover() const { - return (mouse_x > GetX() && mouse_x < GetX() + width && mouse_y > GetY() && - mouse_y < GetY() + height); + return ( + asw::input::mouse.x > GetX() && asw::input::mouse.x < GetX() + width && + asw::input::mouse.y > GetY() && asw::input::mouse.y < GetY() + height); } void Button::SetX(int newValue) { @@ -35,6 +29,7 @@ int Button::GetY() const { return y; } -void Button::draw(BITMAP* tempBitmap) { - draw_sprite(tempBitmap, images[Hover()], GetX(), GetY()); +void Button::draw() { + auto frame = Hover() ? 1 : 0; + asw::draw::sprite(images[frame], asw::Vec2(x, y)); } diff --git a/src/button.h b/src/button.h index a050321..f8f85b6 100644 --- a/src/button.h +++ b/src/button.h @@ -1,16 +1,16 @@ -#ifndef BUTTON_H -#define BUTTON_H +#pragma once -#include +#include +#include +#include class Button { public: - Button(); - ~Button(); + Button() = default; - void SetImages(const char* image1, const char* image2); + void SetImages(const std::string& image1, const std::string& image2); - void draw(BITMAP* tempBitmap); + void draw(); void SetX(int newValue); void SetY(int newValue); @@ -24,10 +24,10 @@ class Button { int GetY() const; private: - int x, y; - int width, height; + int x{0}; + int y{0}; + int width{520}; + int height{120}; - BITMAP* images[2]; + std::array images; }; - -#endif diff --git a/src/id.h b/src/id.h index c1c62df..20e92c3 100644 --- a/src/id.h +++ b/src/id.h @@ -1,12 +1,24 @@ // MATERIAL TYPES -#define AIR 0 -#define SOLID 1 -#define PUSHABLE 2 -#define ENEMY 3 +constexpr int AIR = 0; +constexpr int SOLID = 1; +constexpr int PUSHABLE = 2; +constexpr int ENEMY = 3; // DIRECTIONS -#define NONE 0 -#define LEFT 1 -#define RIGHT 2 -#define UP 3 -#define DOWN 4 +constexpr int NONE = 0; +constexpr int LEFT = 1; +constexpr int RIGHT = 2; +constexpr int UP = 3; +constexpr int DOWN = 4; + +// TILE VALUES +constexpr int V_EMPTY = 0; +constexpr int V_ROBOT = 1; +constexpr int V_BOX = 2; +constexpr int V_SCRAP = 3; +constexpr int V_GROUND = 4; +constexpr int V_WALL = 5; +constexpr int V_GARBAGECAN = 6; +constexpr int V_JANITORROOM = 7; +constexpr int V_WALL2 = 8; +constexpr int V_JANITORROOMOPEN = 9; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7512f18..25ce15a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,18 +4,14 @@ * Mazes Main */ -#include -#include -#include - -#include +#include +#include +#include +#include #include #include #include -#include "rapidxml/rapidxml.hpp" -#include "rapidxml/rapidxml_print.hpp" - #include "button.h" #include "id.h" @@ -27,12 +23,8 @@ Button mode; Button back; // Fonts -FONT *f1, *f2, *f3, *f4, *f5; - -// Menu -int selectorY, selectorX, newSelectorY, selected_object; -int cursor_x, cursor_y; -int menu_view_x, menu_view_y; +asw::Font font; +bool helpOpen = false; // Creates integers int lives; @@ -51,7 +43,6 @@ bool doneLevel; bool mousePressed; bool moving; int gameScreen; -bool exitGame; std::string levelText; @@ -109,44 +100,43 @@ int map[24][32] = {{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}}; // Define bitmaps -BITMAP* buffer; -BITMAP* character[4]; -BITMAP* background; -BITMAP* robot; -BITMAP* wall; -BITMAP* fakeWall; -BITMAP* ground; -BITMAP* box; -BITMAP* menu; -BITMAP* help_menu; -BITMAP* cursor[2]; -BITMAP* levelSelect; -BITMAP* levelSelectLeft; -BITMAP* levelSelectRight; -BITMAP* winscreen; -BITMAP* intro; -BITMAP* splash; - -BITMAP* scrap; -BITMAP* broom; -BITMAP* garbagecan; -BITMAP* janitorroom; -BITMAP* janitorroomopen; -BITMAP* wall2; -BITMAP* wood_floor; +asw::Texture character[4]; +asw::Texture background; +asw::Texture robot; +asw::Texture wall; +asw::Texture fakeWall; +asw::Texture ground; +asw::Texture box; +asw::Texture menu; +asw::Texture help_menu; +asw::Texture cursor[2]; +asw::Texture levelSelect; +asw::Texture levelSelectLeft; +asw::Texture levelSelectRight; +asw::Texture winscreen; +asw::Texture intro; +asw::Texture splash; + +asw::Texture scrap; +asw::Texture broom; +asw::Texture garbagecan; +asw::Texture janitorroom; +asw::Texture janitorroomopen; +asw::Texture wall2; +asw::Texture wood_floor; // Define sound effects -SAMPLE* song; -SAMPLE* hitwall; -SAMPLE* boxhitwall; -SAMPLE* boxslide; -SAMPLE* explode; -SAMPLE* sweep; -SAMPLE* trash; -SAMPLE* oof; -SAMPLE* winsound; -SAMPLE* door; -SAMPLE* click; +asw::Music song; +asw::Sample hitwall; +asw::Sample boxhitwall; +asw::Sample boxslide; +asw::Sample explode; +asw::Sample sweep; +asw::Sample trash; +asw::Sample oof; +asw::Sample winsound; +asw::Sample door; +asw::Sample click; void restart(); void update(); @@ -160,7 +150,7 @@ clock_t currentTime; // Tiles on screen struct tile { - BITMAP* image[2]; + std::array image; int value; int type; int dir; @@ -195,57 +185,10 @@ bool collision(int xMin1, return false; } -void highcolor_fade_in(BITMAP* bmp_orig, int speed) { - BITMAP* bmp_buff; - - if ((bmp_buff = create_bitmap(SCREEN_W, SCREEN_H))) { - int a; - - if (speed <= 0) - speed = 16; - - for (a = 0; a < 256; a += speed) { - clear(bmp_buff); - set_trans_blender(0, 0, 0, a); - draw_trans_sprite(bmp_buff, bmp_orig, 0, 0); - vsync(); - blit(bmp_buff, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); - } - - destroy_bitmap(bmp_buff); - } - - blit(bmp_orig, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); -} - -void highcolor_fade_out(int speed) { - BITMAP* bmp_orig; - - if ((bmp_orig = create_bitmap(SCREEN_W, SCREEN_H))) { - BITMAP* bmp_buff; - - if ((bmp_buff = create_bitmap(SCREEN_W, SCREEN_H))) { - int a; - blit(screen, bmp_orig, 0, 0, 0, 0, SCREEN_W, SCREEN_H); - - if (speed <= 0) - speed = 16; - - for (a = 255 - speed; a > 0; a -= speed) { - clear(bmp_buff); - set_trans_blender(0, 0, 0, a); - draw_trans_sprite(bmp_buff, bmp_orig, 0, 0); - vsync(); - blit(bmp_buff, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); - } - - destroy_bitmap(bmp_buff); - } - - destroy_bitmap(bmp_orig); +void rest(int ms) { + clock_t endTime = clock() + ms; + while (clock() < endTime) { } - - rectfill(screen, 0, 0, SCREEN_W, SCREEN_H, makecol(0, 0, 0)); } void setupGame(bool first) { @@ -260,82 +203,97 @@ void setupGame(bool first) { gameScreen = 0; currentLevel = 1; score = 0; - buffer = create_bitmap(1280, 960); - exitGame = false; levelText = ""; if (perspective == 0) { - character[0] = load_png("images/blocks/3d/character_down.png", nullptr); - character[1] = load_png("images/blocks/3d/character_up.png", nullptr); - character[2] = load_png("images/blocks/3d/character_left.png", nullptr); - character[3] = load_png("images/blocks/3d/character_right.png", nullptr); - - wall = load_png("images/blocks/3d/wall.png", nullptr); - wall2 = load_png("images/blocks/3d/wall2.png", nullptr); - robot = load_png("images/blocks/3d/robot.png", nullptr); - box = load_png("images/blocks/3d/box.png", nullptr); - scrap = load_png("images/blocks/3d/scrap.png", nullptr); - broom = load_png("images/blocks/3d/broom.png", nullptr); - garbagecan = load_png("images/blocks/3d/garbagecan.png", nullptr); - janitorroom = load_png("images/blocks/3d/janitor_room.png", nullptr); - janitorroomopen = - load_png("images/blocks/3d/janitor_room_open.png", nullptr); - wood_floor = load_png("images/blocks/3d/wood_floor.png", nullptr); + character[0] = asw::assets::loadTexture( + "assets/images/blocks/3d/character_down.png"); + character[1] = + asw::assets::loadTexture("assets/images/blocks/3d/character_up.png"); + character[2] = asw::assets::loadTexture( + "assets/images/blocks/3d/character_left.png"); + character[3] = asw::assets::loadTexture( + "assets/images/blocks/3d/character_right.png"); + + wall = asw::assets::loadTexture("assets/images/blocks/3d/wall.png"); + wall2 = asw::assets::loadTexture("assets/images/blocks/3d/wall2.png"); + robot = asw::assets::loadTexture("assets/images/blocks/3d/robot.png"); + box = asw::assets::loadTexture("assets/images/blocks/3d/box.png"); + scrap = asw::assets::loadTexture("assets/images/blocks/3d/scrap.png"); + broom = asw::assets::loadTexture("assets/images/blocks/3d/broom.png"); + garbagecan = + asw::assets::loadTexture("assets/images/blocks/3d/garbagecan.png"); + janitorroom = + asw::assets::loadTexture("assets/images/blocks/3d/janitor_room.png"); + janitorroomopen = asw::assets::loadTexture( + "assets/images/blocks/3d/janitor_room_open.png"); + wood_floor = + asw::assets::loadTexture("assets/images/blocks/3d/wood_floor.png"); } if (perspective == 1) { - character[0] = load_png("images/blocks/2d/character.png", nullptr); - character[1] = load_png("images/blocks/2d/character.png", nullptr); - character[2] = load_png("images/blocks/2d/character.png", nullptr); - character[3] = load_png("images/blocks/2d/character.png", nullptr); - - wall = load_png("images/blocks/2d/wall.png", nullptr); - wall2 = load_png("images/blocks/2d/wall2.png", nullptr); - robot = load_png("images/blocks/2d/robot.png", nullptr); - box = load_png("images/blocks/2d/box.png", nullptr); - scrap = load_png("images/blocks/2d/scrap.png", nullptr); - broom = load_png("images/blocks/2d/broom.png", nullptr); - garbagecan = load_png("images/blocks/2d/garbagecan.png", nullptr); - janitorroom = load_png("images/blocks/2d/janitor_room.png", nullptr); - janitorroomopen = - load_png("images/blocks/2d/janitor_room_open.png", nullptr); - wood_floor = load_png("images/blocks/2d/wood_floor.png", nullptr); + character[0] = + asw::assets::loadTexture("assets/images/blocks/2d/character.png"); + character[1] = + asw::assets::loadTexture("assets/images/blocks/2d/character.png"); + character[2] = + asw::assets::loadTexture("assets/images/blocks/2d/character.png"); + character[3] = + asw::assets::loadTexture("assets/images/blocks/2d/character.png"); + + wall = asw::assets::loadTexture("assets/images/blocks/2d/wall.png"); + wall2 = asw::assets::loadTexture("assets/images/blocks/2d/wall2.png"); + robot = asw::assets::loadTexture("assets/images/blocks/2d/robot.png"); + box = asw::assets::loadTexture("assets/images/blocks/2d/box.png"); + scrap = asw::assets::loadTexture("assets/images/blocks/2d/scrap.png"); + broom = asw::assets::loadTexture("assets/images/blocks/2d/broom.png"); + garbagecan = + asw::assets::loadTexture("assets/images/blocks/2d/garbagecan.png"); + janitorroom = + asw::assets::loadTexture("assets/images/blocks/2d/janitor_room.png"); + janitorroomopen = asw::assets::loadTexture( + "assets/images/blocks/2d/janitor_room_open.png"); + wood_floor = + asw::assets::loadTexture("assets/images/blocks/2d/wood_floor.png"); } - menu = load_png("images/menu.png", nullptr); - background = load_png("images/background.png", nullptr); - help_menu = load_png("images/help.png", nullptr); - intro = load_png("images/intro.png", nullptr); - splash = load_png("images/splash.png", nullptr); - winscreen = load_png("images/winscreen.png", nullptr); - levelSelect = load_png("images/levelSelect.png", nullptr); - levelSelectLeft = load_png("images/levelSelectLeft.png", nullptr); - levelSelectRight = load_png("images/levelSelectRight.png", nullptr); + menu = asw::assets::loadTexture("assets/images/menu.png"); + background = asw::assets::loadTexture("assets/images/background.png"); + help_menu = asw::assets::loadTexture("assets/images/help.png"); + intro = asw::assets::loadTexture("assets/images/intro.png"); + splash = asw::assets::loadTexture("assets/images/splash.png"); + winscreen = asw::assets::loadTexture("assets/images/winscreen.png"); + levelSelect = asw::assets::loadTexture("assets/images/levelSelect.png"); + levelSelectLeft = + asw::assets::loadTexture("assets/images/levelSelectLeft.png"); + levelSelectRight = + asw::assets::loadTexture("assets/images/levelSelectRight.png"); // Sounds and music - sweep = load_sample("sfx/sweep.wav"); - explode = load_sample("sfx/explode.wav"); - trash = load_sample("sfx/trash.wav"); - oof = load_sample("sfx/oof.wav"); - winsound = load_sample("sfx/winsound.wav"); - door = load_sample("sfx/door.wav"); - hitwall = load_sample("sfx/hitwall.wav"); - boxhitwall = load_sample("sfx/boxhitwall.wav"); - boxslide = load_sample("sfx/boxslide.wav"); - click = load_sample("sfx/click.wav"); - - song = logg_load("sfx/music.ogg"); - - srand(time(nullptr)); + sweep = asw::assets::loadSample("assets/sfx/sweep.wav"); + explode = asw::assets::loadSample("assets/sfx/explode.wav"); + trash = asw::assets::loadSample("assets/sfx/trash.wav"); + oof = asw::assets::loadSample("assets/sfx/oof.wav"); + winsound = asw::assets::loadSample("assets/sfx/winsound.wav"); + door = asw::assets::loadSample("assets/sfx/door.wav"); + hitwall = asw::assets::loadSample("assets/sfx/hitwall.wav"); + boxhitwall = asw::assets::loadSample("assets/sfx/boxhitwall.wav"); + boxslide = asw::assets::loadSample("assets/sfx/boxslide.wav"); + click = asw::assets::loadSample("assets/sfx/click.wav"); + + song = asw::assets::loadMusic("assets/sfx/music.ogg"); // Sets button images - start.SetImages("images/buttons/start.png", - "images/buttons/start_hover.png"); - help.SetImages("images/buttons/help.png", "images/buttons/help_hover.png"); - quit.SetImages("images/buttons/quit.png", "images/buttons/quit_hover.png"); - mode.SetImages("images/buttons/mode_3d.png", - "images/buttons/mode_3d_hover.png"); - back.SetImages("images/buttons/back.png", "images/buttons/back_hover.png"); + start.SetImages("assets/images/buttons/start.png", + "assets/images/buttons/start_hover.png"); + help.SetImages("assets/images/buttons/help.png", + "assets/images/buttons/help_hover.png"); + quit.SetImages("assets/images/buttons/quit.png", + "assets/images/buttons/quit_hover.png"); + mode.SetImages("assets/images/buttons/mode_3d.png", + "assets/images/buttons/mode_3d_hover.png"); + back.SetImages("assets/images/buttons/back.png", + "assets/images/buttons/back_hover.png"); // Sets button positions start.SetX(380); @@ -350,34 +308,17 @@ void setupGame(bool first) { mode.SetY(660); back.SetY(40); - // Sets Cursors - cursor[0] = load_png("images/cursor1.png", nullptr); - cursor[1] = load_png("images/cursor2.png", nullptr); - // Sets time startTime = clock(); currentTime = clock(); // Sets Font - f1 = load_font("fonts/arial_black.pcx", nullptr, nullptr); - f2 = extract_font_range(f1, ' ', 'A' - 1); - f3 = extract_font_range(f1, 'A', 'Z'); - f4 = extract_font_range(f1, 'Z' + 1, 'z'); - - // Merge fonts - font = merge_fonts(f4, f5 = merge_fonts(f2, f3)); - - // Destroy temporary fonts - destroy_font(f1); - destroy_font(f2); - destroy_font(f3); - destroy_font(f4); - destroy_font(f5); + font = asw::assets::loadFont("assets/fonts/dosis.ttf", 16); } // Background Music if (first) { - play_sample(song, 255, 128, 1000, 1); + asw::sound::playMusic(song, 255); } } @@ -391,49 +332,49 @@ void resetBlocks(int newI, int newT) { t = newT; } - if (tiles[i][t].value == 0) { - tiles[i][t].image[0] = NULL; - tiles[i][t].image[1] = NULL; + if (tiles[i][t].value == V_EMPTY) { + tiles[i][t].image[0] = nullptr; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = AIR; - } else if (tiles[i][t].value == 1) { + } else if (tiles[i][t].value == V_ROBOT) { tiles[i][t].image[0] = robot; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = ENEMY; - } else if (tiles[i][t].value == 2) { + } else if (tiles[i][t].value == V_BOX) { tiles[i][t].image[0] = box; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = PUSHABLE; - } else if (tiles[i][t].value == 3) { + } else if (tiles[i][t].value == V_SCRAP) { tiles[i][t].image[0] = scrap; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = SOLID; - } else if (tiles[i][t].value == 4) { - tiles[i][t].image[0] = NULL; - tiles[i][t].image[1] = NULL; + } else if (tiles[i][t].value == V_GROUND) { + tiles[i][t].image[0] = nullptr; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = AIR; - } else if (tiles[i][t].value == 5) { + } else if (tiles[i][t].value == V_WALL) { tiles[i][t].image[0] = wall; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = SOLID; - } else if (tiles[i][t].value == 6) { + } else if (tiles[i][t].value == V_GARBAGECAN) { tiles[i][t].image[0] = garbagecan; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = SOLID; - } else if (tiles[i][t].value == 7) { + } else if (tiles[i][t].value == V_JANITORROOM) { tiles[i][t].image[0] = janitorroom; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = SOLID; - } else if (tiles[i][t].value == 8) { + } else if (tiles[i][t].value == V_WALL2) { tiles[i][t].image[0] = wall2; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = SOLID; - } else if (tiles[i][t].value == 9) { + } else if (tiles[i][t].value == V_JANITORROOMOPEN) { tiles[i][t].image[0] = janitorroomopen; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = SOLID; } else { - tiles[i][t].image[0] = NULL; - tiles[i][t].image[1] = NULL; + tiles[i][t].image[0] = nullptr; + tiles[i][t].image[1] = nullptr; tiles[i][t].type = AIR; } @@ -450,7 +391,8 @@ void resetBlocks(int newI, int newT) { // Controls Character Movements void charactermove() { - if (key[KEY_UP] || key[KEY_W] || joy[0].stick[0].axis[1].d1) { + if (asw::input::wasKeyPressed(asw::input::Key::UP) || + asw::input::wasKeyPressed(asw::input::Key::W)) { characterRotation = 128; if (tiles[y / 40 - 1][x / 40].type == AIR) { @@ -459,211 +401,217 @@ void charactermove() { tiles[y / 40 - 1][x / 40].value != 7 && tiles[y / 40 - 1][x / 40].value != 9 && tiles[y / 40 - 1][x / 40].value != 3) { - play_sample(hitwall, 255, 122, 1000, 0); + asw::sound::play(hitwall, 255, 122, 0); } else if (tiles[y / 40 - 1][x / 40].type == PUSHABLE && tiles[y / 40 - 2][x / 40].type == AIR) { - play_sample(boxslide, 255, 122, 1000, 0); + asw::sound::play(boxslide, 255, 122, 0); tiles[y / 40 - 2][x / 40].value = tiles[y / 40 - 1][x / 40].value; - tiles[y / 40 - 1][x / 40].value = 0; + tiles[y / 40 - 1][x / 40].value = V_EMPTY; y -= 40; } else if (tiles[y / 40 - 1][x / 40].type == PUSHABLE && tiles[y / 40 - 2][x / 40].type != AIR) { if (tiles[y / 40 - 2][x / 40].type == ENEMY) { - play_sample(explode, 255, 122, 1000, 0); - tiles[y / 40 - 2][x / 40].value = 3; + asw::sound::play(explode, 255, 122, 0); + tiles[y / 40 - 2][x / 40].value = V_SCRAP; score += 100; } else { - play_sample(boxhitwall, 255, 122, 1000, 0); + asw::sound::play(boxhitwall, 255, 122, 0); } - } else if (key[KEY_SPACE] && tiles[y / 40 - 1][x / 40].value == 3 && - haveBroom) { + } else if (asw::input::isKeyDown(asw::input::Key::SPACE) && + tiles[y / 40 - 1][x / 40].value == V_SCRAP && haveBroom) { if (tiles[y / 40 - 2][x / 40].type == AIR) { tiles[y / 40 - 2][x / 40].value = tiles[y / 40 - 1][x / 40].value; - tiles[y / 40 - 1][x / 40].value = 0; - } else if (tiles[y / 40 - 2][x / 40].value == 6) { + tiles[y / 40 - 1][x / 40].value = V_EMPTY; + } else if (tiles[y / 40 - 2][x / 40].value == V_GARBAGECAN) { score += 50; if (robotsLeft > 0) { robotsLeft -= 1; } - play_sample(trash, 255, 122, 1000, 0); - tiles[y / 40 - 1][x / 40].value = 0; + asw::sound::play(trash, 255, 122, 0); + tiles[y / 40 - 1][x / 40].value = V_EMPTY; } - play_sample(sweep, 1000, 122, 1000, 0); - } else if (tiles[y / 40 - 1][x / 40].value == 7) { + asw::sound::play(sweep, 1000, 122, 0); + } else if (tiles[y / 40 - 1][x / 40].value == V_JANITORROOM) { if (!haveBroom) { - tiles[y / 40 - 1][x / 40].value = 9; - play_sample(door, 255, 122, 1000, 0); + tiles[y / 40 - 1][x / 40].value = V_JANITORROOMOPEN; + asw::sound::play(door, 255, 122, 0); haveBroom = true; } - } else if (tiles[y / 40 - 1][x / 40].value == 9) { + } else if (tiles[y / 40 - 1][x / 40].value == V_JANITORROOMOPEN) { if (robotsLeft == 0) { doneLevel = 1; } } } - if (key[KEY_DOWN] || key[KEY_S] || joy[0].stick[0].axis[1].d2) { + if (asw::input::wasKeyPressed(asw::input::Key::DOWN) || + asw::input::wasKeyPressed(asw::input::Key::S)) { characterRotation = 0; - if (tiles[y / 40 + 1][x / 40].value == 0 || - tiles[y / 40 + 1][x / 40].value == 8) { + if (tiles[y / 40 + 1][x / 40].value == V_EMPTY || + tiles[y / 40 + 1][x / 40].value == V_WALL2) { y = y + 40; - } else if (tiles[y / 40 + 1][x / 40].value == 5) { - play_sample(hitwall, 255, 122, 1000, 0); - } else if (tiles[y / 40 + 1][x / 40].value == 2 && - tiles[y / 40 + 2][x / 40].value == 0) { - play_sample(boxslide, 255, 122, 1000, 0); - tiles[y / 40 + 1][x / 40].value = 0; - tiles[y / 40 + 2][x / 40].value = 2; + } else if (tiles[y / 40 + 1][x / 40].value == V_WALL) { + asw::sound::play(hitwall, 255, 122, 0); + } else if (tiles[y / 40 + 1][x / 40].value == V_BOX && + tiles[y / 40 + 2][x / 40].value == V_EMPTY) { + asw::sound::play(boxslide, 255, 122, 0); + tiles[y / 40 + 1][x / 40].value = V_EMPTY; + tiles[y / 40 + 2][x / 40].value = V_BOX; y = y + 40; - } else if (tiles[y / 40 + 1][x / 40].value == 2 && + } else if (tiles[y / 40 + 1][x / 40].value == V_BOX && tiles[y / 40 + 2][x / 40].value != 0) { - if (tiles[y / 40 + 1][x / 40].value == 2 && - tiles[y / 40 + 2][x / 40].value == 1) { - play_sample(explode, 255, 122, 1000, 0); - tiles[y / 40 + 2][x / 40].value = 3; + if (tiles[y / 40 + 1][x / 40].value == V_BOX && + tiles[y / 40 + 2][x / 40].value == V_ROBOT) { + asw::sound::play(explode, 255, 122, 0); + tiles[y / 40 + 2][x / 40].value = V_SCRAP; score += 100; } else { - play_sample(boxhitwall, 255, 122, 1000, 0); + asw::sound::play(boxhitwall, 255, 122, 0); } - } else if (tiles[y / 40 + 1][x / 40].value == 3 && - tiles[y / 40 + 2][x / 40].value == 0 && haveBroom == 1 && - (key[KEY_SPACE] || joy[0].button[0].b)) { - tiles[y / 40 + 1][x / 40].value = 0; - tiles[y / 40 + 2][x / 40].value = 3; - play_sample(sweep, 1000, 122, 1000, 0); - } else if (tiles[y / 40 + 1][x / 40].value == 3 && - tiles[y / 40 + 2][x / 40].value == 6 && haveBroom == 1 && - (key[KEY_SPACE] || joy[0].button[0].b)) { - tiles[y / 40 + 1][x / 40].value = 0; + } else if (tiles[y / 40 + 1][x / 40].value == V_SCRAP && + tiles[y / 40 + 2][x / 40].value == V_EMPTY && haveBroom == 1 && + asw::input::isKeyDown(asw::input::Key::SPACE)) { + tiles[y / 40 + 1][x / 40].value = V_EMPTY; + tiles[y / 40 + 2][x / 40].value = V_SCRAP; + asw::sound::play(sweep, 1000, 122, 0); + } else if (tiles[y / 40 + 1][x / 40].value == V_SCRAP && + tiles[y / 40 + 2][x / 40].value == V_GARBAGECAN && + haveBroom == 1 && + asw::input::isKeyDown(asw::input::Key::SPACE)) { + tiles[y / 40 + 1][x / 40].value = V_EMPTY; score += 50; if (robotsLeft > 0) { robotsLeft -= 1; } - play_sample(sweep, 1000, 122, 1000, 0); - play_sample(trash, 255, 122, 1000, 0); - } else if (tiles[y / 40 + 1][x / 40].value == 7) { + asw::sound::play(sweep, 1000, 122, 0); + asw::sound::play(trash, 255, 122, 0); + } else if (tiles[y / 40 + 1][x / 40].value == V_JANITORROOM) { if (!haveBroom) { - tiles[y / 40 + 1][x / 40].value = 9; - play_sample(door, 255, 122, 1000, 0); + tiles[y / 40 + 1][x / 40].value = V_JANITORROOMOPEN; + asw::sound::play(door, 255, 122, 0); haveBroom = true; } - } else if (tiles[y / 40 + 1][x / 40].value == 9) { + } else if (tiles[y / 40 + 1][x / 40].value == V_JANITORROOMOPEN) { if (robotsLeft == 0) { doneLevel = 1; } } } - if (key[KEY_LEFT] || key[KEY_A] || joy[0].stick[0].axis[0].d1) { + if (asw::input::wasKeyPressed(asw::input::Key::LEFT) || + asw::input::wasKeyPressed(asw::input::Key::A)) { characterRotation = 64; - if (tiles[y / 40][x / 40 - 1].value == 0 || - tiles[y / 40][x / 40 - 1].value == 8) { + if (tiles[y / 40][x / 40 - 1].value == V_EMPTY || + tiles[y / 40][x / 40 - 1].value == V_WALL2) { x = x - 40; - } else if (tiles[y / 40][x / 40 - 1].value == 5) { - play_sample(hitwall, 255, 122, 1000, 0); - } else if (tiles[y / 40][x / 40 - 1].value == 2 && - tiles[y / 40][x / 40 - 2].value == 0) { - play_sample(boxslide, 255, 122, 1000, 0); - tiles[y / 40][x / 40 - 1].value = 0; - tiles[y / 40][x / 40 - 2].value = 2; + } else if (tiles[y / 40][x / 40 - 1].value == V_WALL) { + asw::sound::play(hitwall, 255, 122, 0); + } else if (tiles[y / 40][x / 40 - 1].value == V_BOX && + tiles[y / 40][x / 40 - 2].value == V_EMPTY) { + asw::sound::play(boxslide, 255, 122, 0); + tiles[y / 40][x / 40 - 1].value = V_EMPTY; + tiles[y / 40][x / 40 - 2].value = V_BOX; x = x - 40; - } else if (tiles[y / 40][x / 40 - 1].value == 2 && + } else if (tiles[y / 40][x / 40 - 1].value == V_BOX && tiles[y / 40][x / 40 - 2].value != 0) { - if (tiles[y / 40][x / 40 - 1].value == 2 && - tiles[y / 40][x / 40 - 2].value == 1) { - play_sample(explode, 255, 122, 1000, 0); - tiles[y / 40][x / 40 - 2].value = 3; + if (tiles[y / 40][x / 40 - 1].value == V_BOX && + tiles[y / 40][x / 40 - 2].value == V_ROBOT) { + asw::sound::play(explode, 255, 122, 0); + tiles[y / 40][x / 40 - 2].value = V_SCRAP; score += 100; } else { - play_sample(boxhitwall, 255, 122, 1000, 0); + asw::sound::play(boxhitwall, 255, 122, 0); } - } else if (tiles[y / 40][x / 40 - 1].value == 3 && - tiles[y / 40][x / 40 - 2].value == 0 && haveBroom == 1 && - (key[KEY_SPACE] || joy[0].button[0].b)) { - tiles[y / 40][x / 40 - 1].value = 0; - tiles[y / 40][x / 40 - 2].value = 3; - play_sample(sweep, 1000, 122, 1000, 0); - } else if (tiles[y / 40][x / 40 - 1].value == 3 && - tiles[y / 40][x / 40 - 2].value == 6 && haveBroom == 1 && - (key[KEY_SPACE] || joy[0].button[0].b)) { - tiles[y / 40][x / 40 - 1].value = 0; + } else if (tiles[y / 40][x / 40 - 1].value == V_SCRAP && + tiles[y / 40][x / 40 - 2].value == V_EMPTY && haveBroom == 1 && + asw::input::isKeyDown(asw::input::Key::SPACE)) { + tiles[y / 40][x / 40 - 1].value = V_EMPTY; + tiles[y / 40][x / 40 - 2].value = V_SCRAP; + asw::sound::play(sweep, 1000, 122, 0); + } else if (tiles[y / 40][x / 40 - 1].value == V_SCRAP && + tiles[y / 40][x / 40 - 2].value == V_GARBAGECAN && + haveBroom == 1 && + asw::input::isKeyDown(asw::input::Key::SPACE)) { + tiles[y / 40][x / 40 - 1].value = V_EMPTY; score += 50; if (robotsLeft > 0) { robotsLeft -= 1; } - play_sample(sweep, 1000, 122, 1000, 0); - play_sample(trash, 255, 122, 1000, 0); - } else if (tiles[y / 40][x / 40 - 1].value == 7) { + asw::sound::play(sweep, 1000, 122, 0); + asw::sound::play(trash, 255, 122, 0); + } else if (tiles[y / 40][x / 40 - 1].value == V_JANITORROOM) { if (!haveBroom) { - tiles[y / 40][x / 40 - 1].value = 9; - play_sample(door, 255, 122, 1000, 0); + tiles[y / 40][x / 40 - 1].value = V_JANITORROOMOPEN; + asw::sound::play(door, 255, 122, 0); haveBroom = true; } - } else if (tiles[y / 40][x / 40 - 1].value == 9) { + } else if (tiles[y / 40][x / 40 - 1].value == V_JANITORROOMOPEN) { if (robotsLeft == 0) { doneLevel = 1; } } } - if (key[KEY_RIGHT] || key[KEY_D] || joy[0].stick[0].axis[0].d2) { + if (asw::input::wasKeyPressed(asw::input::Key::RIGHT) || + asw::input::wasKeyPressed(asw::input::Key::D)) { characterRotation = 192; - if (tiles[y / 40][x / 40 + 1].value == 0 || - tiles[y / 40][x / 40 + 1].value == 8) { + if (tiles[y / 40][x / 40 + 1].value == V_EMPTY || + tiles[y / 40][x / 40 + 1].value == V_WALL2) { x = x + 40; - } else if (tiles[y / 40][x / 40 + 1].value == 5) { - play_sample(hitwall, 255, 122, 1000, 0); - } else if (tiles[y / 40][x / 40 + 1].value == 2 && - tiles[y / 40][x / 40 + 2].value == 0) { - play_sample(boxslide, 255, 122, 1000, 0); - tiles[y / 40][x / 40 + 1].value = 0; - tiles[y / 40][x / 40 + 2].value = 2; + } else if (tiles[y / 40][x / 40 + 1].value == V_WALL) { + asw::sound::play(hitwall, 255, 122, 0); + } else if (tiles[y / 40][x / 40 + 1].value == V_BOX && + tiles[y / 40][x / 40 + 2].value == V_EMPTY) { + asw::sound::play(boxslide, 255, 122, 0); + tiles[y / 40][x / 40 + 1].value = V_EMPTY; + tiles[y / 40][x / 40 + 2].value = V_BOX; x = x + 40; - } else if (tiles[y / 40][x / 40 + 1].value == 2 && + } else if (tiles[y / 40][x / 40 + 1].value == V_BOX && tiles[y / 40][x / 40 + 2].value != 0) { - if (tiles[y / 40][x / 40 + 1].value == 2 && - tiles[y / 40][x / 40 + 2].value == 1) { - play_sample(explode, 255, 122, 1000, 0); - tiles[y / 40][x / 40 + 2].value = 3; + if (tiles[y / 40][x / 40 + 1].value == V_BOX && + tiles[y / 40][x / 40 + 2].value == V_ROBOT) { + asw::sound::play(explode, 255, 122, 0); + tiles[y / 40][x / 40 + 2].value = V_SCRAP; score += 100; } else { - play_sample(boxhitwall, 255, 122, 1000, 0); + asw::sound::play(boxhitwall, 255, 122, 0); } - } else if (tiles[y / 40][x / 40 + 1].value == 3 && - tiles[y / 40][x / 40 + 2].value == 0 && haveBroom == 1 && - (key[KEY_SPACE] || joy[0].button[0].b)) { - tiles[y / 40][x / 40 + 1].value = 0; - tiles[y / 40][x / 40 + 2].value = 3; - play_sample(sweep, 1000, 122, 1000, 0); - } else if (tiles[y / 40][x / 40 + 1].value == 3 && - tiles[y / 40][x / 40 + 2].value == 6 && haveBroom == 1 && - (key[KEY_SPACE] || joy[0].button[0].b)) { - tiles[y / 40][x / 40 + 1].value = 0; + } else if (tiles[y / 40][x / 40 + 1].value == V_SCRAP && + tiles[y / 40][x / 40 + 2].value == V_EMPTY && haveBroom == 1 && + asw::input::isKeyDown(asw::input::Key::SPACE)) { + tiles[y / 40][x / 40 + 1].value = V_EMPTY; + tiles[y / 40][x / 40 + 2].value = V_SCRAP; + asw::sound::play(sweep, 1000, 122, 0); + } else if (tiles[y / 40][x / 40 + 1].value == V_SCRAP && + tiles[y / 40][x / 40 + 2].value == V_GARBAGECAN && + haveBroom == 1 && + asw::input::isKeyDown(asw::input::Key::SPACE)) { + tiles[y / 40][x / 40 + 1].value = V_EMPTY; score += 50; if (robotsLeft > 0) { robotsLeft -= 1; } - play_sample(sweep, 1000, 122, 1000, 0); - play_sample(trash, 255, 122, 1000, 0); - } else if (tiles[y / 40][x / 40 + 1].value == 7) { + asw::sound::play(sweep, 1000, 122, 0); + asw::sound::play(trash, 255, 122, 0); + } else if (tiles[y / 40][x / 40 + 1].value == V_JANITORROOM) { if (!haveBroom) { - play_sample(door, 255, 122, 1000, 0); + asw::sound::play(door, 255, 122, 0); haveBroom = 1; - tiles[y / 40][x / 40 + 1].value = 9; + tiles[y / 40][x / 40 + 1].value = V_JANITORROOMOPEN; } - } else if (tiles[y / 40][x / 40 + 1].value == 9) { + } else if (tiles[y / 40][x / 40 + 1].value == V_JANITORROOMOPEN) { if (robotsLeft == 0) { doneLevel = 1; } @@ -675,7 +623,7 @@ void charactermove() { // Change tiles void changeMap() { - finalFile = "levels/level" + convertInt(currentLevel) + ".map"; + finalFile = "assets/levels/level" + convertInt(currentLevel) + ".map"; doneLevel = 0; haveBroom = 0; @@ -727,15 +675,12 @@ void changeMap() { resetBlocks(-1, -1); if (gameScreen == 3) { - textprintf_centre_ex(screen, font, 640, 460, makecol(255, 255, 255), -2, - "%s", levelText.c_str()); + asw::draw::textCenter(font, levelText, asw::Vec2(640, 460), + asw::util::makeColor(255, 255, 255)); rest(1000); - highcolor_fade_out(16); } } else if (gameScreen == 3) { - highcolor_fade_out(16); gameScreen = 4; - highcolor_fade_in(winscreen, 16); } } @@ -743,75 +688,77 @@ void changeMap() { void game() { setupGame(true); - while (!exitGame) { - // Controller Support - poll_joystick(); - - if (key[KEY_ESC] || joy[0].button[3].b) { - exitGame = true; - } + while (!asw::core::exit) { + asw::core::update(); + asw::display::present(); + asw::display::clear(); // Splash if (gameScreen == 0) { - highcolor_fade_in(intro, 16); + asw::display::clear(); + asw::draw::sprite(intro, asw::Vec2(0, 0)); + asw::display::present(); rest(1000); - highcolor_fade_out(16); - highcolor_fade_in(splash, 16); + asw::display::clear(); + asw::draw::sprite(splash, asw::Vec2(0, 0)); + asw::display::present(); rest(1000); - highcolor_fade_out(16); gameScreen = 1; - highcolor_fade_in(menu, 16); + asw::display::clear(); + asw::draw::sprite(menu, asw::Vec2(0, 0)); + asw::display::present(); + continue; } // Menu else if (gameScreen == 1) { + // Draws Menu + asw::draw::sprite(menu, asw::Vec2(0, 0)); + + // Draws Buttons + start.draw(); + help.draw(); + quit.draw(); + mode.draw(); + + if (helpOpen) { + helpOpen = true; + asw::draw::sprite(help_menu, asw::Vec2(0, 0)); + + if (asw::input::keyboard.anyPressed || + asw::input::wasButtonPressed(asw::input::MouseButton::LEFT)) { + helpOpen = false; + } + } else { + if (asw::input::wasKeyPressed(asw::input::Key::ESCAPE)) { + asw::core::exit = true; + } + } + // Checks for mouse press - if (mouse_b & 1) { + if (asw::input::wasButtonPressed(asw::input::MouseButton::LEFT)) { if (start.Hover()) { - highcolor_fade_out(16); gameScreen = 2; setupGame(false); - highcolor_fade_in(levelSelect, 16); + continue; } else if (help.Hover()) { - highcolor_fade_in(help_menu, 16); - - do { - draw_sprite(buffer, help_menu, 0, 0); - draw_sprite(screen, buffer, 0, 0); - } while (!(key[KEY_SPACE] || key[KEY_ENTER] || mouse_b & 1 || - joy[0].button[1].b || joy[0].button[0].b)); - - highcolor_fade_out(16); + helpOpen = true; } else if (quit.Hover()) { - exitGame = true; + asw::core::exit = true; } else if (mode.Hover()) { if (perspective == 0) { perspective = 1; setupGame(true); - mode.SetImages("images/buttons/mode_2d.png", - "images/buttons/mode_2d_hover.png"); - mouse_b = false; + mode.SetImages("assets/images/buttons/mode_2d.png", + "assets/images/buttons/mode_2d_hover.png"); } else if (perspective == 1) { perspective = 0; setupGame(true); - mode.SetImages("images/buttons/mode_3d.png", - "images/buttons/mode_3d_hover.png"); - mouse_b = false; + mode.SetImages("assets/images/buttons/mode_3d.png", + "assets/images/buttons/mode_3d_hover.png"); } } } - - // Draws Menu - draw_sprite(buffer, menu, 0, 0); - - // Draws Buttons - start.draw(buffer); - help.draw(buffer); - quit.draw(buffer); - mode.draw(buffer); - - // Draws Cursor - draw_sprite(buffer, cursor[0], mouse_x, mouse_y); } // Level Select @@ -820,96 +767,96 @@ void game() { changeMap(); // Die - if (tiles[y / 40][x / 40].value == 1) { + if (tiles[y / 40][x / 40].value == V_ROBOT) { lives -= 1; x = 40; y = 40; - play_sample(oof, 255, 122, 1000, 0); + asw::sound::play(oof, 255, 122, 0); } // Go to menu - if (key[KEY_M] || joy[0].button[1].b) { - highcolor_fade_out(16); + if (asw::input::wasKeyPressed(asw::input::Key::ESCAPE)) { gameScreen = 1; - highcolor_fade_in(menu, 16); + continue; } - draw_sprite(buffer, levelSelect, 0, 0); - back.draw(buffer); - stretch_sprite(buffer, background, 320, 220, 640, 480); - textprintf_centre_ex(buffer, font, 640, 760, makecol(0, 0, 0), - makecol(255, 255, 255), "Level:%i", currentLevel); + asw::draw::sprite(levelSelect, asw::Vec2(0, 0)); + back.draw(); + asw::draw::stretchSprite(background, + asw::Quad(320, 220, 640, 480)); + asw::draw::textCenter(font, "Level: " + std::to_string(currentLevel), + asw::Vec2(640, 760), + asw::util::makeColor(0, 0, 0)); // Mini tiles tiles for (int i = 0; i < 24; i++) { for (int t = 0; t < 32; t++) { - if (tiles[i][t].image[0] != NULL && tiles[i][t].value != 1) { + if (tiles[i][t].image[0] != nullptr && tiles[i][t].value != 1) { if (perspective == 0) { - stretch_sprite(buffer, tiles[i][t].image[0], t * 20 + 320, - i * 20 + 220, 30, 30); + asw::draw::stretchSprite( + tiles[i][t].image[0], + asw::Quad(t * 20 + 320, i * 20 + 220, 30, 30)); } else if (perspective == 1) { - stretch_sprite(buffer, tiles[i][t].image[0], t * 20 + 320, - i * 20 + 220, 20, 20); + asw::draw::stretchSprite( + tiles[i][t].image[0], + asw::Quad(t * 20 + 320, i * 20 + 220, 20, 20)); } } } } // Click buttons - if (collision(mouse_x, mouse_x, -1, 200, mouse_y, mouse_y, 0, 960)) { - draw_sprite(buffer, levelSelectLeft, 0, 0); - draw_sprite(buffer, cursor[1], mouse_x, mouse_y); + if (collision(asw::input::mouse.x, asw::input::mouse.x, -1, 200, + asw::input::mouse.y, asw::input::mouse.y, 0, 960)) { + asw::draw::sprite(levelSelectLeft, asw::Vec2(0, 0)); - if (mouse_b & 1 && currentLevel > 1) { - play_sample(click, 255, 125, 1000, 0); + if (asw::input::wasButtonPressed(asw::input::MouseButton::LEFT) && + currentLevel > 1) { + asw::sound::play(click, 255, 125, 0); currentLevel -= 1; setupGame(false); rest(140); } - } else if (collision(mouse_x, mouse_x, 1080, 1280, mouse_y, mouse_y, 0, - 960)) { - draw_sprite(buffer, levelSelectRight, 1080, 0); - draw_sprite(buffer, cursor[1], mouse_x, mouse_y); + } else if (collision(asw::input::mouse.x, asw::input::mouse.x, 1080, 1280, + asw::input::mouse.y, asw::input::mouse.y, 0, 960)) { + asw::draw::sprite(levelSelectRight, asw::Vec2(1080, 0)); - if (mouse_b & 1) { - finalFile = "levels/level" + convertInt(currentLevel + 1) + ".map"; + if (asw::input::wasButtonPressed(asw::input::MouseButton::LEFT)) { + finalFile = + "assets/levels/level" + convertInt(currentLevel + 1) + ".map"; if (fexists(finalFile.c_str())) { - play_sample(click, 255, 125, 1000, 0); + asw::sound::play(click, 255, 125, 0); currentLevel += 1; setupGame(false); rest(140); } } - } else if (collision(mouse_x, mouse_x, 320, 978, mouse_y, mouse_y, 220, + } else if (collision(asw::input::mouse.x, asw::input::mouse.x, 320, 978, + asw::input::mouse.y, asw::input::mouse.y, 220, 718)) { - draw_sprite(buffer, cursor[1], mouse_x, mouse_y); - - if (mouse_b & 1) { - highcolor_fade_out(16); + if (asw::input::wasButtonPressed(asw::input::MouseButton::LEFT)) { gameScreen = 3; changeMap(); setupGame(false); + continue; } - } else { - draw_sprite(buffer, cursor[0], mouse_x, mouse_y); } - if (mouse_b & 1 && back.Hover() == true) { - highcolor_fade_out(16); + if (asw::input::wasButtonPressed(asw::input::MouseButton::LEFT) && + back.Hover() == true) { gameScreen = 1; - highcolor_fade_in(menu, 16); + continue; } } // Ingame Loops if (gameScreen == 3) { // Go to menu - if (key[KEY_M] || joy[0].button[1].b) { - highcolor_fade_out(16); + if (asw::input::wasKeyPressed(asw::input::Key::ESCAPE)) { gameScreen = 1; score = 0; - highcolor_fade_in(menu, 16); + continue; } // Changes move @@ -927,40 +874,37 @@ void game() { elaspedTime = int(currentTime - startTime) / CLOCKS_PER_SEC; // Draw background - draw_sprite(buffer, background, 0, 0); + asw::draw::sprite(background, asw::Vec2(0, 0)); // Updates robots positions - if (step % 4 == 0) { + if (step % 40 == 0) { for (int i = 0; i < 24; i++) { for (int t = 0; t < 32; t++) { - if (tiles[i][t].value == 1) { - int random_integer; - int lowest = 0, highest = 5; - int range = (highest - lowest) + 1; - random_integer = lowest + int(range * rand() / (RAND_MAX + 1.0)); - - if (random_integer == 1 && tiles[i - 1][t].value == 0) { - tiles[i - 1][t].value = 1; - tiles[i][t].value = 0; + if (tiles[i][t].value == V_ROBOT) { + int random_integer = asw::random::between(0, 4); + + if (random_integer == 1 && tiles[i - 1][t].value == V_EMPTY) { + tiles[i - 1][t].value = V_ROBOT; + tiles[i][t].value = V_EMPTY; } - if (random_integer == 2 && tiles[i][t + 1].value == 0) { - tiles[i][t + 1].value = 1; - tiles[i][t].value = 0; + if (random_integer == 2 && tiles[i][t + 1].value == V_EMPTY) { + tiles[i][t + 1].value = V_ROBOT; + tiles[i][t].value = V_EMPTY; } - if (random_integer == 3 && tiles[i + 1][t].value == 0) { - tiles[i + 1][t].value = 1; - tiles[i][t].value = 0; + if (random_integer == 3 && tiles[i + 1][t].value == V_EMPTY) { + tiles[i + 1][t].value = V_ROBOT; + tiles[i][t].value = V_EMPTY; } - if (random_integer == 4 && tiles[i][t - 1].value == 0) { - tiles[i][t - 1].value = 1; - tiles[i][t].value = 0; + if (random_integer == 4 && tiles[i][t - 1].value == V_EMPTY) { + tiles[i][t - 1].value = V_ROBOT; + tiles[i][t].value = V_EMPTY; } if (i == y / 40 && t == x / 40) { - play_sample(oof, 2000, 122, 1000, 0); + asw::sound::play(oof, 2000, 122, 0); lives -= 1; x = 40; y = 40; @@ -971,32 +915,26 @@ void game() { } // Restart Map - if (key[KEY_R] || joy[0].button[2].b) { - highcolor_fade_out(16); + if (asw::input::wasKeyPressed(asw::input::Key::R)) { changeMap(); } // Pause Game - if (key[KEY_P] || joy[0].button[7].b) { - while (key[KEY_P] || joy[0].button[7].b) { - poll_joystick(); - } - - while (!(key[KEY_P] || joy[0].button[7].b || key[KEY_ESC])) { - textout_ex(buffer, font, "Paused press P to resume", 420, 440, - makecol(0, 0, 0), makecol(255, 255, 255)); - draw_sprite(screen, buffer, 0, 0); - poll_joystick(); - } - - while (key[KEY_P] || joy[0].button[7].b) { - poll_joystick(); + if (asw::input::wasKeyPressed(asw::input::Key::P)) { + while (!(asw::input::wasKeyPressed(asw::input::Key::P) || + asw::input::wasKeyPressed(asw::input::Key::ESCAPE))) { + asw::display::clear(); + asw::draw::text(font, "Paused press P to resume", + asw::Vec2(420, 440), + asw::util::makeColor(0, 0, 0)); + asw::core::update(); + asw::display::present(); } } // Finish Level if (doneLevel == 1) { - play_sample(winsound, 255, 122, 1000, 0); + asw::sound::play(winsound, 255, 122, 0); currentLevel += 1; lives += 1; changeMap(); @@ -1015,28 +953,29 @@ void game() { if (y / 40 == i && x / 40 == t) { // Draws Character if (perspective == 0) { - // rotate_sprite(buffer, character, x + 5, y + 5, + // rotate_sprite( character, x + 5, y + 5, // ftofix(characterRotation)); if (characterRotation == 0) { - draw_sprite(buffer, character[0], x, y); + asw::draw::sprite(character[0], asw::Vec2(x, y)); } else if (characterRotation == 128) { - draw_sprite(buffer, character[1], x, y); + asw::draw::sprite(character[1], asw::Vec2(x, y)); } else if (characterRotation == 64) { - draw_sprite(buffer, character[2], x, y); + asw::draw::sprite(character[2], asw::Vec2(x, y)); } else if (characterRotation == 192) { - draw_sprite(buffer, character[3], x, y); + asw::draw::sprite(character[3], asw::Vec2(x, y)); } } else { - draw_sprite(buffer, character[0], x, y); + asw::draw::sprite(character[0], asw::Vec2(x, y)); } // Draws broom if needed - if ((key[KEY_SPACE] || joy[0].button[0].b) && haveBroom == 1) { + if (asw::input::isKeyDown(asw::input::Key::SPACE) && + haveBroom == 1) { if (perspective == 0) { - rotate_sprite(buffer, broom, x + 10, y + 10, - ftofix(float(characterRotation))); + asw::draw::rotateSprite(broom, asw::Vec2(x + 10, y + 10), + characterRotation); } else { - draw_sprite(buffer, broom, x, y); + asw::draw::sprite(broom, asw::Vec2(x, y)); } } } @@ -1048,126 +987,66 @@ void game() { map[i][t] = tiles[i][t].value; - if (tiles[i][t].image[0] != NULL) { + if (tiles[i][t].image[0] != nullptr) { if (perspective == 0) { - stretch_sprite(buffer, tiles[i][t].image[0], t * 40, i * 40, 60, - 60); + asw::draw::stretchSprite( + tiles[i][t].image[0], + asw::Quad(t * 40, i * 40, 60, 60)); } else { - stretch_sprite(buffer, tiles[i][t].image[0], t * 40, i * 40, 40, - 40); + asw::draw::stretchSprite( + tiles[i][t].image[0], + asw::Quad(t * 40, i * 40, 40, 40)); } } } } // Draws Stats - textprintf_ex(buffer, font, 0, 0, makecol(0, 0, 0), - makecol(255, 255, 255), "Score:%i", score); - textprintf_right_ex(buffer, font, 1280, 0, makecol(0, 0, 0), - makecol(255, 255, 255), "Robots Left:%i", robotsLeft); - textprintf_centre_ex(buffer, font, 640, 0, makecol(0, 0, 0), - makecol(255, 255, 255), "Lives:%i", lives); + asw::draw::text(font, "Score:" + std::to_string(score), + asw::Vec2(0, 0), + asw::util::makeColor(255, 255, 255)); - // Draws Cursor - draw_sprite(buffer, cursor[0], (mouse_x / 40) * 40, (mouse_y / 40) * 40); + asw::draw::textRight(font, "Robots Left:" + std::to_string(robotsLeft), + asw::Vec2(1280, 0), + asw::util::makeColor(255, 255, 255)); + + asw::draw::textCenter(font, "Lives:" + std::to_string(lives), + asw::Vec2(640, 0), + asw::util::makeColor(255, 255, 255)); // Checks for character move charactermove(); // Rests (regulates game speed) rest(100); - } else if (gameScreen == 4) { - draw_sprite(buffer, winscreen, 0, 0); - textprintf_ex(buffer, font, 310, 400, makecol(0, 0, 0), -1, "%i", score); - if (key[KEY_SPACE] || key[KEY_ENTER] || mouse_b & 1 || - joy[0].button[0].b) { - highcolor_fade_out(16); + } else if (gameScreen == 4) { + asw::draw::sprite(winscreen, asw::Vec2(0, 0)); + asw::draw::text(font, std::to_string(score), asw::Vec2(310, 400), + asw::util::makeColor(0, 0, 0)); + + if (asw::input::wasKeyPressed(asw::input::Key::SPACE) || + asw::input::wasKeyPressed(asw::input::Key::RETURN) || + asw::input::wasKeyPressed(asw::input::Key::ESCAPE) || + asw::input::wasButtonPressed(asw::input::MouseButton::LEFT)) { gameScreen = 1; - highcolor_fade_in(winscreen, 16); + continue; } } // Adds one to step step++; - - // Draws Buffer - draw_sprite(screen, buffer, 0, 0); } } -void close() { - for (int i = 0; i < 4; i++) { - if (character[i]) { - destroy_bitmap(character[i]); - } - } - - for (int i = 0; i < 2; i++) { - if (cursor[i]) { - destroy_bitmap(cursor[i]); - } - } - - destroy_bitmap(buffer); - destroy_bitmap(background); - destroy_bitmap(robot); - destroy_bitmap(wall); - destroy_bitmap(fakeWall); - destroy_bitmap(ground); - destroy_bitmap(box); - destroy_bitmap(menu); - destroy_bitmap(help_menu); - destroy_bitmap(levelSelect); - destroy_bitmap(levelSelectLeft); - destroy_bitmap(levelSelectRight); - destroy_bitmap(winscreen); - destroy_bitmap(intro); - destroy_bitmap(splash); - destroy_bitmap(scrap); - destroy_bitmap(broom); - destroy_bitmap(garbagecan); - destroy_bitmap(janitorroom); - destroy_bitmap(janitorroomopen); - destroy_bitmap(wall2); - destroy_bitmap(wood_floor); - - destroy_sample(hitwall); - destroy_sample(boxhitwall); - destroy_sample(boxslide); - destroy_sample(explode); - destroy_sample(sweep); - destroy_sample(trash); - destroy_sample(oof); - destroy_sample(winsound); - destroy_sample(door); - destroy_sample(click); - - // Allegro - clear_keybuf(); -} - // Main functions run here int main() { // Initializing - allegro_init(); - install_timer(); - install_mouse(); - install_joystick(JOY_TYPE_AUTODETECT); - install_keyboard(); - set_color_depth(32); - set_gfx_mode(GFX_AUTODETECT_WINDOWED, 1280, 960, 0, 0); - install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, "."); - set_window_title("Mazes"); + asw::core::init(1280, 960, 1); + asw::display::setTitle("Mazes"); // Starts Game game(); - close(); - - rest(100); - return 0; } - -END_OF_MAIN() diff --git a/src/rapidxml/rapidxml.hpp b/src/rapidxml/rapidxml.hpp deleted file mode 100644 index 3d59043..0000000 --- a/src/rapidxml/rapidxml.hpp +++ /dev/null @@ -1,2645 +0,0 @@ -#ifndef RAPIDXML_HPP_INCLUDED -#define RAPIDXML_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml/rapidxml.hpp This file contains rapidxml parser and DOM -//! implementation - -// If standard library is disabled, user must provide implementations of -// required functions and typedefs -#if !defined(RAPIDXML_NO_STDLIB) -#include // For assert -#include // For std::size_t -#include // For placement new -#endif - -// On MSVC, disable "conditional expression is constant" warning (level 4). -// This warning is almost impossible to avoid with certain types of templated -// code -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4127) // Conditional expression is constant -#endif - -/////////////////////////////////////////////////////////////////////////// -// RAPIDXML_PARSE_ERROR - -#if defined(RAPIDXML_NO_EXCEPTIONS) - -#define RAPIDXML_PARSE_ERROR(what, where) \ - { \ - parse_error_handler(what, where); \ - assert(0); \ - } - -namespace rapidxml { -//! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, -//! this function is called to notify user about the error. -//! It must be defined by the user. -//!

-//! This function cannot return. If it does, the results are undefined. -//!

-//! A very simple definition might look like that: -//!
-//! void %rapidxml::%parse_error_handler(const char *what, void *where)
-//! {
-//!     std::cout << "Parse error: " << what << "\n";
-//!     std::abort();
-//! }
-//! 
-//! \param what Human readable description of the error. -//! \param where Pointer to character data where error was detected. -void parse_error_handler(const char* what, void* where); -} // namespace rapidxml - -#else - -#include // For std::exception - -#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) - -namespace rapidxml { - -//! Parse error exception. -//! This exception is thrown by the parser when an error occurs. -//! Use what() function to get human-readable error message. -//! Use where() function to get a pointer to position within source text where -//! error was detected.

If throwing exceptions by the parser is -//! undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro -//! before rapidxml.hpp is included. This will cause the parser to call -//! rapidxml::parse_error_handler() function instead of throwing an exception. -//! This function must be defined by the user. -//!

-//! This class derives from std::exception class. -class parse_error : public std::exception { - public: - //! Constructs parse error - parse_error(const char* what, void* where) : m_what(what), m_where(where) {} - - //! Gets human readable description of error. - //! \return Pointer to null terminated description of the error. - virtual const char* what() const throw() { return m_what; } - - //! Gets pointer to character data where error happened. - //! Ch should be the same as char type of xml_document that produced the - //! error. \return Pointer to location within the parsed string where error - //! occured. - template - Ch* where() const { - return reinterpret_cast(m_where); - } - - private: - const char* m_what; - void* m_where; -}; -} // namespace rapidxml - -#endif - -/////////////////////////////////////////////////////////////////////////// -// Pool sizes - -#ifndef RAPIDXML_STATIC_POOL_SIZE - // Size of static memory block of memory_pool. -// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to -// override the default value. No dynamic memory allocations are performed by -// memory_pool until static memory is exhausted. -#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_DYNAMIC_POOL_SIZE - // Size of dynamic memory block of memory_pool. -// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want -// to override the default value. After the static block is exhausted, dynamic -// blocks with approximately this size are allocated by memory_pool. -#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_ALIGNMENT - // Memory allocation alignment. -// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to -// override the default value, which is the size of pointer. All memory -// allocations for nodes, attributes and strings will be aligned to this value. -// This must be a power of 2 and at least 1, otherwise memory_pool will not -// work. -#define RAPIDXML_ALIGNMENT sizeof(void*) -#endif - -namespace rapidxml { -// Forward declarations -template -class xml_node; -template -class xml_attribute; -template -class xml_document; - -//! Enumeration listing all node types produced by the parser. -//! Use xml_node::type() function to query node type. -enum node_type { - node_document, //!< A document node. Name and value are empty. - node_element, //!< An element node. Name contains element name. Value - //!< contains text of first data node. - node_data, //!< A data node. Name is empty. Value contains data text. - node_cdata, //!< A CDATA node. Name is empty. Value contains data text. - node_comment, //!< A comment node. Name is empty. Value contains comment - //!< text. - node_declaration, //!< A declaration node. Name and value are empty. - //!< Declaration parameters (version, encoding and - //!< standalone) are in node attributes. - node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE - //!< text. - node_pi //!< A PI node. Name contains target. Value contains instructions. -}; - -/////////////////////////////////////////////////////////////////////// -// Parsing flags - -//! Parse flag instructing the parser to not create data nodes. -//! Text of first data node will still be placed in value of parent element, -//! unless rapidxml::parse_no_element_values flag is also specified. Can be -//! combined with other flags by use of | operator.

See -//! xml_document::parse() function. -const int parse_no_data_nodes = 0x1; - -//! Parse flag instructing the parser to not use text of first data node as a -//! value of parent element. Can be combined with other flags by use of | -//! operator. Note that child data nodes of element node take precendence over -//! its value when printing. That is, if element has one or more child data -//! nodes and a value, the value will be ignored. Use -//! rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you -//! want to manipulate data using values of elements.

See -//! xml_document::parse() function. -const int parse_no_element_values = 0x2; - -//! Parse flag instructing the parser to not place zero terminators after -//! strings in the source text. By default zero terminators are placed, -//! modifying source text. Can be combined with other flags by use of | -//! operator.

See xml_document::parse() function. -const int parse_no_string_terminators = 0x4; - -//! Parse flag instructing the parser to not translate entities in the source -//! text. By default entities are translated, modifying source text. Can be -//! combined with other flags by use of | operator.

See -//! xml_document::parse() function. -const int parse_no_entity_translation = 0x8; - -//! Parse flag instructing the parser to disable UTF-8 handling and assume plain -//! 8 bit characters. By default, UTF-8 handling is enabled. Can be combined -//! with other flags by use of | operator.

See xml_document::parse() -//! function. -const int parse_no_utf8 = 0x10; - -//! Parse flag instructing the parser to create XML declaration node. -//! By default, declaration node is not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_declaration_node = 0x20; - -//! Parse flag instructing the parser to create comments nodes. -//! By default, comment nodes are not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_comment_nodes = 0x40; - -//! Parse flag instructing the parser to create DOCTYPE node. -//! By default, doctype node is not created. -//! Although W3C specification allows at most one DOCTYPE node, RapidXml will -//! silently accept documents with more than one. Can be combined with other -//! flags by use of | operator.

See xml_document::parse() function. -const int parse_doctype_node = 0x80; - -//! Parse flag instructing the parser to create PI nodes. -//! By default, PI nodes are not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_pi_nodes = 0x100; - -//! Parse flag instructing the parser to validate closing tag names. -//! If not set, name inside closing tag is irrelevant to the parser. -//! By default, closing tags are not validated. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_validate_closing_tags = 0x200; - -//! Parse flag instructing the parser to trim all leading and trailing -//! whitespace of data nodes. By default, whitespace is not trimmed. This flag -//! does not cause the parser to modify source text. Can be combined with other -//! flags by use of | operator.

See xml_document::parse() function. -const int parse_trim_whitespace = 0x400; - -//! Parse flag instructing the parser to condense all whitespace runs of data -//! nodes to a single space character. Trimming of leading and trailing -//! whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. By -//! default, whitespace is not normalized. If this flag is specified, source -//! text will be modified. Can be combined with other flags by use of | -//! operator.

See xml_document::parse() function. -const int parse_normalize_whitespace = 0x800; - -// Compound flags - -//! Parse flags which represent default behaviour of the parser. -//! This is always equal to 0, so that all other flags can be simply ored -//! together. Normally there is no need to inconveniently disable flags by -//! anding with their negated (~) values. This also means that meaning of each -//! flag is a negation of the default setting. For example, if flag name -//! is rapidxml::parse_no_utf8, it means that utf-8 is enabled by -//! default, and using the flag will disable it.

See -//! xml_document::parse() function. -const int parse_default = 0; - -//! A combination of parse flags that forbids any modifications of the source -//! text. This also results in faster parsing. However, note that the following -//! will occur:
  • names and values of nodes will not be zero terminated, -//! you have to use xml_base::name_size() and xml_base::value_size() functions -//! to determine where name and value ends
  • entities will not be -//! translated
  • whitespace will not be normalized
  • -//!
-//! See xml_document::parse() function. -const int parse_non_destructive = - parse_no_string_terminators | parse_no_entity_translation; - -//! A combination of parse flags resulting in fastest possible parsing, without -//! sacrificing important data.

See xml_document::parse() function. -const int parse_fastest = parse_non_destructive | parse_no_data_nodes; - -//! A combination of parse flags resulting in largest amount of data being -//! extracted. This usually results in slowest parsing.

See -//! xml_document::parse() function. -const int parse_full = parse_declaration_node | parse_comment_nodes | - parse_doctype_node | parse_pi_nodes | - parse_validate_closing_tags; - -/////////////////////////////////////////////////////////////////////// -// Internals - -//! \cond internal -namespace internal { - -// Struct that contains lookup tables for the parser -// It must be a template to allow correct linking (because it has static data -// members, which are defined in a header file). -template -struct lookup_tables { - static const unsigned char lookup_whitespace[256]; // Whitespace table - static const unsigned char lookup_node_name[256]; // Node name table - static const unsigned char lookup_text[256]; // Text table - static const unsigned char lookup_text_pure_no_ws[256]; // Text table - static const unsigned char lookup_text_pure_with_ws[256]; // Text table - static const unsigned char - lookup_attribute_name[256]; // Attribute name table - static const unsigned char - lookup_attribute_data_1[256]; // Attribute data table with single quote - static const unsigned char - lookup_attribute_data_1_pure[256]; // Attribute data table with single - // quote - static const unsigned char - lookup_attribute_data_2[256]; // Attribute data table with double quotes - static const unsigned char - lookup_attribute_data_2_pure[256]; // Attribute data table with double - // quotes - static const unsigned char lookup_digits[256]; // Digits - static const unsigned char - lookup_upcase[256]; // To uppercase conversion table for ASCII characters -}; - -// Find length of the string -template -inline std::size_t measure(const Ch* p) { - const Ch* tmp = p; - - while (*tmp) - ++tmp; - - return tmp - p; -} - -// Compare strings for equality -template -inline bool compare(const Ch* p1, - std::size_t size1, - const Ch* p2, - std::size_t size2, - bool case_sensitive) { - if (size1 != size2) - return false; - - if (case_sensitive) { - for (const Ch* end = p1 + size1; p1 < end; ++p1, ++p2) - if (*p1 != *p2) - return false; - } else { - for (const Ch* end = p1 + size1; p1 < end; ++p1, ++p2) - if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] != - lookup_tables<0>::lookup_upcase[static_cast(*p2)]) - return false; - } - - return true; -} -} // namespace internal -//! \endcond - -/////////////////////////////////////////////////////////////////////// -// Memory pool - -//! This class is used by the parser to create new nodes and attributes, without -//! overheads of dynamic memory allocation. In most cases, you will not need to -//! use this class directly. However, if you need to create nodes manually or -//! modify names/values of nodes, you are encouraged to use memory_pool of -//! relevant xml_document to allocate the memory. Not only is this faster than -//! allocating them by using new operator, but also their lifetime -//! will be tied to the lifetime of document, possibly simplyfing memory -//! management.

Call allocate_node() or allocate_attribute() functions -//! to obtain new nodes or attributes from the pool. You can also call -//! allocate_string() function to allocate strings. Such strings can then be -//! used as names or values of nodes without worrying about their lifetime. Note -//! that there is no free() function -- all allocations are freed -//! at once when clear() function is called, or when the pool is destroyed. -//!

-//! It is also possible to create a standalone memory_pool, and use it -//! to allocate nodes, whose lifetime will not be tied to any document. -//!

-//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically -//! allocated memory. Until static memory is exhausted, no dynamic memory -//! allocations are done. When static memory is exhausted, pool allocates -//! additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE -//! each, by using global new[] and delete[] -//! operators. This behaviour can be changed by setting custom allocation -//! routines. Use set_allocator() function to set them.

Allocations for -//! nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT -//! bytes. This value defaults to the size of pointer on target architecture. -//!

-//! To obtain absolutely top performance from the parser, -//! it is important that all nodes are allocated from a single, contiguous block -//! of memory. Otherwise, cache misses when jumping between two (or more) -//! disjoint blocks of memory can slow down parsing quite considerably. If -//! required, you can tweak RAPIDXML_STATIC_POOL_SIZE, -//! RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT -//! to obtain best wasted memory to performance compromise. -//! To do it, define their values before rapidxml.hpp file is included. -//! \param Ch Character type of created nodes. -template -class memory_pool { - public: - //! \cond internal - typedef void*(alloc_func)( - std::size_t); // Type of user-defined function used to allocate memory - typedef void(free_func)( - void*); // Type of user-defined function used to free memory - //! \endcond - - //! Constructs empty pool with default allocator functions. - memory_pool() : m_alloc_func(nullptr), m_free_func(nullptr) { init(); } - - //! Destroys pool and frees all the memory. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Nodes allocated from the pool are no longer valid. - ~memory_pool() { clear(); } - - //! Allocates a new node from the pool, and optionally assigns name and value - //! to it. If the allocation request cannot be accomodated, this function will - //! throw std::bad_alloc. If exceptions are disabled by defining - //! RAPIDXML_NO_EXCEPTIONS, this function will call - //! rapidxml::parse_error_handler() function. \param type Type of node to - //! create. \param name Name to assign to the node, or 0 to assign no name. - //! \param value Value to assign to the node, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate - //! size from name string. \param value_size Size of value to assign, or 0 to - //! automatically calculate size from value string. \return Pointer to - //! allocated node. This pointer will never be NULL. - xml_node* allocate_node(node_type type, - const Ch* name = nullptr, - const Ch* value = nullptr, - std::size_t name_size = 0, - std::size_t value_size = 0) { - void* memory = allocate_aligned(sizeof(xml_node)); - xml_node* node = new (memory) xml_node(type); - - if (name) { - if (name_size > 0) - node->name(name, name_size); - else - node->name(name); - } - - if (value) { - if (value_size > 0) - node->value(value, value_size); - else - node->value(value); - } - - return node; - } - - //! Allocates a new attribute from the pool, and optionally assigns name and - //! value to it. If the allocation request cannot be accomodated, this - //! function will throw std::bad_alloc. If exceptions are - //! disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call - //! rapidxml::parse_error_handler() function. \param name Name to assign to - //! the attribute, or 0 to assign no name. \param value Value to assign to the - //! attribute, or 0 to assign no value. \param name_size Size of name to - //! assign, or 0 to automatically calculate size from name string. \param - //! value_size Size of value to assign, or 0 to automatically calculate size - //! from value string. \return Pointer to allocated attribute. This pointer - //! will never be NULL. - xml_attribute* allocate_attribute(const Ch* name = nullptr, - const Ch* value = nullptr, - std::size_t name_size = 0, - std::size_t value_size = 0) { - void* memory = allocate_aligned(sizeof(xml_attribute)); - xml_attribute* attribute = new (memory) xml_attribute; - - if (name) { - if (name_size > 0) - attribute->name(name, name_size); - else - attribute->name(name); - } - - if (value) { - if (value_size > 0) - attribute->value(value, value_size); - else - attribute->value(value); - } - - return attribute; - } - - //! Allocates a char array of given size from the pool, and optionally copies - //! a given string to it. If the allocation request cannot be accomodated, - //! this function will throw std::bad_alloc. If exceptions are - //! disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call - //! rapidxml::parse_error_handler() function. \param source String to - //! initialize the allocated memory with, or 0 to not initialize it. \param - //! size Number of characters to allocate, or zero to calculate it - //! automatically from source string length; if size is 0, source string must - //! be specified and null terminated. \return Pointer to allocated char array. - //! This pointer will never be NULL. - Ch* allocate_string(const Ch* source = nullptr, std::size_t size = 0) { - assert(source || - size); // Either source or size (or both) must be specified - - if (size == 0) - size = internal::measure(source) + 1; - - Ch* result = static_cast(allocate_aligned(size * sizeof(Ch))); - - if (source) - for (std::size_t i = 0; i < size; ++i) - result[i] = source[i]; - - return result; - } - - //! Clones an xml_node and its hierarchy of child nodes and attributes. - //! Nodes and attributes are allocated from this memory pool. - //! Names and values are not cloned, they are shared between the clone and the - //! source. Result node can be optionally specified as a second parameter, in - //! which case its contents will be replaced with cloned source node. This is - //! useful when you want to clone entire document. \param source Node to - //! clone. \param result Node to put results in, or 0 to automatically - //! allocate result node \return Pointer to cloned node. This pointer will - //! never be NULL. - xml_node* clone_node(const xml_node* source, - xml_node* result = nullptr) { - // Prepare result node - if (result) { - result->remove_all_attributes(); - result->remove_all_nodes(); - result->type(source->type()); - } else - result = allocate_node(source->type()); - - // Clone name and value - result->name(source->name(), source->name_size()); - result->value(source->value(), source->value_size()); - - // Clone child nodes and attributes - for (xml_node* child = source->first_node(); child; - child = child->next_sibling()) - result->append_node(clone_node(child)); - - for (xml_attribute* attr = source->first_attribute(); attr; - attr = attr->next_attribute()) - result->append_attribute(allocate_attribute( - attr->name(), attr->value(), attr->name_size(), attr->value_size())); - - return result; - } - - //! Clears the pool. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Any nodes or strings allocated from the pool will no longer be valid. - void clear() { - while (m_begin != m_static_memory) { - char* previous_begin = - reinterpret_cast(align(m_begin))->previous_begin; - - if (m_free_func) - m_free_func(m_begin); - else - delete[] m_begin; - - m_begin = previous_begin; - } - - init(); - } - - //! Sets or resets the user-defined memory allocation functions for the pool. - //! This can only be called when no memory is allocated from the pool yet, - //! otherwise results are undefined. Allocation function must not return - //! invalid pointer on failure. It should either throw, stop the program, or - //! use longjmp() function to pass control to other place of - //! program. If it returns invalid pointer, results are undefined.

- //! User defined allocation functions must have the following forms: - //!
- //!
void *allocate(std::size_t size); - //!
void free(void *pointer); - //!

- //! \param af Allocation function, or 0 to restore default function - //! \param ff Free function, or 0 to restore default function - void set_allocator(alloc_func* af, free_func* ff) { - assert(m_begin == m_static_memory && - m_ptr == align(m_begin)); // Verify that no memory is allocated yet - m_alloc_func = af; - m_free_func = ff; - } - - private: - struct header { - char* previous_begin; - }; - - void init() { - m_begin = m_static_memory; - m_ptr = align(m_begin); - m_end = m_static_memory + sizeof(m_static_memory); - } - - char* align(char* ptr) { - std::size_t alignment = - ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & - (RAPIDXML_ALIGNMENT - 1)); - return ptr + alignment; - } - - char* allocate_raw(std::size_t size) { - // Allocate - void* memory; - - if (m_alloc_func) { // Allocate memory using either user-specified - // allocation function or global operator new[] - memory = m_alloc_func(size); - assert(memory); // Allocator is not allowed to return 0, on failure it - // must either throw, stop the program or use longjmp - } else { - memory = new char[size]; -#ifdef RAPIDXML_NO_EXCEPTIONS - - if (!memory) // If exceptions are disabled, verify memory allocation, - // because new will not be able to throw bad_alloc - RAPIDXML_PARSE_ERROR("out of memory", 0); - -#endif - } - - return static_cast(memory); - } - - void* allocate_aligned(std::size_t size) { - // Calculate aligned pointer - char* result = align(m_ptr); - - // If not enough memory left in current pool, allocate a new pool - if (result + size > m_end) { - // Calculate required pool size (may be bigger than - // RAPIDXML_DYNAMIC_POOL_SIZE) - std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; - - if (pool_size < size) - pool_size = size; - - // Allocate - std::size_t alloc_size = - sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + - pool_size; // 2 alignments required in worst case: one for header, - // one for actual allocation - char* raw_memory = allocate_raw(alloc_size); - - // Setup new pool in allocated memory - char* pool = align(raw_memory); - header* new_header = reinterpret_cast(pool); - new_header->previous_begin = m_begin; - m_begin = raw_memory; - m_ptr = pool + sizeof(header); - m_end = raw_memory + alloc_size; - - // Calculate aligned pointer again using new pool - result = align(m_ptr); - } - - // Update pool and return aligned pointer - m_ptr = result + size; - return result; - } - - char* m_begin; // Start of raw memory making up current pool - char* m_ptr; // First free byte in current pool - char* m_end; // One past last available byte in current pool - char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory - alloc_func* - m_alloc_func; // Allocator function, or 0 if default is to be used - free_func* m_free_func; // Free function, or 0 if default is to be used -}; - -/////////////////////////////////////////////////////////////////////////// -// XML base - -//! Base class for xml_node and xml_attribute implementing common functions: -//! name(), name_size(), value(), value_size() and parent(). -//! \param Ch Character type to use -template -class xml_base { - public: - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - // Construct a base with empty name, value and parent - xml_base() : m_name(nullptr), m_value(nullptr), m_parent(nullptr) {} - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets name of the node. - //! Interpretation of name depends on type of node. - //! Note that name will not be zero-terminated if - //! rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use name_size() function to determine length of the name. - //! \return Name of node, or empty string if node has no name. - Ch* name() const { return m_name ? m_name : nullstr(); } - - //! Gets size of node name, not including terminator character. - //! This function works correctly irrespective of whether name is or is not - //! zero terminated. \return Size of node name, in characters. - std::size_t name_size() const { return m_name ? m_name_size : 0; } - - //! Gets value of node. - //! Interpretation of value depends on type of node. - //! Note that value will not be zero-terminated if - //! rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use value_size() function to determine length of the value. - //! \return Value of node, or empty string if node has no value. - Ch* value() const { return m_value ? m_value : nullstr(); } - - //! Gets size of node value, not including terminator character. - //! This function works correctly irrespective of whether value is or is not - //! zero terminated. \return Size of node value, in characters. - std::size_t value_size() const { return m_value ? m_value_size : 0; } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets name of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to - //! it. It will not delete or otherwise free the pointer on destruction. It is - //! reponsibility of the user to properly manage lifetime of the string. The - //! easiest way to achieve it is to use memory_pool of the document to - //! allocate the string - on destruction of the document the string will be - //! automatically freed.

Size of name must be specified separately, - //! because name does not have to be zero terminated. Use name(const Ch *) - //! function to have the length automatically calculated (string must be zero - //! terminated). \param name Name of node to set. Does not have to be zero - //! terminated. \param size Size of name, in characters. This does not include - //! zero terminator, if one is present. - void name(const Ch* name, std::size_t size) { - m_name = const_cast(name); - m_name_size = size; - } - - //! Sets name of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::name(const Ch *, - //! std::size_t). \param name Name of node to set. Must be zero terminated. - void name(const Ch* name) { this->name(name, internal::measure(name)); } - - //! Sets value of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to - //! it. It will not delete or otherwise free the pointer on destruction. It is - //! reponsibility of the user to properly manage lifetime of the string. The - //! easiest way to achieve it is to use memory_pool of the document to - //! allocate the string - on destruction of the document the string will be - //! automatically freed.

Size of value must be specified separately, - //! because it does not have to be zero terminated. Use value(const Ch *) - //! function to have the length automatically calculated (string must be zero - //! terminated).

If an element has a child node of type node_data, it - //! will take precedence over element value when printing. If you want to - //! manipulate data of elements using values, use parser flag - //! rapidxml::parse_no_data_nodes to prevent creation of data nodes by the - //! parser. \param value value of node to set. Does not have to be zero - //! terminated. \param size Size of value, in characters. This does not - //! include zero terminator, if one is present. - void value(const Ch* value, std::size_t size) { - m_value = const_cast(value); - m_value_size = size; - } - - //! Sets value of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::value(const Ch *, - //! std::size_t). \param value Vame of node to set. Must be zero terminated. - void value(const Ch* value) { this->value(value, internal::measure(value)); } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets node parent. - //! \return Pointer to parent node, or 0 if there is no parent. - xml_node* parent() const { return m_parent; } - - protected: - // Return empty string - static Ch* nullstr() { - static Ch zero = Ch('\0'); - return &zero; - } - - Ch* m_name; // Name of node, or 0 if no name - Ch* m_value; // Value of node, or 0 if no value - std::size_t m_name_size; // Length of node name, or undefined of no name - std::size_t m_value_size; // Length of node value, or undefined if no value - xml_node* m_parent; // Pointer to parent node, or 0 if none -}; - -//! Class representing attribute node of XML document. -//! Each attribute has name and value strings, which are available through -//! name() and value() functions (inherited from xml_base). Note that after -//! parse, both name and value of attribute will point to interior of source -//! text used for parsing. Thus, this text must persist in memory for the -//! lifetime of attribute. \param Ch Character type to use. -template -class xml_attribute : public xml_base { - friend class xml_node; - - public: - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty attribute with the specified type. - //! Consider using memory_pool of appropriate xml_document if allocating - //! attributes manually. - xml_attribute() {} - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which attribute is a child. - //! \return Pointer to document that contains this attribute, or 0 if there is - //! no parent document. - xml_document* document() const { - if (xml_node* node = this->parent()) { - while (node->parent()) - node = node->parent(); - - return node->type() == node_document - ? static_cast*>(node) - : 0; - } else - return 0; - } - - //! Gets previous attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return previous attribute - //! regardless of its name; this string doesn't have to be zero-terminated if - //! name_size is non-zero \param name_size Size of name, in characters, or 0 - //! to have size calculated automatically from string \param case_sensitive - //! Should name comparison be case-sensitive; non case-sensitive comparison - //! works properly only for ASCII characters \return Pointer to found - //! attribute, or 0 if not found. - xml_attribute* previous_attribute(const Ch* name = 0, - std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_attribute* attribute = m_prev_attribute; attribute; - attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) - return attribute; - - return 0; - } else - return this->m_parent ? m_prev_attribute : 0; - } - - //! Gets next attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return next attribute - //! regardless of its name; this string doesn't have to be zero-terminated if - //! name_size is non-zero \param name_size Size of name, in characters, or 0 - //! to have size calculated automatically from string \param case_sensitive - //! Should name comparison be case-sensitive; non case-sensitive comparison - //! works properly only for ASCII characters \return Pointer to found - //! attribute, or 0 if not found. - xml_attribute* next_attribute(const Ch* name = 0, - std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_attribute* attribute = m_next_attribute; attribute; - attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) - return attribute; - - return 0; - } else - return this->m_parent ? m_next_attribute : 0; - } - - private: - xml_attribute* - m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if - // none; only valid if parent is non-zero - xml_attribute* - m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; - // only valid if parent is non-zero -}; - -/////////////////////////////////////////////////////////////////////////// -// XML node - -//! Class representing a node of XML document. -//! Each node may have associated name and value strings, which are available -//! through name() and value() functions. Interpretation of name and value -//! depends on type of the node. Type of node can be determined by using type() -//! function.

Note that after parse, both name and value of node, if -//! any, will point interior of source text used for parsing. Thus, this text -//! must persist in the memory for the lifetime of node. \param Ch Character -//! type to use. -template -class xml_node : public xml_base { - public: - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty node with the specified type. - //! Consider using memory_pool of appropriate document to allocate nodes - //! manually. \param type Type of node to construct. - xml_node(node_type type) - : m_type(type), m_first_node(nullptr), m_first_attribute(nullptr) {} - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets type of node. - //! \return Type of node. - node_type type() const { return m_type; } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which node is a child. - //! \return Pointer to document that contains this node, or 0 if there is no - //! parent document. - xml_document* document() const { - xml_node* node = const_cast*>(this); - - while (node->parent()) - node = node->parent(); - - return node->type() == node_document ? static_cast*>(node) - : 0; - } - - //! Gets first child node, optionally matching node name. - //! \param name Name of child to find, or 0 to return first child regardless - //! of its name; this string doesn't have to be zero-terminated if name_size - //! is non-zero \param name_size Size of name, in characters, or 0 to have - //! size calculated automatically from string \param case_sensitive Should - //! name comparison be case-sensitive; non case-sensitive comparison works - //! properly only for ASCII characters \return Pointer to found child, or 0 if - //! not found. - xml_node* first_node(const Ch* name = nullptr, - std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_node* child = m_first_node; child; - child = child->next_sibling()) - if (internal::compare(child->name(), child->name_size(), name, - name_size, case_sensitive)) - return child; - - return nullptr; - } else - return m_first_node; - } - - //! Gets last child node, optionally matching node name. - //! Behaviour is undefined if node has no children. - //! Use first_node() to test if node has children. - //! \param name Name of child to find, or 0 to return last child regardless of - //! its name; this string doesn't have to be zero-terminated if name_size is - //! non-zero \param name_size Size of name, in characters, or 0 to have size - //! calculated automatically from string \param case_sensitive Should name - //! comparison be case-sensitive; non case-sensitive comparison works properly - //! only for ASCII characters \return Pointer to found child, or 0 if not - //! found. - xml_node* last_node(const Ch* name = nullptr, - std::size_t name_size = 0, - bool case_sensitive = true) const { - assert( - m_first_node); // Cannot query for last child if node has no children - - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_node* child = m_last_node; child; - child = child->previous_sibling()) - if (internal::compare(child->name(), child->name_size(), name, - name_size, case_sensitive)) - return child; - - return nullptr; - } else - return m_last_node; - } - - //! Gets previous sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return previous sibling - //! regardless of its name; this string doesn't have to be zero-terminated if - //! name_size is non-zero \param name_size Size of name, in characters, or 0 - //! to have size calculated automatically from string \param case_sensitive - //! Should name comparison be case-sensitive; non case-sensitive comparison - //! works properly only for ASCII characters \return Pointer to found sibling, - //! or 0 if not found. - xml_node* previous_sibling(const Ch* name = nullptr, - std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent - - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_node* sibling = m_prev_sibling; sibling; - sibling = sibling->m_prev_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, - name_size, case_sensitive)) - return sibling; - - return nullptr; - } else - return m_prev_sibling; - } - - //! Gets next sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return next sibling - //! regardless of its name; this string doesn't have to be zero-terminated if - //! name_size is non-zero \param name_size Size of name, in characters, or 0 - //! to have size calculated automatically from string \param case_sensitive - //! Should name comparison be case-sensitive; non case-sensitive comparison - //! works properly only for ASCII characters \return Pointer to found sibling, - //! or 0 if not found. - xml_node* next_sibling(const Ch* name = nullptr, - std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent - - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_node* sibling = m_next_sibling; sibling; - sibling = sibling->m_next_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, - name_size, case_sensitive)) - return sibling; - - return nullptr; - } else - return m_next_sibling; - } - - //! Gets first attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return first attribute - //! regardless of its name; this string doesn't have to be zero-terminated if - //! name_size is non-zero \param name_size Size of name, in characters, or 0 - //! to have size calculated automatically from string \param case_sensitive - //! Should name comparison be case-sensitive; non case-sensitive comparison - //! works properly only for ASCII characters \return Pointer to found - //! attribute, or 0 if not found. - xml_attribute* first_attribute(const Ch* name = nullptr, - std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_attribute* attribute = m_first_attribute; attribute; - attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) - return attribute; - - return nullptr; - } else - return m_first_attribute; - } - - //! Gets last attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return last attribute - //! regardless of its name; this string doesn't have to be zero-terminated if - //! name_size is non-zero \param name_size Size of name, in characters, or 0 - //! to have size calculated automatically from string \param case_sensitive - //! Should name comparison be case-sensitive; non case-sensitive comparison - //! works properly only for ASCII characters \return Pointer to found - //! attribute, or 0 if not found. - xml_attribute* last_attribute(const Ch* name = 0, - std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) - name_size = internal::measure(name); - - for (xml_attribute* attribute = m_last_attribute; attribute; - attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) - return attribute; - - return nullptr; - } else - return m_first_attribute ? m_last_attribute : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets type of node. - //! \param type Type of node to set. - void type(node_type type) { m_type = type; } - - /////////////////////////////////////////////////////////////////////////// - // Node manipulation - - //! Prepends a new child node. - //! The prepended child becomes the first child, and all existing children are - //! moved one position back. \param child Node to prepend. - void prepend_node(xml_node* child) { - assert(child && !child->parent() && child->type() != node_document); - - if (first_node()) { - child->m_next_sibling = m_first_node; - m_first_node->m_prev_sibling = child; - } else { - child->m_next_sibling = 0; - m_last_node = child; - } - - m_first_node = child; - child->m_parent = this; - child->m_prev_sibling = 0; - } - - //! Appends a new child node. - //! The appended child becomes the last child. - //! \param child Node to append. - void append_node(xml_node* child) { - assert(child && !child->parent() && child->type() != node_document); - - if (first_node()) { - child->m_prev_sibling = m_last_node; - m_last_node->m_next_sibling = child; - } else { - child->m_prev_sibling = nullptr; - m_first_node = child; - } - - m_last_node = child; - child->m_parent = this; - child->m_next_sibling = nullptr; - } - - //! Inserts a new child node at specified place inside the node. - //! All children after and including the specified node are moved one position - //! back. \param where Place where to insert the child, or 0 to insert at the - //! back. \param child Node to insert. - void insert_node(xml_node* where, xml_node* child) { - assert(!where || where->parent() == this); - assert(child && !child->parent() && child->type() != node_document); - - if (where == m_first_node) - prepend_node(child); - else if (where == 0) - append_node(child); - else { - child->m_prev_sibling = where->m_prev_sibling; - child->m_next_sibling = where; - where->m_prev_sibling->m_next_sibling = child; - where->m_prev_sibling = child; - child->m_parent = this; - } - } - - //! Removes first child node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_first_node() { - assert(first_node()); - xml_node* child = m_first_node; - m_first_node = child->m_next_sibling; - - if (child->m_next_sibling) - child->m_next_sibling->m_prev_sibling = 0; - else - m_last_node = 0; - - child->m_parent = 0; - } - - //! Removes last child of the node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_last_node() { - assert(first_node()); - xml_node* child = m_last_node; - - if (child->m_prev_sibling) { - m_last_node = child->m_prev_sibling; - child->m_prev_sibling->m_next_sibling = 0; - } else - m_first_node = 0; - - child->m_parent = 0; - } - - //! Removes specified child from the node - // \param where Pointer to child to be removed. - void remove_node(xml_node* where) { - assert(where && where->parent() == this); - assert(first_node()); - - if (where == m_first_node) - remove_first_node(); - else if (where == m_last_node) - remove_last_node(); - else { - where->m_prev_sibling->m_next_sibling = where->m_next_sibling; - where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; - where->m_parent = 0; - } - } - - //! Removes all child nodes (but not attributes). - void remove_all_nodes() { - for (xml_node* node = first_node(); node; node = node->m_next_sibling) - node->m_parent = nullptr; - - m_first_node = nullptr; - } - - //! Prepends a new attribute to the node. - //! \param attribute Attribute to prepend. - void prepend_attribute(xml_attribute* attribute) { - assert(attribute && !attribute->parent()); - - if (first_attribute()) { - attribute->m_next_attribute = m_first_attribute; - m_first_attribute->m_prev_attribute = attribute; - } else { - attribute->m_next_attribute = nullptr; - m_last_attribute = attribute; - } - - m_first_attribute = attribute; - attribute->m_parent = this; - attribute->m_prev_attribute = nullptr; - } - - //! Appends a new attribute to the node. - //! \param attribute Attribute to append. - void append_attribute(xml_attribute* attribute) { - assert(attribute && !attribute->parent()); - - if (first_attribute()) { - attribute->m_prev_attribute = m_last_attribute; - m_last_attribute->m_next_attribute = attribute; - } else { - attribute->m_prev_attribute = nullptr; - m_first_attribute = attribute; - } - - m_last_attribute = attribute; - attribute->m_parent = this; - attribute->m_next_attribute = nullptr; - } - - //! Inserts a new attribute at specified place inside the node. - //! All attributes after and including the specified attribute are moved one - //! position back. \param where Place where to insert the attribute, or 0 to - //! insert at the back. \param attribute Attribute to insert. - void insert_attribute(xml_attribute* where, - xml_attribute* attribute) { - assert(!where || where->parent() == this); - assert(attribute && !attribute->parent()); - - if (where == m_first_attribute) - prepend_attribute(attribute); - else if (where == 0) - append_attribute(attribute); - else { - attribute->m_prev_attribute = where->m_prev_attribute; - attribute->m_next_attribute = where; - where->m_prev_attribute->m_next_attribute = attribute; - where->m_prev_attribute = attribute; - attribute->m_parent = this; - } - } - - //! Removes first attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_first_attribute() { - assert(first_attribute()); - xml_attribute* attribute = m_first_attribute; - - if (attribute->m_next_attribute) { - attribute->m_next_attribute->m_prev_attribute = 0; - } else - m_last_attribute = 0; - - attribute->m_parent = 0; - m_first_attribute = attribute->m_next_attribute; - } - - //! Removes last attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_last_attribute() { - assert(first_attribute()); - xml_attribute* attribute = m_last_attribute; - - if (attribute->m_prev_attribute) { - attribute->m_prev_attribute->m_next_attribute = 0; - m_last_attribute = attribute->m_prev_attribute; - } else - m_first_attribute = 0; - - attribute->m_parent = 0; - } - - //! Removes specified attribute from node. - //! \param where Pointer to attribute to be removed. - void remove_attribute(xml_attribute* where) { - assert(first_attribute() && where->parent() == this); - - if (where == m_first_attribute) - remove_first_attribute(); - else if (where == m_last_attribute) - remove_last_attribute(); - else { - where->m_prev_attribute->m_next_attribute = where->m_next_attribute; - where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; - where->m_parent = 0; - } - } - - //! Removes all attributes of node. - void remove_all_attributes() { - for (xml_attribute* attribute = first_attribute(); attribute; - attribute = attribute->m_next_attribute) - attribute->m_parent = nullptr; - - m_first_attribute = nullptr; - } - - private: - /////////////////////////////////////////////////////////////////////////// - // Restrictions - - // No copying - xml_node(const xml_node&); - void operator=(const xml_node&); - - /////////////////////////////////////////////////////////////////////////// - // Data members - - // Note that some of the pointers below have UNDEFINED values if certain other - // pointers are 0. This is required for maximum performance, as it allows the - // parser to omit initialization of unneded/redundant values. - // - // The rules are as follows: - // 1. first_node and first_attribute contain valid pointers, or 0 if node has - // no children/attributes respectively - // 2. last_node and last_attribute are valid only if node has at least one - // child/attribute respectively, otherwise they contain garbage - // 3. prev_sibling and next_sibling are valid only if node has a parent, - // otherwise they contain garbage - - node_type m_type; // Type of node; always valid - xml_node* - m_first_node; // Pointer to first child node, or 0 if none; always valid - xml_node* m_last_node; // Pointer to last child node, or 0 if none; this - // value is only valid if m_first_node is non-zero - xml_attribute* m_first_attribute; // Pointer to first attribute of node, - // or 0 if none; always valid - xml_attribute* m_last_attribute; // Pointer to last attribute of node, or - // 0 if none; this value is only valid - // if m_first_attribute is non-zero - xml_node* - m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; - // this value is only valid if m_parent is non-zero - xml_node* - m_next_sibling; // Pointer to next sibling of node, or 0 if none; this - // value is only valid if m_parent is non-zero -}; - -/////////////////////////////////////////////////////////////////////////// -// XML document - -//! This class represents root of the DOM hierarchy. -//! It is also an xml_node and a memory_pool through public inheritance. -//! Use parse() function to build a DOM tree from a zero-terminated XML text -//! string. parse() function allocates memory for nodes and attributes by using -//! functions of xml_document, which are inherited from memory_pool. To access -//! root node of the document, use the document itself, as if it was an -//! xml_node. \param Ch Character type to use. -template -class xml_document : public xml_node, public memory_pool { - public: - //! Constructs empty XML document - xml_document() : xml_node(node_document) {} - - //! Parses zero-terminated XML string according to given flags. - //! Passed string will be modified by the parser, unless - //! rapidxml::parse_non_destructive flag is used. The string must persist for - //! the lifetime of the document. In case of error, rapidxml::parse_error - //! exception will be thrown.

If you want to parse contents of a - //! file, you must first load the file into the memory, and pass pointer to - //! its beginning. Make sure that data is zero-terminated.

Document - //! can be parsed into multiple times. Each new call to parse removes previous - //! nodes and attributes (if any), but does not clear memory pool. \param text - //! XML data to parse; pointer is non-const to denote fact that this data may - //! be modified by the parser. - template - void parse(Ch* text) { - assert(text); - - // Remove current contents - this->remove_all_nodes(); - this->remove_all_attributes(); - - // Parse BOM, if any - parse_bom(text); - - // Parse children - while (1) { - // Skip whitespace before node - skip(text); - - if (*text == 0) - break; - - // Parse and append new child - if (*text == Ch('<')) { - ++text; // Skip '<' - - if (xml_node* node = parse_node(text)) - this->append_node(node); - } else - RAPIDXML_PARSE_ERROR("expected <", text); - } - } - - //! Clears the document by deleting all nodes and clearing the memory pool. - //! All nodes owned by document pool are destroyed. - void clear() { - this->remove_all_nodes(); - this->remove_all_attributes(); - memory_pool::clear(); - } - - private: - /////////////////////////////////////////////////////////////////////// - // Internal character utility functions - - // Detect whitespace character - struct whitespace_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables< - 0>::lookup_whitespace[static_cast(ch)]; - } - }; - - // Detect node name character - struct node_name_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables< - 0>::lookup_node_name[static_cast(ch)]; - } - }; - - // Detect attribute name character - struct attribute_name_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables< - 0>::lookup_attribute_name[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) - struct text_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text[static_cast( - ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_no_ws_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables< - 0>::lookup_text_pure_no_ws[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_with_ws_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables< - 0>::lookup_text_pure_with_ws[static_cast(ch)]; - } - }; - - // Detect attribute value character - template - struct attribute_value_pred { - static unsigned char test(Ch ch) { - if (Quote == Ch('\'')) - return internal::lookup_tables< - 0>::lookup_attribute_data_1[static_cast(ch)]; - - if (Quote == Ch('\"')) - return internal::lookup_tables< - 0>::lookup_attribute_data_2[static_cast(ch)]; - - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Detect attribute value character - template - struct attribute_value_pure_pred { - static unsigned char test(Ch ch) { - if (Quote == Ch('\'')) - return internal::lookup_tables< - 0>::lookup_attribute_data_1_pure[static_cast(ch)]; - - if (Quote == Ch('\"')) - return internal::lookup_tables< - 0>::lookup_attribute_data_2_pure[static_cast(ch)]; - - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Insert coded character, using UTF8 or 8-bit ASCII - template - static void insert_coded_character(Ch*& text, unsigned long code) { - if (Flags & parse_no_utf8) { - // Insert 8-bit ASCII character - // Todo: possibly verify that code is less than 256 and use replacement - // char otherwise? - text[0] = static_cast(code); - text += 1; - } else { - // Insert UTF8 sequence - if (code < 0x80) { // 1 byte sequence - text[0] = static_cast(code); - text += 1; - } else if (code < 0x800) { // 2 byte sequence - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xC0); - text += 2; - } else if (code < 0x10000) { // 3 byte sequence - text[2] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xE0); - text += 3; - } else if (code < 0x110000) { // 4 byte sequence - text[3] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[2] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xF0); - text += 4; - } else { // Invalid, only codes up to 0x10FFFF are allowed in Unicode - RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); - } - } - } - - // Skip characters until predicate evaluates to true - template - static void skip(Ch*& text) { - Ch* tmp = text; - - while (StopPred::test(*tmp)) - ++tmp; - - text = tmp; - } - - // Skip characters until predicate evaluates to true while doing the - // following: - // - replacing XML character entity references with proper characters (' - // & " < > &#...;) - // - condensing whitespace sequences to single space character - template - static Ch* skip_and_expand_character_refs(Ch*& text) { - // If entity translation, whitespace condense and whitespace trimming is - // disabled, use plain skip - if (Flags & parse_no_entity_translation && - !(Flags & parse_normalize_whitespace) && - !(Flags & parse_trim_whitespace)) { - skip(text); - return text; - } - - // Use simple skip until first modification is detected - skip(text); - - // Use translation skip - Ch* src = text; - Ch* dest = src; - - while (StopPred::test(*src)) { - // If entity translation is enabled - if (!(Flags & parse_no_entity_translation)) { - // Test if replacement is needed - if (src[0] == Ch('&')) { - switch (src[1]) { - // & ' - case Ch('a'): - if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { - *dest = Ch('&'); - ++dest; - src += 5; - continue; - } - - if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && - src[5] == Ch(';')) { - *dest = Ch('\''); - ++dest; - src += 6; - continue; - } - - break; - - // " - case Ch('q'): - if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && - src[5] == Ch(';')) { - *dest = Ch('"'); - ++dest; - src += 6; - continue; - } - - break; - - // > - case Ch('g'): - if (src[2] == Ch('t') && src[3] == Ch(';')) { - *dest = Ch('>'); - ++dest; - src += 4; - continue; - } - - break; - - // < - case Ch('l'): - if (src[2] == Ch('t') && src[3] == Ch(';')) { - *dest = Ch('<'); - ++dest; - src += 4; - continue; - } - - break; - - // &#...; - assumes ASCII - case Ch('#'): - if (src[2] == Ch('x')) { - unsigned long code = 0; - src += 3; // Skip &#x - - while (1) { - unsigned char digit = internal::lookup_tables< - 0>::lookup_digits[static_cast(*src)]; - - if (digit == 0xFF) - break; - - code = code * 16 + digit; - ++src; - } - - insert_coded_character(dest, - code); // Put character in output - } else { - unsigned long code = 0; - src += 2; // Skip &# - - while (1) { - unsigned char digit = internal::lookup_tables< - 0>::lookup_digits[static_cast(*src)]; - - if (digit == 0xFF) - break; - - code = code * 10 + digit; - ++src; - } - - insert_coded_character(dest, - code); // Put character in output - } - - if (*src == Ch(';')) - ++src; - else - RAPIDXML_PARSE_ERROR("expected ;", src); - - continue; - - // Something else - default: - // Ignore, just copy '&' verbatim - break; - } - } - } - - // If whitespace condensing is enabled - if (Flags & parse_normalize_whitespace) { - // Test if condensing is needed - if (whitespace_pred::test(*src)) { - *dest = Ch(' '); - ++dest; // Put single space in dest - ++src; // Skip first whitespace char - - // Skip remaining whitespace chars - while (whitespace_pred::test(*src)) - ++src; - - continue; - } - } - - // No replacement, only copy character - *dest++ = *src++; - } - - // Return new end - text = src; - return dest; - } - - /////////////////////////////////////////////////////////////////////// - // Internal parsing functions - - // Parse BOM, if any - template - void parse_bom(Ch*& text) { - // UTF-8? - if (static_cast(text[0]) == 0xEF && - static_cast(text[1]) == 0xBB && - static_cast(text[2]) == 0xBF) { - text += 3; // Skup utf-8 bom - } - } - - // Parse XML declaration ( - xml_node* parse_xml_declaration(Ch*& text) { - // If parsing of declaration is disabled - if (!(Flags & parse_declaration_node)) { - // Skip until end of declaration - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - text += 2; // Skip '?>' - return nullptr; - } - - // Create declaration - xml_node* declaration = this->allocate_node(node_declaration); - - // Skip whitespace before attributes or ?> - skip(text); - - // Parse declaration attributes - parse_node_attributes(text, declaration); - - // Skip ?> - if (text[0] != Ch('?') || text[1] != Ch('>')) - RAPIDXML_PARSE_ERROR("expected ?>", text); - - text += 2; - - return declaration; - } - - // Parse XML comment (' - return nullptr; // Do not produce comment node - } - - // Remember value start - Ch* value = text; - - // Skip until end of comment - while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - // Create comment node - xml_node* comment = this->allocate_node(node_comment); - comment->value(value, text - value); - - // Place zero terminator after comment value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 3; // Skip '-->' - return comment; - } - - // Parse DOCTYPE - template - xml_node* parse_doctype(Ch*& text) { - // Remember value start - Ch* value = text; - - // Skip to > - while (*text != Ch('>')) { - // Determine character type - switch (*text) { - // If '[' encountered, scan for matching ending ']' using naive - // algorithm with depth This works for all W3C test files except for 2 - // most wicked - case Ch('['): { - ++text; // Skip '[' - int depth = 1; - - while (depth > 0) { - switch (*text) { - case Ch('['): - ++depth; - break; - - case Ch(']'): - --depth; - break; - - case 0: - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - default: - break; - } - - ++text; - } - - break; - } - - // Error on end of text - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Other character, skip it - default: - ++text; - } - } - - // If DOCTYPE nodes enabled - if (Flags & parse_doctype_node) { - // Create a new doctype node - xml_node* doctype = this->allocate_node(node_doctype); - doctype->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 1; // skip '>' - return doctype; - } else { - text += 1; // skip '>' - return nullptr; - } - } - - // Parse PI - template - xml_node* parse_pi(Ch*& text) { - // If creation of PI nodes is enabled - if (Flags & parse_pi_nodes) { - // Create pi node - xml_node* pi = this->allocate_node(node_pi); - - // Extract PI target name - Ch* name = text; - skip(text); - - if (text == name) - RAPIDXML_PARSE_ERROR("expected PI target", text); - - pi->name(name, text - name); - - // Skip whitespace between pi target and pi - skip(text); - - // Remember start of pi - Ch* value = text; - - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - // Set pi value (verbatim, no entity expansion or whitespace - // normalization) - pi->value(value, text - value); - - // Place zero terminator after name and value - if (!(Flags & parse_no_string_terminators)) { - pi->name()[pi->name_size()] = Ch('\0'); - pi->value()[pi->value_size()] = Ch('\0'); - } - - text += 2; // Skip '?>' - return pi; - } else { - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - text += 2; // Skip '?>' - return nullptr; - } - } - - // Parse and append data - // Return character that ends data. - // This is necessary because this character might have been overwritten by a - // terminating 0 - template - Ch parse_and_append_data(xml_node* node, Ch*& text, Ch* contents_start) { - // Backup to contents start if whitespace trimming is disabled - if (!(Flags & parse_trim_whitespace)) - text = contents_start; - - // Skip until end of data - Ch *value = text, *end; - - if (Flags & parse_normalize_whitespace) - end = skip_and_expand_character_refs(text); - else - end = skip_and_expand_character_refs(text); - - // Trim trailing whitespace if flag is set; leading was already trimmed by - // whitespace skip after > - if (Flags & parse_trim_whitespace) { - if (Flags & parse_normalize_whitespace) { - // Whitespace is already condensed to single space characters by - // skipping function, so just trim 1 char off the end - if (*(end - 1) == Ch(' ')) - --end; - } else { - // Backup until non-whitespace character is found - while (whitespace_pred::test(*(end - 1))) - --end; - } - } - - // If characters are still left between end and value (this test is only - // necessary if normalization is enabled) Create new data node - if (!(Flags & parse_no_data_nodes)) { - xml_node* data = this->allocate_node(node_data); - data->value(value, end - value); - node->append_node(data); - } - - // Add data to parent node if no data exists yet - if (!(Flags & parse_no_element_values)) - if (*node->value() == Ch('\0')) - node->value(value, end - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) { - Ch ch = *text; - *end = Ch('\0'); - return ch; // Return character that ends data; this is required because - // zero terminator overwritten it - } - - // Return character that ends data - return *text; - } - - // Parse CDATA - template - xml_node* parse_cdata(Ch*& text) { - // If CDATA is disabled - if (Flags & parse_no_data_nodes) { - // Skip until end of cdata - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - text += 3; // Skip ]]> - return nullptr; // Do not produce CDATA node - } - - // Skip until end of cdata - Ch* value = text; - - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - // Create new cdata node - xml_node* cdata = this->allocate_node(node_cdata); - cdata->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 3; // Skip ]]> - return cdata; - } - - // Parse element node - template - xml_node* parse_element(Ch*& text) { - // Create element node - xml_node* element = this->allocate_node(node_element); - - // Extract element name - Ch* name = text; - skip(text); - - if (text == name) - RAPIDXML_PARSE_ERROR("expected element name", text); - - element->name(name, text - name); - - // Skip whitespace between element name and attributes or > - skip(text); - - // Parse attributes, if any - parse_node_attributes(text, element); - - // Determine ending type - if (*text == Ch('>')) { - ++text; - parse_node_contents(text, element); - } else if (*text == Ch('/')) { - ++text; - - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - - ++text; - } else - RAPIDXML_PARSE_ERROR("expected >", text); - - // Place zero terminator after name - if (!(Flags & parse_no_string_terminators)) - element->name()[element->name_size()] = Ch('\0'); - - // Return parsed element - return element; - } - - // Determine node type, and parse it - template - xml_node* parse_node(Ch*& text) { - // Parse proper node type - switch (text[0]) { - // <... - default: - // Parse and append element node - return parse_element(text); - - // (text); - } else { - // Parse PI - return parse_pi(text); - } - - // (text); - } - - break; - - // (text); - } - - break; - - // (text); - } - - break; - - default: - break; - } // switch - - // Attempt to skip other, unrecognized node types starting with ')) { - if (*text == 0) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - ++text; - } - - ++text; // Skip '>' - return nullptr; // No node recognized - } - } - - // Parse contents of the node - children, data etc. - template - void parse_node_contents(Ch*& text, xml_node* node) { - // For all children and text - while (1) { - // Skip whitespace between > and node contents - Ch* contents_start = - text; // Store start of node contents before whitespace is skipped - skip(text); - Ch next_char = *text; - - // After data nodes, instead of continuing the loop, control jumps here. - // This is because zero termination inside parse_and_append_data() - // function would wreak havoc with the above code. Also, skipping - // whitespace after data nodes is unnecessary. - after_data_node: - - // Determine what comes next: node closing, child node, data node, or 0? - switch (next_char) { - // Node closing or child node - case Ch('<'): - if (text[1] == Ch('/')) { - // Node closing - text += 2; // Skip '(text); - - if (!internal::compare(node->name(), node->name_size(), - closing_name, text - closing_name, true)) - RAPIDXML_PARSE_ERROR("invalid closing tag name", text); - } else { - // No validation, just skip name - skip(text); - } - - // Skip remaining whitespace after node name - skip(text); - - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - - ++text; // Skip '>' - return; // Node closed, finished parsing contents - } else { - // Child node - ++text; // Skip '<' - - if (xml_node* child = parse_node(text)) - node->append_node(child); - } - - break; - - // End of data - error - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Data node - default: - next_char = parse_and_append_data(node, text, contents_start); - goto after_data_node; // Bypass regular processing after data nodes - } - } - } - - // Parse XML attributes of the node - template - void parse_node_attributes(Ch*& text, xml_node* node) { - // For all attributes - while (attribute_name_pred::test(*text)) { - // Extract attribute name - Ch* name = text; - ++text; // Skip first character of attribute name - skip(text); - - if (text == name) - RAPIDXML_PARSE_ERROR("expected attribute name", name); - - // Create new attribute - xml_attribute* attribute = this->allocate_attribute(); - attribute->name(name, text - name); - node->append_attribute(attribute); - - // Skip whitespace after attribute name - skip(text); - - // Skip = - if (*text != Ch('=')) - RAPIDXML_PARSE_ERROR("expected =", text); - - ++text; - - // Add terminating zero after name - if (!(Flags & parse_no_string_terminators)) - attribute->name()[attribute->name_size()] = 0; - - // Skip whitespace after = - skip(text); - - // Skip quote and remember if it was ' or " - Ch quote = *text; - - if (quote != Ch('\'') && quote != Ch('"')) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - - ++text; - - // Extract attribute value and expand char refs in it - Ch *value = text, *end; - const int AttFlags = - Flags & ~parse_normalize_whitespace; // No whitespace normalization - // in attributes - - if (quote == Ch('\'')) - end = - skip_and_expand_character_refs, - attribute_value_pure_pred, - AttFlags>(text); - else - end = skip_and_expand_character_refs, - attribute_value_pure_pred, - AttFlags>(text); - - // Set attribute value - attribute->value(value, end - value); - - // Make sure that end quote is present - if (*text != quote) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - - ++text; // Skip quote - - // Add terminating zero after value - if (!(Flags & parse_no_string_terminators)) - attribute->value()[attribute->value_size()] = 0; - - // Skip whitespace after attribute value - skip(text); - } - } -}; - -//! \cond internal -namespace internal { - -// Whitespace (space \n \r \t) -template -const unsigned char lookup_tables::lookup_whitespace[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F -}; - -// Node name (anything but space \n \r \t / > ? \0) -template -const unsigned char lookup_tables::lookup_node_name[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Text (i.e. PCDATA) (anything but < \0) -template -const unsigned char lookup_tables::lookup_text[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Text (i.e. PCDATA) that does not require processing when ws normalization is -// disabled (anything but < \0 &) -template -const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Text (i.e. PCDATA) that does not require processing when ws normalizationis -// is enabled (anything but < \0 & space \n \r \t) -template -const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Attribute name (anything but space \n \r \t / < > = ? ! \0) -template -const unsigned char lookup_tables::lookup_attribute_name[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Attribute data with single quote (anything but ' \0) -template -const unsigned char lookup_tables::lookup_attribute_data_1[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Attribute data with single quote that does not require processing (anything -// but ' \0 &) -template -const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Attribute data with double quote (anything but " \0) -template -const unsigned char lookup_tables::lookup_attribute_data_2[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Attribute data with double quote that does not require processing (anything -// but " \0 &) -template -const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F -}; - -// Digits (dec and hex, 255 denotes end of numeric character reference) -template -const unsigned char lookup_tables::lookup_digits[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 0 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 1 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 2 - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 255, 255, 255, 255, 255, 255, // 3 - 255, 10, 11, 12, 13, 14, 15, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 4 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 5 - 255, 10, 11, 12, 13, 14, 15, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 6 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 7 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 8 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // 9 - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // A - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // B - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // C - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // D - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, // E - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255 // F -}; - -// Upper case conversion -template -const unsigned char lookup_tables::lookup_upcase[256] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, // 0 - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, // 1 - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, // 2 - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, // 3 - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, // 4 - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, // 5 - 96, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, // 6 - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 123, 124, 125, 126, 127, // 7 - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, // 8 - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, // 9 - 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, // A - 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, // B - 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, // C - 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, // D - 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, // E - 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255 // F -}; -} // namespace internal -//! \endcond - -} // namespace rapidxml - -// Undefine internal macros -#undef RAPIDXML_PARSE_ERROR - -// On MSVC, restore warnings state -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif diff --git a/src/rapidxml/rapidxml_iterators.hpp b/src/rapidxml/rapidxml_iterators.hpp deleted file mode 100644 index c3c1bc2..0000000 --- a/src/rapidxml/rapidxml_iterators.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED -#define RAPIDXML_ITERATORS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_iterators.hpp This file contains rapidxml iterators - -#include "rapidxml.hpp" - -namespace rapidxml { - -//! Iterator of child nodes of xml_node -template -class node_iterator { - public: - typedef typename xml_node value_type; - typedef typename xml_node& reference; - typedef typename xml_node* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - node_iterator() : m_node(0) {} - - node_iterator(xml_node* node) : m_node(node->first_node()) {} - - reference operator*() const { - assert(m_node); - return *m_node; - } - - pointer operator->() const { - assert(m_node); - return m_node; - } - - node_iterator& operator++() { - assert(m_node); - m_node = m_node->next_sibling(); - return *this; - } - - node_iterator operator++(int) { - node_iterator tmp = *this; - ++this; - return tmp; - } - - node_iterator& operator--() { - assert(m_node && m_node->previous_sibling()); - m_node = m_node->previous_sibling(); - return *this; - } - - node_iterator operator--(int) { - node_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator==(const node_iterator& rhs) { return m_node == rhs.m_node; } - - bool operator!=(const node_iterator& rhs) { return m_node != rhs.m_node; } - - private: - xml_node* m_node; -}; - -//! Iterator of child attributes of xml_node -template -class attribute_iterator { - public: - typedef typename xml_attribute value_type; - typedef typename xml_attribute& reference; - typedef typename xml_attribute* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - attribute_iterator() : m_attribute(0) {} - - attribute_iterator(xml_node* node) - : m_attribute(node->first_attribute()) {} - - reference operator*() const { - assert(m_attribute); - return *m_attribute; - } - - pointer operator->() const { - assert(m_attribute); - return m_attribute; - } - - attribute_iterator& operator++() { - assert(m_attribute); - m_attribute = m_attribute->next_attribute(); - return *this; - } - - attribute_iterator operator++(int) { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - attribute_iterator& operator--() { - assert(m_attribute && m_attribute->previous_attribute()); - m_attribute = m_attribute->previous_attribute(); - return *this; - } - - attribute_iterator operator--(int) { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator==(const attribute_iterator& rhs) { - return m_attribute == rhs.m_attribute; - } - - bool operator!=(const attribute_iterator& rhs) { - return m_attribute != rhs.m_attribute; - } - - private: - xml_attribute* m_attribute; -}; - -} // namespace rapidxml - -#endif diff --git a/src/rapidxml/rapidxml_print.hpp b/src/rapidxml/rapidxml_print.hpp deleted file mode 100644 index 4dab5db..0000000 --- a/src/rapidxml/rapidxml_print.hpp +++ /dev/null @@ -1,540 +0,0 @@ -#ifndef RAPIDXML_PRINT_HPP_INCLUDED -#define RAPIDXML_PRINT_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_print.hpp This file contains rapidxml printer implementation - -#include "rapidxml.hpp" - -// Only include streams if not disabled -#ifndef RAPIDXML_NO_STREAMS -#include -#include -#endif - -namespace rapidxml { - -/////////////////////////////////////////////////////////////////////// -// Printing flags - -const int print_no_indenting = - 0x1; //!< Printer flag instructing the printer to suppress indenting of - //!< XML. See print() function. - -/////////////////////////////////////////////////////////////////////// -// Internal - -//! \cond internal -namespace internal { - -/////////////////////////////////////////////////////////////////////////// -// Internal character operations - -// Copy characters from given range to given output iterator -template -inline OutIt copy_chars(const Ch* begin, const Ch* end, OutIt out) { - while (begin != end) - *out++ = *begin++; - - return out; -} - -// Copy characters from given range to given output iterator and expand -// characters into references (< > ' " &) -template -inline OutIt copy_and_expand_chars(const Ch* begin, - const Ch* end, - Ch noexpand, - OutIt out) { - while (begin != end) { - if (*begin == noexpand) { - *out++ = *begin; // No expansion, copy character - } else { - switch (*begin) { - case Ch('<'): - *out++ = Ch('&'); - *out++ = Ch('l'); - *out++ = Ch('t'); - *out++ = Ch(';'); - break; - - case Ch('>'): - *out++ = Ch('&'); - *out++ = Ch('g'); - *out++ = Ch('t'); - *out++ = Ch(';'); - break; - - case Ch('\''): - *out++ = Ch('&'); - *out++ = Ch('a'); - *out++ = Ch('p'); - *out++ = Ch('o'); - *out++ = Ch('s'); - *out++ = Ch(';'); - break; - - case Ch('"'): - *out++ = Ch('&'); - *out++ = Ch('q'); - *out++ = Ch('u'); - *out++ = Ch('o'); - *out++ = Ch('t'); - *out++ = Ch(';'); - break; - - case Ch('&'): - *out++ = Ch('&'); - *out++ = Ch('a'); - *out++ = Ch('m'); - *out++ = Ch('p'); - *out++ = Ch(';'); - break; - - default: - *out++ = *begin; // No expansion, copy character - } - } - - ++begin; // Step to next character - } - - return out; -} - -// Fill given output iterator with repetitions of the same character -template -inline OutIt fill_chars(OutIt out, int n, Ch ch) { - for (int i = 0; i < n; ++i) - *out++ = ch; - - return out; -} - -// Find character -template -inline bool find_char(const Ch* begin, const Ch* end) { - while (begin != end) - if (*begin++ == ch) - return true; - - return false; -} - -/////////////////////////////////////////////////////////////////////////// -// Internal printing operations -template -inline OutIt print_children(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_attributes(OutIt out, const xml_node* node, int flags); - -template -inline OutIt print_data_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_cdata_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_element_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_declaration_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_comment_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_doctype_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -template -inline OutIt print_pi_node(OutIt out, - const xml_node* node, - int flags, - int indent); - -// Print node -template -inline OutIt print_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - // Print proper node type - switch (node->type()) { - // Document - case node_document: - out = print_children(out, node, flags, indent); - break; - - // Element - case node_element: - out = print_element_node(out, node, flags, indent); - break; - - // Data - case node_data: - out = print_data_node(out, node, flags, indent); - break; - - // CDATA - case node_cdata: - out = print_cdata_node(out, node, flags, indent); - break; - - // Declaration - case node_declaration: - out = print_declaration_node(out, node, flags, indent); - break; - - // Comment - case node_comment: - out = print_comment_node(out, node, flags, indent); - break; - - // Doctype - case node_doctype: - out = print_doctype_node(out, node, flags, indent); - break; - - // Pi - case node_pi: - out = print_pi_node(out, node, flags, indent); - break; - - // Unknown - default: - assert(0); - break; - } - - // If indenting not disabled, add line break after node - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - - // Return modified iterator - return out; -} - -// Print children of the node -template -inline OutIt print_children(OutIt out, - const xml_node* node, - int flags, - int indent) { - for (xml_node* child = node->first_node(); child; - child = child->next_sibling()) - out = print_node(out, child, flags, indent); - - return out; -} - -// Print attributes of the node -template -inline OutIt print_attributes(OutIt out, const xml_node* node, int flags) { - for (xml_attribute* attribute = node->first_attribute(); attribute; - attribute = attribute->next_attribute()) { - if (attribute->name() && attribute->value()) { - // Print attribute name - *out = Ch(' '), ++out; - out = copy_chars(attribute->name(), - attribute->name() + attribute->name_size(), out); - *out = Ch('='), ++out; - - // Print attribute value using appropriate quote type - if (find_char( - attribute->value(), - attribute->value() + attribute->value_size())) { - *out = Ch('\''), ++out; - out = copy_and_expand_chars( - attribute->value(), attribute->value() + attribute->value_size(), - Ch('"'), out); - *out = Ch('\''), ++out; - } else { - *out = Ch('"'), ++out; - out = copy_and_expand_chars( - attribute->value(), attribute->value() + attribute->value_size(), - Ch('\''), out); - *out = Ch('"'), ++out; - } - } - } - - return out; -} - -// Print data node -template -inline OutIt print_data_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - assert(node->type() == node_data); - - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), - Ch(0), out); - return out; -} - -// Print data node -template -inline OutIt print_cdata_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - assert(node->type() == node_cdata); - - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - *out = Ch('<'); - ++out; - *out = Ch('!'); - ++out; - *out = Ch('['); - ++out; - *out = Ch('C'); - ++out; - *out = Ch('D'); - ++out; - *out = Ch('A'); - ++out; - *out = Ch('T'); - ++out; - *out = Ch('A'); - ++out; - *out = Ch('['); - ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch(']'); - ++out; - *out = Ch(']'); - ++out; - *out = Ch('>'); - ++out; - return out; -} - -// Print element node -template -inline OutIt print_element_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - assert(node->type() == node_element); - - // Print element name and attributes, if any - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - *out = Ch('<'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - out = print_attributes(out, node, flags); - - // If node is childless - if (node->value_size() == 0 && !node->first_node()) { - // Print childless node tag ending - *out = Ch('/'), ++out; - *out = Ch('>'), ++out; - } else { - // Print normal node tag ending - *out = Ch('>'), ++out; - - // Test if node contains a single data node only (and no other nodes) - xml_node* child = node->first_node(); - - if (!child) { - // If node has no children, only print its value without indenting - out = copy_and_expand_chars( - node->value(), node->value() + node->value_size(), Ch(0), out); - } else if (child->next_sibling() == 0 && child->type() == node_data) { - // If node has a sole data child, only print its value without indenting - out = copy_and_expand_chars( - child->value(), child->value() + child->value_size(), Ch(0), out); - } else { - // Print all children with full indenting - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - - out = print_children(out, node, flags, indent + 1); - - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - } - - // Print node end - *out = Ch('<'), ++out; - *out = Ch('/'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch('>'), ++out; - } - - return out; -} - -// Print declaration node -template -inline OutIt print_declaration_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - // Print declaration start - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - *out = Ch('x'), ++out; - *out = Ch('m'), ++out; - *out = Ch('l'), ++out; - - // Print attributes - out = print_attributes(out, node, flags); - - // Print declaration end - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - - return out; -} - -// Print comment node -template -inline OutIt print_comment_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - assert(node->type() == node_comment); - - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - *out = Ch('>'), ++out; - return out; -} - -// Print doctype node -template -inline OutIt print_doctype_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - assert(node->type() == node_doctype); - - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('D'), ++out; - *out = Ch('O'), ++out; - *out = Ch('C'), ++out; - *out = Ch('T'), ++out; - *out = Ch('Y'), ++out; - *out = Ch('P'), ++out; - *out = Ch('E'), ++out; - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('>'), ++out; - return out; -} - -// Print pi node -template -inline OutIt print_pi_node(OutIt out, - const xml_node* node, - int flags, - int indent) { - assert(node->type() == node_pi); - - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - return out; -} - -} // namespace internal -//! \endcond - -/////////////////////////////////////////////////////////////////////////// -// Printing - -//! Prints XML to given output iterator. -//! \param out Output iterator to print to. -//! \param node Node to be printed. Pass xml_document to print entire document. -//! \param flags Flags controlling how XML is printed. -//! \return Output iterator pointing to position immediately after last -//! character of printed text. -template -inline OutIt print(OutIt out, const xml_node& node, int flags = 0) { - return internal::print_node(out, &node, flags, 0); -} - -#ifndef RAPIDXML_NO_STREAMS - -//! Prints XML to given output stream. -//! \param out Output stream to print to. -//! \param node Node to be printed. Pass xml_document to print entire document. -//! \param flags Flags controlling how XML is printed. -//! \return Output stream. -template -inline std::basic_ostream& print(std::basic_ostream& out, - const xml_node& node, - int flags = 0) { - print(std::ostream_iterator(out), node, flags); - return out; -} - -//! Prints formatted XML to given output stream. Uses default printing flags. -//! Use print() function to customize printing process. \param out Output stream -//! to print to. \param node Node to be printed. \return Output stream. -template -inline std::basic_ostream& operator<<(std::basic_ostream& out, - const xml_node& node) { - return print(out, node); -} - -#endif - -} // namespace rapidxml - -#endif diff --git a/src/rapidxml/rapidxml_utils.hpp b/src/rapidxml/rapidxml_utils.hpp deleted file mode 100644 index 1b305ca..0000000 --- a/src/rapidxml/rapidxml_utils.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef RAPIDXML_UTILS_HPP_INCLUDED -#define RAPIDXML_UTILS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities -//! that can be useful in certain simple scenarios. They should probably not be -//! used if maximizing performance is the main objective. - -#include -#include -#include -#include -#include "rapidxml.hpp" - -namespace rapidxml { - -//! Represents data loaded from a file -template -class file { - public: - //! Loads file into the memory. Data will be automatically destroyed by the - //! destructor. \param filename Filename to load. - file(const char* filename) { - using namespace std; - - // Open stream - basic_ifstream stream(filename, ios::binary); - - if (!stream) - throw runtime_error(string("cannot open file ") + filename); - - stream.unsetf(ios::skipws); - - // Determine stream size - stream.seekg(0, ios::end); - size_t size = stream.tellg(); - stream.seekg(0); - - // Load data and add terminating 0 - m_data.resize(size + 1); - stream.read(&m_data.front(), static_cast(size)); - m_data[size] = 0; - } - - //! Loads file into the memory. Data will be automatically destroyed by the - //! destructor \param stream Stream to load from - file(std::basic_istream& stream) { - using namespace std; - - // Load data and add terminating 0 - stream.unsetf(ios::skipws); - m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); - - if (stream.fail() || stream.bad()) - throw runtime_error("error reading stream"); - - m_data.push_back(0); - } - - //! Gets file data. - //! \return Pointer to data of file. - Ch* data() { return &m_data.front(); } - - //! Gets file data. - //! \return Pointer to data of file. - const Ch* data() const { return &m_data.front(); } - - //! Gets file data size. - //! \return Size of file data, in characters. - std::size_t size() const { return m_data.size(); } - - private: - std::vector m_data; // File data -}; - -//! Counts children of node. Time complexity is O(n). -//! \return Number of children of node -template -inline std::size_t count_children(xml_node* node) { - xml_node* child = node->first_node(); - std::size_t count = 0; - - while (child) { - ++count; - child = child->next_sibling(); - } - - return count; -} - -//! Counts attributes of node. Time complexity is O(n). -//! \return Number of attributes of node -template -inline std::size_t count_attributes(xml_node* node) { - xml_attribute* attr = node->first_attribute(); - std::size_t count = 0; - - while (attr) { - ++count; - attr = attr->next_attribute(); - } - - return count; -} - -} // namespace rapidxml - -#endif