00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038
00039 #include "Array.h"
00040 #include "util.h"
00041 #include "debug.h"
00042 #include "InternalErr.h"
00043 #include "escaping.h"
00044
00045 #include <algorithm>
00046 #include <functional>
00047
00048 using namespace std;
00049
00050 namespace libdap {
00051
00052 void
00053 Array::_duplicate(const Array &a)
00054 {
00055 _shape = a._shape;
00056 }
00057
00058
00059
00060
00061
00062
00063
00071 void
00072 Array::update_length(int)
00073 {
00074 int length = 1;
00075 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00076 length *= (*i).c_size > 0 ? (*i).c_size : 1;
00077 }
00078
00079 set_length(length);
00080 }
00081
00082
00083
00084
00100 Array::Array(const string &n, BaseType *v) : Vector(n, 0, dods_array_c)
00101 {
00102 add_var(v);
00103 }
00104
00106 Array::Array(const Array &rhs) : Vector(rhs)
00107 {
00108 _duplicate(rhs);
00109 }
00110
00112 Array::~Array()
00113 {
00114 DBG(cerr << "Entering ~Array (" << this << ")" << endl);
00115 DBG(cerr << "Exiting ~Array" << endl);
00116 }
00117
00118 BaseType *
00119 Array::ptr_duplicate()
00120 {
00121 return new Array(*this);
00122 }
00123
00124 Array &
00125 Array::operator=(const Array &rhs)
00126 {
00127 if (this == &rhs)
00128 return *this;
00129
00130 dynamic_cast<Vector &>(*this) = rhs;
00131
00132 _duplicate(rhs);
00133
00134 return *this;
00135 }
00136
00156 void
00157 Array::add_var(BaseType *v, Part)
00158 {
00159 if (v && v->type() == dods_array_c) {
00160 Array &a = dynamic_cast<Array&>(*v);
00161 Vector::add_var(a.var());
00162 Dim_iter i = a.dim_begin();
00163 Dim_iter i_end = a.dim_end();
00164 while (i != i_end) {
00165 append_dim(a.dimension_size(i), a.dimension_name(i));
00166 ++i;
00167 }
00168 }
00169 else {
00170 Vector::add_var(v);
00171 }
00172 }
00173
00185 void
00186 Array::append_dim(int size, string name)
00187 {
00188 dimension d;
00189
00190
00191 d.size = size;
00192 d.name = www2id(name);
00193
00194
00195 d.start = 0;
00196 d.stop = size - 1;
00197 d.stride = 1;
00198 d.c_size = size;
00199 #if 0
00200 d.selected = true;
00201 #endif
00202 _shape.push_back(d);
00203
00204 update_length(size);
00205 }
00206
00213 void
00214 Array::reset_constraint()
00215 {
00216 set_length(-1);
00217
00218 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00219 (*i).start = 0;
00220 (*i).stop = (*i).size - 1;
00221 (*i).stride = 1;
00222 (*i).c_size = (*i).size;
00223 #if 0
00224 (*i).selected = true;
00225 #endif
00226 update_length((*i).size);
00227 }
00228 }
00229
00230
00240 void
00241 Array::clear_constraint()
00242 {
00243 reset_constraint();
00244 #if 0
00245 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00246 (*i).start = 0;
00247 (*i).stop = 0;
00248 (*i).stride = 0;
00249 (*i).c_size = 0;
00250 (*i).selected = false;
00251 }
00252
00253 set_length(-1);
00254 #endif
00255 }
00256
00257
00258
00259 static const char *array_sss = \
00260 "Invalid constraint parameters: At least one of the start, stride or stop \n\
00261 specified do not match the array variable.";
00262
00282 void
00283 Array::add_constraint(Dim_iter i, int start, int stride, int stop)
00284 {
00285 dimension &d = *i ;
00286
00287
00288
00289
00290
00291 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
00292 throw Error(malformed_expr, array_sss);
00293
00294 if (((stop - start) / stride + 1) > d.size)
00295 throw Error(malformed_expr, array_sss);
00296
00297 d.start = start;
00298 d.stop = stop;
00299 d.stride = stride;
00300
00301 d.c_size = (stop - start) / stride + 1;
00302
00303 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
00304 #if 0
00305 d.selected = true;
00306 #endif
00307 update_length(d.c_size);
00308 }
00309
00311 Array::Dim_iter
00312 Array::dim_begin()
00313 {
00314 return _shape.begin() ;
00315 }
00316
00318 Array::Dim_iter
00319 Array::dim_end()
00320 {
00321 return _shape.end() ;
00322 }
00323
00333 unsigned int
00334 Array::dimensions(bool )
00335 {
00336 unsigned int dim = 0;
00337 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00338 dim++;
00339 #if 0
00340 if (constrained) {
00341 if ((*i).selected)
00342 dim++;
00343 }
00344 else {
00345 dim++;
00346 }
00347 #endif
00348 }
00349
00350 return dim;
00351 }
00352
00370 int
00371 Array::dimension_size(Dim_iter i, bool constrained)
00372 {
00373 int size = 0;
00374
00375 if (!_shape.empty()) {
00376 if (constrained)
00377 size = (*i).c_size;
00378 else
00379 size = (*i).size;
00380 }
00381
00382 #if 0
00383 if (constrained) {
00384 if ((*i).selected)
00385 size = (*i).c_size;
00386 else
00387 size = 0;
00388 }
00389 else
00390 size = (*i).size;
00391 #endif
00392
00393 return size;
00394 }
00395
00414 int
00415 Array::dimension_start(Dim_iter i, bool )
00416 {
00417 return (!_shape.empty()) ? (*i).start : 0;
00418
00419 #if 0
00420 int start = 0;
00421
00422 if (!_shape.empty())
00423 start = (*i).start;
00424
00425 #if array_selected
00426 if (constrained) {
00427 if ((*i).selected)
00428 start = (*i).start;
00429 else
00430 start = 0;
00431 }
00432 else
00433 start = (*i).start;
00434 #endif
00435
00436 return start;
00437 #endif
00438 }
00439
00458 int
00459 Array::dimension_stop(Dim_iter i, bool )
00460 {
00461 return (!_shape.empty()) ? (*i).stop : 0;
00462
00463 #if 0
00464 int stop = 0;
00465
00466 if (!_shape.empty())
00467 stop = (*i).stop;
00468
00469 #if array_selected
00470 if (constrained) {
00471 if ((*i).selected)
00472 stop = (*i).stop;
00473 else
00474 stop = 0;
00475 }
00476 else
00477 stop = (*i).stop;
00478 #endif
00479
00480 return stop;
00481 #endif
00482 }
00483
00503 int
00504 Array::dimension_stride(Dim_iter i, bool )
00505 {
00506 return (!_shape.empty()) ? (*i).stride : 0;
00507
00508 #if 0
00509 int stride = 0;
00510
00511 if (!_shape.empty())
00512 stride = (*i).stride;
00513
00514 #if array_selected
00515 if (constrained) {
00516 if ((*i).selected)
00517 stride = (*i).stride;
00518 else
00519 stride = 0;
00520 }
00521 else
00522 stride = (*i).stride;
00523 #endif
00524
00525 return stride;
00526 #endif
00527 }
00528
00539 string
00540 Array::dimension_name(Dim_iter i)
00541 {
00542
00543
00544
00545
00546
00547 if (_shape.empty())
00548 throw InternalErr(__FILE__, __LINE__,
00549 "*This* array has no dimensions.");
00550 return (*i).name;
00551 }
00552
00570 void
00571 Array::print_decl(FILE *out, string space, bool print_semi,
00572 bool constraint_info, bool constrained)
00573 {
00574 if (constrained && !send_p())
00575 return;
00576
00577
00578 var()->print_decl(out, space, false, constraint_info, constrained);
00579
00580 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00581 #if 0
00582 if (constrained && !((*i).selected))
00583 continue;
00584 #endif
00585 fprintf(out, "[") ;
00586 if ((*i).name != "") {
00587 fprintf(out, "%s = ", id2www((*i).name).c_str()) ;
00588 }
00589 if (constrained) {
00590 fprintf(out, "%d]", (*i).c_size) ;
00591 }
00592 else {
00593 fprintf(out, "%d]", (*i).size) ;
00594 }
00595 }
00596
00597 if (print_semi) {
00598 fprintf(out, ";\n") ;
00599 }
00600 }
00601
00619 void
00620 Array::print_decl(ostream &out, string space, bool print_semi,
00621 bool constraint_info, bool constrained)
00622 {
00623 if (constrained && !send_p())
00624 return;
00625
00626
00627 var()->print_decl(out, space, false, constraint_info, constrained);
00628
00629 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00630 #if 0
00631 if (constrained && !((*i).selected))
00632 continue;
00633 #endif
00634 out << "[" ;
00635 if ((*i).name != "") {
00636 out << id2www((*i).name) << " = " ;
00637 }
00638 if (constrained) {
00639 out << (*i).c_size << "]" ;
00640 }
00641 else {
00642 out << (*i).size << "]" ;
00643 }
00644 }
00645
00646 if (print_semi) {
00647 out << ";\n" ;
00648 }
00649 }
00650
00651 void
00652 Array::print_xml(FILE *out, string space, bool constrained)
00653 {
00654 print_xml_core(out, space, constrained, "Array");
00655 }
00656
00657 void
00658 Array::print_xml(ostream &out, string space, bool constrained)
00659 {
00660 print_xml_core(out, space, constrained, "Array");
00661 }
00662
00663 void
00664 Array::print_as_map_xml(FILE *out, string space, bool constrained)
00665 {
00666 print_xml_core(out, space, constrained, "Map");
00667 }
00668
00669 void
00670 Array::print_as_map_xml(ostream &out, string space, bool constrained)
00671 {
00672 print_xml_core(out, space, constrained, "Map");
00673 }
00674
00675 class PrintArrayDim : public unary_function<Array::dimension&, void>
00676 {
00677 FILE *d_out;
00678 string d_space;
00679 bool d_constrained;
00680 public:
00681 PrintArrayDim(FILE *o, string s, bool c)
00682 : d_out(o), d_space(s), d_constrained(c)
00683 {}
00684
00685 void operator()(Array::dimension &d)
00686 {
00687 int size = d_constrained ? d.c_size : d.size;
00688 if (d.name.empty())
00689 fprintf(d_out, "%s<dimension size=\"%d\"/>\n", d_space.c_str(),
00690 size);
00691 else
00692 fprintf(d_out, "%s<dimension name=\"%s\" size=\"%d\"/>\n",
00693 d_space.c_str(), id2xml(d.name).c_str(), size);
00694 }
00695 };
00696
00697 void
00698 Array::print_xml_core(FILE *out, string space, bool constrained, string tag)
00699 {
00700 if (constrained && !send_p())
00701 return;
00702
00703 fprintf(out, "%s<%s", space.c_str(), tag.c_str());
00704 if (!name().empty())
00705 fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00706 fprintf(out , ">\n");
00707
00708 get_attr_table().print_xml(out, space + " ", constrained);
00709
00710 BaseType *btp = var();
00711 string tmp_name = btp->name();
00712 btp->set_name("");
00713 btp->print_xml(out, space + " ", constrained);
00714 btp->set_name(tmp_name);
00715
00716 for_each(dim_begin(), dim_end(),
00717 PrintArrayDim(out, space + " ", constrained));
00718
00719 fprintf(out, "%s</%s>\n", space.c_str(), tag.c_str());
00720 }
00721
00722 class PrintArrayDimStrm : public unary_function<Array::dimension&, void>
00723 {
00724 ostream &d_out;
00725 string d_space;
00726 bool d_constrained;
00727 public:
00728 PrintArrayDimStrm(ostream &o, string s, bool c)
00729 : d_out(o), d_space(s), d_constrained(c)
00730 {}
00731
00732 void operator()(Array::dimension &d)
00733 {
00734 int size = d_constrained ? d.c_size : d.size;
00735 if (d.name.empty())
00736 d_out << d_space << "<dimension size=\"" << size << "\"/>\n" ;
00737 else
00738 d_out << d_space << "<dimension name=\"" << id2xml(d.name)
00739 << "\" size=\"" << size << "\"/>\n" ;
00740 }
00741 };
00742
00743 void
00744 Array::print_xml_core(ostream &out, string space, bool constrained, string tag)
00745 {
00746 if (constrained && !send_p())
00747 return;
00748
00749 out << space << "<" << tag ;
00750 if (!name().empty())
00751 out << " name=\"" << id2xml(name()) << "\"" ;
00752 out << ">\n" ;
00753
00754 get_attr_table().print_xml(out, space + " ", constrained);
00755
00756 BaseType *btp = var();
00757 string tmp_name = btp->name();
00758 btp->set_name("");
00759 btp->print_xml(out, space + " ", constrained);
00760 btp->set_name(tmp_name);
00761
00762 for_each(dim_begin(), dim_end(),
00763 PrintArrayDimStrm(out, space + " ", constrained));
00764
00765 out << space << "</" << tag << ">\n" ;
00766 }
00767
00778 unsigned int
00779 Array::print_array(FILE *out, unsigned int index, unsigned int dims,
00780 unsigned int shape[])
00781 {
00782 if (dims == 1) {
00783 fprintf(out, "{") ;
00784 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00785 var(index++)->print_val(out, "", false);
00786 fprintf(out, ", ") ;
00787 }
00788 var(index++)->print_val(out, "", false);
00789 fprintf(out, "}") ;
00790
00791 return index;
00792 }
00793 else {
00794 fprintf(out, "{") ;
00795
00796
00797
00798
00799
00800
00801 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00802 index = print_array(out, index, dims - 1, shape + 1);
00803 fprintf(out, ",") ;
00804 }
00805 index = print_array(out, index, dims - 1, shape + 1);
00806 fprintf(out, "}") ;
00807
00808 return index;
00809 }
00810 }
00811
00822 unsigned int
00823 Array::print_array(ostream &out, unsigned int index, unsigned int dims,
00824 unsigned int shape[])
00825 {
00826 if (dims == 1) {
00827 out << "{" ;
00828 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00829 var(index++)->print_val(out, "", false);
00830 out << ", " ;
00831 }
00832 var(index++)->print_val(out, "", false);
00833 out << "}" ;
00834
00835 return index;
00836 }
00837 else {
00838 out << "{" ;
00839
00840
00841
00842
00843
00844
00845 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00846 index = print_array(out, index, dims - 1, shape + 1);
00847 out << "," ;
00848 }
00849 index = print_array(out, index, dims - 1, shape + 1);
00850 out << "}" ;
00851
00852 return index;
00853 }
00854 }
00855
00856 void
00857 Array::print_val(FILE *out, string space, bool print_decl_p)
00858 {
00859
00860
00861
00862
00863
00864
00865 if (print_decl_p) {
00866 print_decl(out, space, false, false, false);
00867 fprintf(out, " = ") ;
00868 }
00869
00870 unsigned int *shape = new unsigned int[_shape.size()];
00871 unsigned int index = 0;
00872 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < _shape.size(); i++)
00873 shape[index++] = dimension_size(i, true);
00874
00875 print_array(out, 0, _shape.size(), shape);
00876
00877 delete [] shape; shape = 0;
00878
00879 if (print_decl_p) {
00880 fprintf(out, ";\n") ;
00881 }
00882 }
00883
00884 void
00885 Array::print_val(ostream &out, string space, bool print_decl_p)
00886 {
00887
00888
00889
00890
00891
00892
00893 if (print_decl_p) {
00894 print_decl(out, space, false, false, false);
00895 out << " = " ;
00896 }
00897
00898 unsigned int *shape = new unsigned int[dimensions(true)];
00899 unsigned int index = 0;
00900 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
00901 shape[index++] = dimension_size(i, true);
00902
00903 print_array(out, 0, dimensions(true), shape);
00904
00905 delete [] shape; shape = 0;
00906
00907 if (print_decl_p) {
00908 out << ";\n" ;
00909 }
00910 }
00911
00921 bool
00922 Array::check_semantics(string &msg, bool)
00923 {
00924 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
00925
00926 if (!sem)
00927 msg = "An array variable must have dimensions";
00928
00929 return sem;
00930 }
00931
00940 void
00941 Array::dump(ostream &strm) const
00942 {
00943 strm << DapIndent::LMarg << "Array::dump - ("
00944 << (void *)this << ")" << endl ;
00945 DapIndent::Indent() ;
00946 Vector::dump(strm) ;
00947 strm << DapIndent::LMarg << "shape:" << endl ;
00948 DapIndent::Indent() ;
00949 Dim_citer i = _shape.begin() ;
00950 Dim_citer ie = _shape.end() ;
00951 unsigned int dim_num = 0 ;
00952 for (; i != ie; i++) {
00953 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":"
00954 << endl ;
00955 DapIndent::Indent() ;
00956 strm << DapIndent::LMarg << "name: " << (*i).name << endl ;
00957 strm << DapIndent::LMarg << "size: " << (*i).size << endl ;
00958 strm << DapIndent::LMarg << "start: " << (*i).start << endl ;
00959 strm << DapIndent::LMarg << "stop: " << (*i).stop << endl ;
00960 strm << DapIndent::LMarg << "stride: " << (*i).stride << endl ;
00961 strm << DapIndent::LMarg << "constrained size: " << (*i).c_size
00962 << endl ;
00963 #if 0
00964 strm << DapIndent::LMarg << "selected: " << (*i).selected << endl ;
00965 #endif
00966 DapIndent::UnIndent() ;
00967 }
00968 DapIndent::UnIndent() ;
00969 DapIndent::UnIndent() ;
00970 }
00971
00972 }
00973